@glimt.dev/otel-browser 0.1.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/LICENSE +23 -0
- package/README.md +51 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +7 -0
- package/dist/types/exporters/config.d.ts +8 -0
- package/dist/types/exporters/exporter-logs-otlp-http-fetch.d.ts +14 -0
- package/dist/types/exporters/exporter-logs-otlp-proto-fetch.d.ts +14 -0
- package/dist/types/exporters/exporter-trace-otlp-http-fetch.d.ts +17 -0
- package/dist/types/exporters/exporter-trace-otlp-proto-fetch.d.ts +14 -0
- package/dist/types/exporters/logs-config.d.ts +1 -0
- package/dist/types/exporters/otlp-exporter-base.d.ts +1 -0
- package/dist/types/exporters/proto.d.ts +13 -0
- package/dist/types/exporters/trace-config.d.ts +1 -0
- package/dist/types/index.d.ts +160 -0
- package/dist/types/instrumentations/browser-error.d.ts +7 -0
- package/dist/types/instrumentations/console.d.ts +6 -0
- package/package.json +65 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-logs';
|
|
2
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
3
|
+
import type { OTLPExporterConfig } from './config';
|
|
4
|
+
/**
|
|
5
|
+
* OTLP exporter for logs over the `http/json` protocol. Browser-compatible.
|
|
6
|
+
*/
|
|
7
|
+
export declare class OTLPHttpJsonLogsExporter implements LogRecordExporter {
|
|
8
|
+
/** @ignore */
|
|
9
|
+
private readonly impl;
|
|
10
|
+
constructor(config?: OTLPExporterConfig, traceUrlForDerivation?: string);
|
|
11
|
+
export(records: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
|
|
12
|
+
shutdown(): Promise<void>;
|
|
13
|
+
forceFlush(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-logs';
|
|
2
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
3
|
+
import type { OTLPExporterConfig } from './config';
|
|
4
|
+
/**
|
|
5
|
+
* OTLP exporter for logs over the `http/protobuf` protocol. Browser-compatible.
|
|
6
|
+
*/
|
|
7
|
+
export declare class OTLPHttpProtoLogsExporter implements LogRecordExporter {
|
|
8
|
+
/** @ignore */
|
|
9
|
+
private readonly impl;
|
|
10
|
+
constructor(config?: OTLPExporterConfig, traceUrlForDerivation?: string);
|
|
11
|
+
export(records: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
|
|
12
|
+
shutdown(): Promise<void>;
|
|
13
|
+
forceFlush(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
2
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
3
|
+
import type { OTLPExporterConfig } from './config';
|
|
4
|
+
/**
|
|
5
|
+
* OTLP exporter for the `http/json` protocol. Compatible with browser environments.
|
|
6
|
+
*/
|
|
7
|
+
export declare class OTLPHttpJsonTraceExporter implements SpanExporter {
|
|
8
|
+
/** @ignore */
|
|
9
|
+
private readonly impl;
|
|
10
|
+
constructor(config?: OTLPExporterConfig);
|
|
11
|
+
/** See `SpanExporter#export()` */
|
|
12
|
+
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
13
|
+
/** See `SpanExporter#shutdown()` */
|
|
14
|
+
shutdown(): Promise<void>;
|
|
15
|
+
/** See `SpanExporter#forceFlush()` */
|
|
16
|
+
forceFlush(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
2
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
3
|
+
import type { OTLPExporterConfig } from './config';
|
|
4
|
+
/**
|
|
5
|
+
* OTLP exporter for the `http/protobuf` protocol. Compatible with browser environments.
|
|
6
|
+
*/
|
|
7
|
+
export declare class OTLPHttpProtoTraceExporter implements SpanExporter {
|
|
8
|
+
/** @ignore */
|
|
9
|
+
private readonly impl;
|
|
10
|
+
constructor(config?: OTLPExporterConfig);
|
|
11
|
+
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
12
|
+
shutdown(): Promise<void>;
|
|
13
|
+
forceFlush(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is constructed by:
|
|
3
|
+
*
|
|
4
|
+
* 1. Clone https://github.com/open-telemetry/opentelemetry-js.git
|
|
5
|
+
* 2. Run `protos:generate` in `experimental/packages/otlp-proto-exporter-base/`
|
|
6
|
+
* 3. Fork `experimental/packages/otlp-proto-exporter-base/src/generated/root.js` and inline all encode methods. Throw away the rest of the code.
|
|
7
|
+
*
|
|
8
|
+
* The OTLP protocol is very stable, so these steps would only need to be done rarely.
|
|
9
|
+
*/
|
|
10
|
+
import type { IExportTraceServiceRequest } from "@opentelemetry/otlp-transformer/build/src/trace/internal-types";
|
|
11
|
+
import { Writer } from "protobufjs/minimal";
|
|
12
|
+
export declare function encodeTraceServiceRequest(message: IExportTraceServiceRequest): Uint8Array;
|
|
13
|
+
export declare function ExportTraceServiceRequest_encode(message: IExportTraceServiceRequest, writer: Writer): Writer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { DiagLogLevel } from '@opentelemetry/api';
|
|
2
|
+
import { logs } from '@opentelemetry/api-logs';
|
|
3
|
+
/**
|
|
4
|
+
* OpenTelemetry semantic convention attribute names for end user identification.
|
|
5
|
+
* @see https://opentelemetry.io/docs/specs/semconv/attributes-registry/enduser/
|
|
6
|
+
*/
|
|
7
|
+
export declare const ENDUSER_ATTRIBUTES: {
|
|
8
|
+
/** Unique identifier of an end user in the system */
|
|
9
|
+
readonly ID: "enduser.id";
|
|
10
|
+
/** Pseudonymous identifier of an end user (privacy-preserving) */
|
|
11
|
+
readonly PSEUDO_ID: "enduser.pseudo.id";
|
|
12
|
+
/** User's email address (PII - use with caution) */
|
|
13
|
+
readonly EMAIL: "enduser.email";
|
|
14
|
+
/** User's role or permission scope */
|
|
15
|
+
readonly ROLE: "enduser.role";
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* User context for telemetry correlation.
|
|
19
|
+
* These values are added as span attributes following OpenTelemetry semantic conventions
|
|
20
|
+
* and propagated via W3C Baggage headers to downstream services.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const sdk = registerOTelBrowser({
|
|
25
|
+
* serviceName: 'my-app',
|
|
26
|
+
* user: { userId: 'user_123' }
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* // Later, update user context
|
|
30
|
+
* sdk.setUserContext({ userId: 'user_456', role: 'admin' })
|
|
31
|
+
*
|
|
32
|
+
* // Clear user context on logout
|
|
33
|
+
* sdk.setUserContext(null)
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export type UserContext = {
|
|
37
|
+
/**
|
|
38
|
+
* User ID - unique identifier of the end user (e.g., database ID, username).
|
|
39
|
+
* Set as `enduser.id` span attribute.
|
|
40
|
+
*/
|
|
41
|
+
userId?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Pseudonymous ID - privacy-preserving identifier (e.g., hashed user ID).
|
|
44
|
+
* Use this instead of userId when privacy is a concern.
|
|
45
|
+
* Set as `enduser.pseudo.id` span attribute.
|
|
46
|
+
*/
|
|
47
|
+
pseudoId?: string;
|
|
48
|
+
/**
|
|
49
|
+
* User's email address.
|
|
50
|
+
* ⚠️ Contains PII - only include if necessary and compliant with privacy regulations.
|
|
51
|
+
* Set as `enduser.email` span attribute.
|
|
52
|
+
*/
|
|
53
|
+
email?: string;
|
|
54
|
+
/**
|
|
55
|
+
* User's role or permission scope (e.g., 'admin', 'user', 'guest').
|
|
56
|
+
* Set as `enduser.role` span attribute.
|
|
57
|
+
*/
|
|
58
|
+
role?: string;
|
|
59
|
+
};
|
|
60
|
+
export type BrowserConfig = {
|
|
61
|
+
serviceName?: string;
|
|
62
|
+
attributes?: Record<string, unknown>;
|
|
63
|
+
instrumentations?: Array<'auto' | 'fetch' | 'xhr' | 'document' | 'user'>;
|
|
64
|
+
exporter?: 'http/protobuf' | 'http/json';
|
|
65
|
+
exporterUrl?: string;
|
|
66
|
+
exporterHeaders?: Record<string, string>;
|
|
67
|
+
credentials?: RequestCredentials;
|
|
68
|
+
logLevel?: keyof typeof DiagLogLevel;
|
|
69
|
+
includeUserAgent?: boolean;
|
|
70
|
+
fetch?: {
|
|
71
|
+
ignoreUrls?: (string | RegExp)[];
|
|
72
|
+
propagateContextUrls?: (string | RegExp)[];
|
|
73
|
+
dontPropagateContextUrls?: (string | RegExp)[];
|
|
74
|
+
resourceNameTemplate?: string;
|
|
75
|
+
attributesFromRequestHeaders?: Record<string, string>;
|
|
76
|
+
attributesFromResponseHeaders?: Record<string, string>;
|
|
77
|
+
};
|
|
78
|
+
logs?: {
|
|
79
|
+
exporter?: 'http/protobuf' | 'http/json';
|
|
80
|
+
exporterUrl?: string;
|
|
81
|
+
exporterHeaders?: Record<string, string>;
|
|
82
|
+
credentials?: RequestCredentials;
|
|
83
|
+
};
|
|
84
|
+
errors?: {
|
|
85
|
+
captureUnhandled?: boolean;
|
|
86
|
+
};
|
|
87
|
+
console?: {
|
|
88
|
+
enabled?: boolean;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Organisation ID for authenticated telemetry.
|
|
92
|
+
* When set together with publishableKey, telemetry will be sent with Basic authentication.
|
|
93
|
+
*/
|
|
94
|
+
organisationId?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Publishable key for authenticated telemetry.
|
|
97
|
+
* Used together with organisationId for Basic auth: base64(orgId:publishableKey)
|
|
98
|
+
*/
|
|
99
|
+
publishableKey?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Initial user context for telemetry.
|
|
102
|
+
* Can be updated later via `sdk.setUserContext()`.
|
|
103
|
+
* @see UserContext
|
|
104
|
+
*/
|
|
105
|
+
user?: UserContext;
|
|
106
|
+
};
|
|
107
|
+
export type BrowserSDK = {
|
|
108
|
+
/** Force flush all pending spans and logs */
|
|
109
|
+
forceFlush: () => Promise<void>;
|
|
110
|
+
/** Shutdown the SDK and flush remaining data */
|
|
111
|
+
shutdown: () => Promise<void>;
|
|
112
|
+
/** Get a logger instance for emitting structured logs */
|
|
113
|
+
getLogger: (name: string, version?: string) => ReturnType<typeof logs.getLogger>;
|
|
114
|
+
/**
|
|
115
|
+
* Set user context for telemetry correlation.
|
|
116
|
+
* Updates baggage for propagation and span attributes for all future spans.
|
|
117
|
+
*
|
|
118
|
+
* @param user - User context to set, or null to clear
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* // Set user after login
|
|
122
|
+
* sdk.setUserContext({ userId: 'user_123', role: 'admin' })
|
|
123
|
+
*
|
|
124
|
+
* // Clear user on logout
|
|
125
|
+
* sdk.setUserContext(null)
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
setUserContext: (user: UserContext | null) => void;
|
|
129
|
+
/**
|
|
130
|
+
* Get the current user context.
|
|
131
|
+
* Returns the user context from module state or extracted from active baggage.
|
|
132
|
+
*/
|
|
133
|
+
getUserContext: () => UserContext | null;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Registers the OpenTelemetry browser SDK with automatic user context propagation.
|
|
137
|
+
*
|
|
138
|
+
* This function initializes:
|
|
139
|
+
* - WebTracerProvider for span creation
|
|
140
|
+
* - W3C Trace Context and Baggage propagators
|
|
141
|
+
* - Automatic instrumentation (fetch, XHR, document load, user interactions)
|
|
142
|
+
* - OTLP export for traces and logs
|
|
143
|
+
* - User context propagation via baggage
|
|
144
|
+
*
|
|
145
|
+
* @param config - Configuration options
|
|
146
|
+
* @returns BrowserSDK instance with control methods
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* const sdk = registerOTelBrowser({
|
|
151
|
+
* serviceName: 'my-app',
|
|
152
|
+
* exporterUrl: 'https://otel-collector.example.com/v1/traces',
|
|
153
|
+
* user: { userId: 'user_123' }
|
|
154
|
+
* })
|
|
155
|
+
*
|
|
156
|
+
* // Update user context after authentication
|
|
157
|
+
* sdk.setUserContext({ userId: currentUser.id, role: currentUser.role })
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function registerOTelBrowser(config?: BrowserConfig): BrowserSDK;
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@glimt.dev/otel-browser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"description": "Minimal browser-only OpenTelemetry bootstrap for Glimt.dev",
|
|
9
|
+
"author": "Glimt.dev",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/types/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./cdn": {
|
|
19
|
+
"default": "./dist/cdn/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"types": "./dist/types/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@opentelemetry/api": "^1.9.0",
|
|
30
|
+
"@opentelemetry/api-logs": "^0.208.0",
|
|
31
|
+
"@opentelemetry/context-zone": "^2.2.0",
|
|
32
|
+
"@opentelemetry/core": "^2.2.0",
|
|
33
|
+
"@opentelemetry/instrumentation": "^0.208.0",
|
|
34
|
+
"@opentelemetry/instrumentation-document-load": "^0.54.0",
|
|
35
|
+
"@opentelemetry/instrumentation-fetch": "^0.208.0",
|
|
36
|
+
"@opentelemetry/instrumentation-user-interaction": "^0.53.0",
|
|
37
|
+
"@opentelemetry/instrumentation-xml-http-request": "^0.208.0",
|
|
38
|
+
"@opentelemetry/otlp-exporter-base": "^0.208.0",
|
|
39
|
+
"@opentelemetry/otlp-transformer": "^0.208.0",
|
|
40
|
+
"@opentelemetry/resources": "^2.2.0",
|
|
41
|
+
"@opentelemetry/sdk-logs": "^0.208.0",
|
|
42
|
+
"@opentelemetry/sdk-trace-base": "^2.2.0",
|
|
43
|
+
"@opentelemetry/sdk-trace-web": "^2.2.0",
|
|
44
|
+
"protobufjs": "^7.5.4"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "24.10.1",
|
|
48
|
+
"esbuild": "^0.27.1",
|
|
49
|
+
"jsdom": "^27.2.0",
|
|
50
|
+
"typescript": "^5.9.3",
|
|
51
|
+
"vitest": "4.0.15",
|
|
52
|
+
"typescript-config": "1.0.0"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.19.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "pnpm clean && tsc --noEmit false --declaration --emitDeclarationOnly --stripInternal --declarationDir dist/types src/index.ts && tsc -p tsconfig.json && node ./build.mjs",
|
|
59
|
+
"clean": "rm -rf dist",
|
|
60
|
+
"type-check": "tsc --noEmit",
|
|
61
|
+
"unit-test": "vitest --run",
|
|
62
|
+
"unit-test-watch": "vitest",
|
|
63
|
+
"size": "node -e \"const fs=require('fs');const zlib=require('zlib');const b=fs.readFileSync('dist/cdn/index.js');const gz=zlib.gzipSync(b,{level:9});const kb=(gz.length/1024).toFixed(1);const max=200;console.log('cdn gz',kb+'kb');if(gz.length>max*1024){console.error('Size limit exceeded:'+kb+'kb > '+max+'kb');process.exit(1)}\""
|
|
64
|
+
}
|
|
65
|
+
}
|