@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 CHANGED
@@ -1,51 +1,232 @@
1
1
  # @glimt.dev/otel-browser
2
2
 
3
- Minimal browser-only OpenTelemetry bootstrap for Glimt.dev.
3
+ OpenTelemetry for the browser. Works out of the box, highly configurable.
4
4
 
5
- - WebTracerProvider + ZoneContextManager
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
- pnpm add @glimt.dev/otel-browser
8
+ npm install @glimt.dev/otel-browser @opentelemetry/api @opentelemetry/api-logs
15
9
  ```
16
10
 
17
- ## Usage
11
+ ```ts
12
+ import { registerOTelBrowser } from '@glimt.dev/otel-browser'
18
13
 
19
- ```html
20
- <meta name="traceparent" content="00-ab42124a3c573678d4d8b21ba52df3bf-d21f7bc17caa5aba-01" />
21
- <script type="module">
22
- import { registerOTelBrowser } from '/dist/index.js'
23
- registerOTelBrowser({
24
- serviceName: 'my-web-app',
25
- includeUserAgent: false,
26
- // Traces
27
- exporterUrl: 'http://localhost:4318/v1/traces',
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
- exporterHeaders: { 'x-tenant-id': 'acme' },
30
- credentials: 'include',
31
- // Logs (default on). URL auto-derives to /v1/logs unless overridden
32
- logs: {
33
- exporter: 'http/protobuf', // or 'http/json'
34
- // exporterUrl: 'http://localhost:4318/v1/logs',
35
- },
36
- // Console instrumentation (optional)
37
- console: { enabled: true },
38
- })
39
- </script>
40
- ```
41
-
42
- ## CORS
43
- - Access-Control-Allow-Origin: * (or your origin)
44
- - Access-Control-Allow-Credentials: true (if using credentials)
45
- - Access-Control-Allow-Headers: content-type, traceparent, baggage, accept, authorization, x-tenant-id
46
- - Content-Type: application/x-protobuf (protobuf) or application/json (json)
47
-
48
- ## References
49
- - https://opentelemetry.io/docs/languages/js/getting-started/browser/
50
- - https://opentelemetry.io/docs/specs/semconv/resource/browser/
51
- - https://last9.io/blog/getting-started-with-opentelemetry-for-browser-monitoring/
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