Skip to content

Commit 03df4fb

Browse files
authored
Support default import from packages (#71)
1 parent dde9a10 commit 03df4fb

File tree

16 files changed

+433
-29
lines changed

16 files changed

+433
-29
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@pydantic/logfire-api': minor
3+
'@pydantic/logfire-browser': minor
4+
'@pydantic/logfire-cf-workers': minor
5+
'logfire': minor
6+
---
7+
8+
Add default export to packages. Using the default import is equivalent to the star import.

.claude/settings.local.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(cat:*)",
5+
"WebSearch",
6+
"Bash(npm run build)",
7+
"Bash(npm run build:*)",
8+
"Bash(npx changeset:*)"
9+
],
10+
"deny": [],
11+
"ask": []
12+
}
13+
}

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@ node_modules
22
packages/*/*.tgz
33
.turbo
44
.env
5-
CLAUDE.md
65
scratch/

CLAUDE.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
This is a monorepo for the **Pydantic Logfire JavaScript SDK** - an observability platform built on OpenTelemetry. The repository contains multiple packages for different JavaScript runtimes (Node.js, browsers, Cloudflare Workers, etc.) and usage examples.
8+
9+
## Repository Structure
10+
11+
This is an **npm workspace monorepo** managed with **Turborepo**:
12+
13+
- `packages/logfire` - Main Node.js SDK with automatic OpenTelemetry instrumentation
14+
- `packages/logfire-api` - Core API package that can be used standalone for manual tracing (no auto-instrumentation)
15+
- `packages/logfire-cf-workers` - Cloudflare Workers integration
16+
- `packages/logfire-browser` - Browser/web SDK
17+
- `packages/tooling-config` - Shared build and linting configuration
18+
- `examples/` - Working examples for various platforms (Express, Next.js, Deno, Cloudflare Workers, etc.)
19+
20+
## Core Architecture
21+
22+
### Package Relationships
23+
24+
- `logfire-api` is the base package that provides the core tracing API (`span`, `info`, `debug`, `error`, etc.) - it wraps OpenTelemetry's trace API with convenience methods
25+
- `logfire` (Node.js SDK) depends on `logfire-api` and adds automatic instrumentation via `@opentelemetry/auto-instrumentations-node`
26+
- `logfire-cf-workers` depends on `logfire-api` and adds Cloudflare Workers-specific instrumentation
27+
- `logfire-browser` depends on `logfire-api` and adds browser-specific instrumentation
28+
29+
### Key Concepts
30+
31+
**Trace API** (`logfire-api`):
32+
33+
- Provides convenience wrappers around OpenTelemetry spans with log levels (trace, debug, info, notice, warn, error, fatal)
34+
- Uses message template formatting with attribute extraction (see `formatter.ts`)
35+
- Uses ULID for trace ID generation (see `ULIDGenerator.ts`)
36+
- Supports attribute scrubbing for sensitive data (see `AttributeScrubber.ts`)
37+
38+
**Configuration** (`logfire` package):
39+
40+
- `configure()` function in `logfireConfig.ts` handles SDK initialization
41+
- Configuration can be provided programmatically or via environment variables:
42+
- `LOGFIRE_TOKEN` - Authentication token
43+
- `LOGFIRE_SERVICE_NAME` - Service name
44+
- `LOGFIRE_SERVICE_VERSION` - Service version
45+
- `LOGFIRE_ENVIRONMENT` - Deployment environment
46+
- `LOGFIRE_CONSOLE` - Enable console output
47+
- `LOGFIRE_SEND_TO_LOGFIRE` - Toggle sending to Logfire backend
48+
- `LOGFIRE_DISTRIBUTED_TRACING` - Enable/disable trace context propagation
49+
50+
**Span Creation**:
51+
52+
- `startSpan()` - Creates a span without setting it on context (manual mode)
53+
- `span()` - Creates a span, executes a callback, and auto-ends the span (recommended)
54+
- `info()`, `debug()`, `error()`, etc. - Convenience methods that create log-type spans
55+
- All spans use message templates with attribute extraction (e.g., `"User {user_id} logged in"`)
56+
57+
## Common Commands
58+
59+
### Development Setup
60+
61+
```bash
62+
npm install
63+
```
64+
65+
### Building
66+
67+
```bash
68+
# Build all packages
69+
npm run build
70+
71+
# Build in watch mode (for development)
72+
npm run dev
73+
```
74+
75+
### Testing
76+
77+
```bash
78+
# Run all tests
79+
npm run test
80+
81+
# Run tests for a specific package
82+
cd packages/logfire && npm test
83+
```
84+
85+
### Linting and Type Checking
86+
87+
```bash
88+
# Run both typecheck and lint across all packages
89+
npm run ci
90+
91+
# Just linting
92+
turbo lint
93+
94+
# Just type checking
95+
turbo typecheck
96+
```
97+
98+
### Working with Examples
99+
100+
Start an example to test changes:
101+
102+
```bash
103+
# Navigate to an example
104+
cd examples/node # or express, nextjs, cf-worker, etc.
105+
106+
# Install dependencies (if needed)
107+
npm install
108+
109+
# Run the example (check the example's package.json for scripts)
110+
npm start # or npm run dev
111+
```
112+
113+
### Changesets (Version Management)
114+
115+
This project uses Changesets for version management:
116+
117+
```bash
118+
# Add a changeset when making changes
119+
npm run changeset-add
120+
121+
# Publish packages (maintainers only)
122+
npm run release
123+
```
124+
125+
### Running a Single Test
126+
127+
```bash
128+
# Navigate to the package
129+
cd packages/logfire-api
130+
131+
# Run vitest with a filter
132+
npm test -- -t "test name pattern"
133+
```
134+
135+
## Development Workflow
136+
137+
1. Make changes in `packages/` source code
138+
2. Run `npm run build` to rebuild packages (or `npm run dev` for watch mode)
139+
3. Test changes using examples in `examples/` directory
140+
4. Run `npm run ci` to ensure linting and type checking pass
141+
5. Add a changeset if the changes warrant a version bump: `npm run changeset-add`
142+
143+
## Important Implementation Details
144+
145+
### Message Template Formatting
146+
147+
The `logfireFormatWithExtras()` function in `formatter.ts` extracts attributes from message templates. For example:
148+
149+
- `"User {user_id} logged in"` with `{ user_id: 123 }` becomes formatted message `"User 123 logged in"`
150+
- Extracted attributes are stored with special keys and used by the Logfire backend
151+
152+
### Attribute Scrubbing
153+
154+
Sensitive data scrubbing is handled in `AttributeScrubber.ts`. By default, it redacts common sensitive patterns (passwords, tokens, API keys, etc.) using regex patterns.
155+
156+
### Span Types
157+
158+
Spans have a `logfire.span_type` attribute:
159+
160+
- `"log"` - Point-in-time events (no child spans expected)
161+
- `"span"` - Duration-based traces (can have child spans)
162+
163+
### ID Generation
164+
165+
The SDK uses ULID (Universally Unique Lexicographically Sortable Identifier) for trace IDs by default, which provides time-ordered IDs for better performance.
166+
167+
### Build System
168+
169+
- Uses Vite for building packages (see individual `vite.config.ts` files)
170+
- Shared Vite config is in `packages/tooling-config/vite-config.ts`
171+
- Outputs both ESM (`.js`) and CommonJS (`.cjs`) formats with corresponding TypeScript definitions
172+
173+
## Testing Notes
174+
175+
- Tests use Vitest
176+
- Some packages have minimal tests (`--passWithNoTests` flag in package.json)
177+
- Test files are located alongside source files with `.test.ts` extension
178+
179+
## Node Version
180+
181+
The project requires **Node.js 22** (see `engines` in root package.json).
182+
183+
## Package Manager
184+
185+
Uses **npm 10.9.2** (enforced via `packageManager` field).
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Default export addition
2+
3+
I need to add a default export to all packages in this monorepo. The default export object should be the same as the star import. For example, the following two codes are equivalent:
4+
5+
```ts
6+
import * as logfire from 'logfire';
7+
```
8+
9+
```ts
10+
import logfire from 'logfire';
11+
```
12+
13+
Implement this for every package in the monorepo. Do not touch the examples.
14+
15+
## Details
16+
17+
Explicitly construct the default export object using the current imports. This should happen in the index.ts files.
18+
19+
## Testing
20+
21+
Test this feature by rebuilding the packages and verifying the resulting bundles.

examples/cf-tail-worker/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"deploy": "wrangler deploy",
77
"dev": "wrangler dev",
88
"start": "wrangler dev",
9-
"test": "vitest",
109
"cf-typegen": "wrangler types"
1110
},
1211
"devDependencies": {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"test": "turbo test",
1010
"release": "turbo build && npx @changesets/cli publish",
1111
"changeset-add": "npx @changesets/cli add",
12-
"ci": "turbo typecheck lint"
12+
"ci": "turbo typecheck lint test"
1313
},
1414
"keywords": [],
1515
"author": "",

packages/logfire-api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"typecheck": "tsc",
5252
"prepack": "cp ../../LICENSE .",
5353
"postpack": "rm LICENSE",
54-
"test": "vitest"
54+
"test": "vitest run"
5555
},
5656
"devDependencies": {
5757
"@opentelemetry/api": "^1.9.0",

packages/logfire-api/src/index.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { trace } from '@opentelemetry/api'
22
import { beforeEach, describe, expect, test, vi } from 'vitest'
33

4-
import { ATTRIBUTES_LEVEL_KEY, ATTRIBUTES_MESSAGE_TEMPLATE_KEY, ATTRIBUTES_SPAN_TYPE_KEY, ATTRIBUTES_TAGS_KEY } from './constants'
4+
import {
5+
ATTRIBUTES_LEVEL_KEY,
6+
ATTRIBUTES_MESSAGE_KEY,
7+
ATTRIBUTES_MESSAGE_TEMPLATE_KEY,
8+
ATTRIBUTES_SPAN_TYPE_KEY,
9+
ATTRIBUTES_TAGS_KEY,
10+
} from './constants'
511
import { info } from './index'
612

713
vi.mock('@opentelemetry/api', () => {
@@ -35,10 +41,11 @@ describe('info', () => {
3541

3642
// eslint-disable-next-line @typescript-eslint/unbound-method
3743
expect(tracer.startSpan).toBeCalledWith(
38-
'aha 1',
44+
'aha {i}',
3945
{
4046
attributes: {
4147
[ATTRIBUTES_LEVEL_KEY]: 9,
48+
[ATTRIBUTES_MESSAGE_KEY]: 'aha 1',
4249
[ATTRIBUTES_MESSAGE_TEMPLATE_KEY]: 'aha {i}',
4350
[ATTRIBUTES_SPAN_TYPE_KEY]: 'log',
4451
[ATTRIBUTES_TAGS_KEY]: [],
@@ -55,10 +62,11 @@ describe('info', () => {
5562

5663
// eslint-disable-next-line @typescript-eslint/unbound-method
5764
expect(tracer.startSpan).toBeCalledWith(
58-
'aha 1',
65+
'aha {i}',
5966
{
6067
attributes: {
6168
[ATTRIBUTES_LEVEL_KEY]: 9,
69+
[ATTRIBUTES_MESSAGE_KEY]: 'aha 1',
6270
[ATTRIBUTES_MESSAGE_TEMPLATE_KEY]: 'aha {i}',
6371
[ATTRIBUTES_SPAN_TYPE_KEY]: 'log',
6472
[ATTRIBUTES_TAGS_KEY]: [],

packages/logfire-api/src/index.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Span, SpanStatusCode, context as TheContextAPI, trace as TheTraceAPI } from '@opentelemetry/api'
33
import { ATTR_EXCEPTION_MESSAGE, ATTR_EXCEPTION_STACKTRACE } from '@opentelemetry/semantic-conventions'
44

5+
import * as AttributeScrubbingExports from './AttributeScrubber'
56
import {
67
ATTRIBUTES_LEVEL_KEY,
78
ATTRIBUTES_MESSAGE_KEY,
@@ -10,22 +11,16 @@ import {
1011
ATTRIBUTES_TAGS_KEY,
1112
} from './constants'
1213
import { logfireFormatWithExtras } from './formatter'
13-
import { logfireApiConfig, ScrubbingOptions, serializeAttributes } from './logfireApiConfig'
14+
import { logfireApiConfig, serializeAttributes } from './logfireApiConfig'
15+
import * as logfireApiConfigExports from './logfireApiConfig'
16+
import * as ULIDGeneratorExports from './ULIDGenerator'
1417

1518
export * from './AttributeScrubber'
1619
export { configureLogfireApi, logfireApiConfig, resolveBaseUrl, resolveSendToLogfire } from './logfireApiConfig'
17-
export type { ScrubbingOptions } from './logfireApiConfig'
20+
export type { LogfireApiConfig, LogfireApiConfigOptions, ScrubbingOptions } from './logfireApiConfig'
1821
export { serializeAttributes } from './serializeAttributes'
1922
export * from './ULIDGenerator'
2023

21-
export interface LogfireApiConfigOptions {
22-
otelScope?: string
23-
/**
24-
* Options for scrubbing sensitive data. Set to False to disable.
25-
*/
26-
scrubbing?: false | ScrubbingOptions
27-
}
28-
2924
export const Level = {
3025
Trace: 1 as const,
3126
Debug: 5 as const,
@@ -211,3 +206,25 @@ export function reportError(message: string, error: Error, extraAttributes: Reco
211206
span.setStatus({ code: SpanStatusCode.ERROR })
212207
span.end()
213208
}
209+
210+
const defaultExport = {
211+
...AttributeScrubbingExports,
212+
...ULIDGeneratorExports,
213+
...logfireApiConfigExports,
214+
215+
serializeAttributes,
216+
Level,
217+
startSpan,
218+
span,
219+
log,
220+
debug,
221+
info,
222+
trace,
223+
error,
224+
fatal,
225+
notice,
226+
warning,
227+
reportError,
228+
}
229+
230+
export default defaultExport

0 commit comments

Comments
 (0)