@glimt.dev/otel-browser 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -42
- package/dist/index.js +23 -2
- package/dist/index.js.map +4 -4
- package/dist/types/index.d.ts +27 -7
- package/package.json +11 -5
package/README.md
CHANGED
|
@@ -1,51 +1,232 @@
|
|
|
1
1
|
# @glimt.dev/otel-browser
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
OpenTelemetry for the browser. Works out of the box, highly configurable.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- W3C tracecontext + baggage propagators
|
|
7
|
-
- Instrumentations: document-load, user-interaction, XHR, fetch, browser-errors (logs)
|
|
8
|
-
- OTLP HTTP export for traces and logs (protobuf default; JSON optional)
|
|
9
|
-
- Browser resource attributes; user_agent is opt-in
|
|
10
|
-
|
|
11
|
-
## Install
|
|
5
|
+
## Quick Start (3 lines)
|
|
12
6
|
|
|
13
7
|
```bash
|
|
14
|
-
|
|
8
|
+
npm install @glimt.dev/otel-browser @opentelemetry/api @opentelemetry/api-logs
|
|
15
9
|
```
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
```ts
|
|
12
|
+
import { registerOTelBrowser } from '@glimt.dev/otel-browser'
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
registerOTelBrowser({ serviceName: 'my-web-app' })
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Done. Traces go to `https://ingest.glimt.dev/v1/traces`, logs to `/v1/logs`.
|
|
18
|
+
|
|
19
|
+
### Local Development
|
|
20
|
+
|
|
21
|
+
For local development with a local collector:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
registerOTelBrowser({
|
|
25
|
+
serviceName: 'my-web-app',
|
|
26
|
+
exporterUrl: 'http://localhost:4318',
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Production: Glimt.dev Ingest
|
|
31
|
+
|
|
32
|
+
For production with Glimt authentication:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
registerOTelBrowser({
|
|
36
|
+
serviceName: 'my-web-app',
|
|
37
|
+
// exporterUrl defaults to https://ingest.glimt.dev
|
|
38
|
+
organisationId: 'your-org-id',
|
|
39
|
+
publishableKey: 'your-publishable-key',
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Full Example (all options)
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { registerOTelBrowser } from '@glimt.dev/otel-browser'
|
|
49
|
+
|
|
50
|
+
const sdk = registerOTelBrowser({
|
|
51
|
+
// Identity
|
|
52
|
+
serviceName: 'my-web-app',
|
|
53
|
+
|
|
54
|
+
// Glimt auth
|
|
55
|
+
organisationId: 'org_xxx',
|
|
56
|
+
publishableKey: 'pk_xxx',
|
|
57
|
+
|
|
58
|
+
// Release metadata (CRITICAL for source mapping)
|
|
59
|
+
release: {
|
|
60
|
+
commit: process.env.NEXT_PUBLIC_COMMIT_SHA, // or 'abc1234'
|
|
61
|
+
branch: process.env.NEXT_PUBLIC_COMMIT_REF, // or 'main'
|
|
62
|
+
version: '1.0.0',
|
|
63
|
+
environment: 'production',
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// Export - base URL, SDK derives /v1/traces and /v1/logs
|
|
67
|
+
exporterUrl: 'https://ingest.glimt.dev',
|
|
68
|
+
exporter: 'http/protobuf', // or 'http/json'
|
|
69
|
+
exporterHeaders: { 'x-tenant-id': 'acme' },
|
|
70
|
+
credentials: 'include', // for CORS
|
|
71
|
+
|
|
72
|
+
// Logs (auto-derived to /v1/logs)
|
|
73
|
+
logs: {
|
|
28
74
|
exporter: 'http/protobuf',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// Instrumentations
|
|
78
|
+
instrumentations: ['auto'], // document-load, user-interaction, xhr, fetch
|
|
79
|
+
fetch: {
|
|
80
|
+
ignoreUrls: [/\/healthz?$/, /analytics\.js$/],
|
|
81
|
+
propagateContextUrls: [/^https:\/\/api\.myapp\.com/],
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// Capture
|
|
85
|
+
captureUnhandledErrors: true, // window.onerror, unhandledrejection (default: true)
|
|
86
|
+
captureConsoleLogs: true, // console.* as OTLP logs (default: false)
|
|
87
|
+
includeUserAgent: false, // privacy default
|
|
88
|
+
|
|
89
|
+
// Initial user context
|
|
90
|
+
user: { userId: 'user_123', role: 'admin' },
|
|
91
|
+
|
|
92
|
+
// Debug
|
|
93
|
+
logLevel: 'DEBUG',
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Update user on login/logout
|
|
97
|
+
sdk.setUserContext({ userId: 'user_456' })
|
|
98
|
+
sdk.setUserContext(null)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Environment Variables (via Build Tools)
|
|
104
|
+
|
|
105
|
+
Browsers don't have runtime environment variables, but you can inject them at build time using your bundler:
|
|
106
|
+
|
|
107
|
+
**Next.js (`next.config.mjs`):**
|
|
108
|
+
```js
|
|
109
|
+
// Automatically available as process.env.NEXT_PUBLIC_*
|
|
110
|
+
// Set in .env or CI environment
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Vite (`vite.config.ts`):**
|
|
114
|
+
```ts
|
|
115
|
+
export default defineConfig({
|
|
116
|
+
define: {
|
|
117
|
+
'import.meta.env.VITE_OTEL_ENDPOINT': JSON.stringify(process.env.OTEL_EXPORTER_OTLP_ENDPOINT),
|
|
118
|
+
'import.meta.env.VITE_COMMIT_SHA': JSON.stringify(process.env.COMMIT_SHA),
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Webpack:**
|
|
124
|
+
```js
|
|
125
|
+
new webpack.DefinePlugin({
|
|
126
|
+
'process.env.OTEL_ENDPOINT': JSON.stringify(process.env.OTEL_EXPORTER_OTLP_ENDPOINT),
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## React / Next.js Integration
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
'use client'
|
|
136
|
+
import { useEffect, useRef } from 'react'
|
|
137
|
+
import { registerOTelBrowser, type BrowserSDK } from '@glimt.dev/otel-browser'
|
|
138
|
+
|
|
139
|
+
export function TelemetryProvider({ userId }: { userId?: string }) {
|
|
140
|
+
const sdk = useRef<BrowserSDK | null>(null)
|
|
141
|
+
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
sdk.current = registerOTelBrowser({
|
|
144
|
+
serviceName: process.env.NEXT_PUBLIC_OTEL_SERVICE_NAME!,
|
|
145
|
+
exporterUrl: process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
146
|
+
user: userId ? { userId } : undefined,
|
|
147
|
+
release: {
|
|
148
|
+
commit: process.env.NEXT_PUBLIC_COMMIT_SHA || process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
|
|
149
|
+
branch: process.env.NEXT_PUBLIC_COMMIT_REF || process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF,
|
|
150
|
+
environment: process.env.NEXT_PUBLIC_VERCEL_ENV,
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
}, [])
|
|
154
|
+
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
sdk.current?.setUserContext(userId ? { userId } : null)
|
|
157
|
+
}, [userId])
|
|
158
|
+
|
|
159
|
+
return null
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// app/layout.tsx
|
|
165
|
+
export default async function RootLayout({ children }) {
|
|
166
|
+
const user = await getCurrentUser()
|
|
167
|
+
return (
|
|
168
|
+
<html>
|
|
169
|
+
<body>
|
|
170
|
+
<TelemetryProvider userId={user?.id} />
|
|
171
|
+
{children}
|
|
172
|
+
</body>
|
|
173
|
+
</html>
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Server-side traceparent
|
|
181
|
+
|
|
182
|
+
Inject in your HTML to correlate browser ↔ server:
|
|
183
|
+
|
|
184
|
+
```html
|
|
185
|
+
<meta name="traceparent" content="00-abc123...-def456...-01" />
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The SDK picks this up automatically as the parent span.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## CORS Requirements
|
|
193
|
+
|
|
194
|
+
Your collector must allow:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
Access-Control-Allow-Origin: * (or your origin)
|
|
198
|
+
Access-Control-Allow-Headers: content-type, traceparent, baggage, authorization
|
|
199
|
+
Access-Control-Allow-Credentials: true (if using credentials)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Defaults
|
|
205
|
+
|
|
206
|
+
| Feature | Default |
|
|
207
|
+
|---------|---------|
|
|
208
|
+
| Trace exporter | `http/protobuf` → `https://ingest.glimt.dev/v1/traces` |
|
|
209
|
+
| Log exporter | `http/protobuf` → `https://ingest.glimt.dev/v1/logs` |
|
|
210
|
+
| Instrumentations | document-load, user-interaction, xhr, fetch |
|
|
211
|
+
| Error capture | `window.onerror`, `unhandledrejection` |
|
|
212
|
+
| User agent | NOT included (privacy) |
|
|
213
|
+
| Console capture | OFF |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## User Context Attributes
|
|
218
|
+
|
|
219
|
+
When you call `sdk.setUserContext()`, these attributes are added to all spans:
|
|
220
|
+
|
|
221
|
+
| Attribute | Description |
|
|
222
|
+
|-----------|-------------|
|
|
223
|
+
| `enduser.id` | Primary user identifier |
|
|
224
|
+
| `enduser.pseudo.id` | Privacy-preserving hash |
|
|
225
|
+
| `enduser.email` | PII, use with caution |
|
|
226
|
+
| `enduser.role` | Permission scope |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT
|