@sebspark/otel 0.1.0 → 0.2.1

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,10 +1,12 @@
1
1
  # `@sebspark/otel`
2
2
 
3
- Open Telemetry implementation of logging, tracing and metrics
3
+ Unified **OpenTelemetry** implementation for logging, tracing, and metrics — with environment detection, auto‑instrumentation, and clean console output for local development.
4
4
 
5
- ## Usage
5
+ ---
6
+
7
+ ## Use logger, tracer, and metrics
6
8
 
7
- Run:
9
+ Install:
8
10
 
9
11
  ```sh
10
12
  npm install @sebspark/otel
@@ -14,145 +16,206 @@ yarn add @sebspark/otel
14
16
  pnpm add @sebspark/otel
15
17
  ```
16
18
 
17
- **Initialization and Context Detection**
18
-
19
- The **OpenTelemetry SDK** is automatically initialized when you import `@sebspark/otel`.
19
+ ### Initialization
20
20
 
21
- **This should be the first import in your application.**
21
+ **This must be the first import in your application:**
22
22
 
23
23
  ```ts
24
24
  import '@sebspark/otel'
25
25
  ```
26
26
 
27
- This setup:
27
+ Automatically:
28
28
 
29
- - Uses **OpenTelemetry auto-instrumentations** to trace supported libraries
30
- - **HTTP**, **gRPC**, **Redis**, **PostgreSQL** etc.
31
- - **Auto-detects environment metadata**, including:
32
- - **GCP** service name (e.g., **Cloud Run**, **GKE**, **GCE**, etc.)
33
- - Instance and zone/region
34
- - Enables **W3C Trace Context** propagation across async operations and network boundaries
35
- - Automatically links logs with `trace_id` and `span_id` inside active spans
36
- - Supports clean shutdown via `SIGTERM` (e.g. **Cloud Run**, **Kubernetes**)
29
+ - Initializes the OpenTelemetry SDK
30
+ - Auto‑instruments common libraries like **HTTP**, **gRPC**, **Redis**, **PostgreSQL**
31
+ - Enables W3C Trace Context propagation
32
+ - Detects environment and adds `resourceAttributes`
33
+ - Links logs with `trace_id` and `span_id`
34
+ - Handles graceful shutdown on `SIGTERM`
35
+
36
+ ---
37
37
 
38
- In **GCP** environments, this ensures that traces are correlated across **Cloud Logging**, **Cloud Trace**, and **Cloud Monitoring** without extra setup.
38
+ ### Logging
39
39
 
40
- #### Environment-aware attributes
40
+ ```ts
41
+ import { getLogger } from '@sebspark/otel'
41
42
 
42
- The following values are detected and attached as `resourceAttributes`:
43
+ const logger = getLogger()
43
44
 
44
- **Env Variable** | **Attribute Key** | **Description**
45
- ------------------------|-------------------------|-------------------------------
46
- OTEL_SERVICE_NAME | service.name | Overrides service name
47
- OTEL_SERVICE_VERSION | service.version | Version of the current service
48
- K_SERVICE | cloud.run.service | Cloud Run service name
49
- K_REVISION | cloud.run.revision | Cloud Run revision
50
- K_CONFIGURATION | cloud.run.configuration | Cloud Run config
51
- POD_NAME | k8s.pod_name | Kubernetes pod name
52
- POD_NAMESPACE | k8s.namespace_name | Kubernetes namespace
53
- KUBERNETES_SERVICE_HOST | cloud.orchestrator | Set to 'kubernetes' if present
54
- GCP_PROJECT | cloud.account.id | GCP project ID
55
- CLOUD_PROVIDER | cloud.provider | e.g. 'gcp', 'aws', etc.
45
+ logger.debug('debug message')
46
+ logger.info('something happened')
47
+ logger.warn('almost bad')
48
+ logger.error('very bad')
49
+ ```
50
+
51
+ Logs inside active spans automatically include:
52
+ - `trace_id`
53
+ - `span_id`
54
+ - `service.name`
55
+ - `service.version`
56
56
 
57
57
  ---
58
58
 
59
- ### Logging
59
+ ### Tracing
60
60
 
61
- The logger automatically includes `trace_id` and `span_id` if available.
61
+ ```ts
62
+ import { getTracer } from '@sebspark/otel'
63
+
64
+ const tracer = getTracer()
65
+
66
+ await tracer.withTrace('trace.name', async (span) => {
67
+ span.setAttribute('user.id', '123')
68
+ // do something...
69
+ })
70
+ ```
71
+
72
+ If the callback throws:
73
+ - Span is marked as `ERROR`
74
+ - Exception is recorded
75
+ - Span is ended properly
76
+
77
+ Synchronous variant:
62
78
 
63
79
  ```ts
64
- import { getLogger } from '@sebspark/otel'
80
+ tracer.withTraceSync('init.config', (span) => {
81
+ // synchronous code
82
+ span.setStatus({ code: SpanStatusCode.OK })
83
+ })
84
+ ```
65
85
 
66
- const logger = getLogger()
86
+ Nested:
87
+
88
+ ```ts
89
+ await tracer.withTrace('trace.name', async (span1) => {
90
+ span1.setAttribute('user.id', '123')
91
+
92
+ await tracer.withTrace('trace.name2', span1, async (span2) => {
93
+ // do stuff
94
+ })
95
+ })
96
+ ```
97
+
98
+ Manual span usage:
67
99
 
68
- logger.debug('message')
69
- logger.info('message')
70
- logger.warn('message')
71
- logger.error('message')
100
+ ```ts
101
+ const span = tracer.startSpan('manual-operation')
102
+ span.setAttribute('manual', true)
103
+ // work...
104
+ span.end()
72
105
  ```
73
106
 
74
107
  ---
75
108
 
76
109
  ### Metrics
77
110
 
78
- You can use the metrics API to create and export custom application-level metrics.
79
-
80
111
  ```ts
81
112
  import { getMeter } from '@sebspark/otel'
82
113
 
83
114
  const meter = getMeter()
84
115
 
85
116
  const counter = meter.createCounter('http_requests_total', {
86
- description: 'Total number of HTTP requests'
117
+ description: 'Total number of HTTP requests',
87
118
  })
88
119
 
89
120
  counter.add(1, {
90
121
  route: '/api/hello',
91
- method: 'GET'
122
+ method: 'GET',
92
123
  })
93
124
  ```
94
125
 
95
126
  ---
96
127
 
97
- ### Tracing
128
+ ## Configure for cloud use (with OpenTelemetry Collector)
98
129
 
99
- The tracer helps you capture **distributed traces** across services and automatically links logs with `trace_id` and `span_id` when called inside a span context.
130
+ When deployed to **Cloud Run**, **GKE**, or other cloud environments, telemetry automatically exports to your configured **OpenTelemetry Collector**.
100
131
 
101
- #### Get a tracer
132
+ Set these environment variables:
102
133
 
103
- ```ts
104
- import { getTracer } from '@sebspark/otel'
134
+ | Variable | Description | Example |
135
+ |-------------------------------|---------------------------------|-------------------------------|
136
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Collector endpoint | `http://otel-collector:4318` |
137
+ | `OTEL_SERVICE_NAME` | Override detected service name | `trade-api` |
138
+ | `OTEL_SERVICE_VERSION` | Version of this instance | `1.2.3` |
105
139
 
106
- const tracer = getTracer()
107
- ```
140
+ Additional GCP/Kubernetes context is auto‑detected:
108
141
 
109
- Optionally override the service name:
142
+ | Env Variable | Attribute Key | Example |
143
+ |---------------------------|-----------------------|-------------------|
144
+ | `K_SERVICE` | `cloud.run.service` | `trade-api` |
145
+ | `K_REVISION` | `cloud.run.revision` | `trade-api-v15` |
146
+ | `POD_NAME` | `k8s.pod_name` | `api-1234` |
147
+ | `KUBERNETES_SERVICE_HOST` | `cloud.orchestrator` | `kubernetes` |
148
+ | `GCP_PROJECT` | `cloud.account.id` | `my-gcp-project` |
110
149
 
111
- ```ts
112
- const tracer = getTracer('my-custom-service')
113
- ```
150
+ ---
114
151
 
115
- #### Automatically wrap logic in a span
152
+ ## Configure for local use (dev logging)
116
153
 
117
- **Async**
154
+ In development, `@sebspark/otel` outputs human-readable **logs**, **spans**, and **metrics** directly to the console.
118
155
 
119
- ```ts
120
- await tracer.withTrace('trace name', async (span) => {
121
- // span is active here
122
- span.setAttribute('custom.attribute', 'value')
123
- })
124
- ```
156
+ ---
157
+
158
+ ### Environment variables
159
+
160
+ | Variable | Affects | Values | Description |
161
+ |----------------|---------|------------------------------------------|-----------------------------------------------------------------------------------------|
162
+ | `LOG_LEVEL` | Logs | `debug,info,warn,error` | Minimum severity to print |
163
+ | `SPAN_LEVEL` | Traces | `OK`, `ERROR`, `UNSET` (comma-separated) | Only trees containing **at least one** span with one of these statuses will be printed |
164
+ | `METRIC_FILTER`| Metrics | Glob patterns (comma-separated) | Only metrics matching any of the patterns are shown |
165
+
166
+ ---
125
167
 
126
- **Sync**
168
+ ### Logs
169
+
170
+ Filtered by `LOG_LEVEL`:
171
+
172
+ ```sh
173
+ LOG_LEVEL=warn yarn dev
174
+ ```
127
175
 
128
176
  ```ts
129
- tracer.withTraceSync('init.config', () => {
130
- // synchronous logic
131
- })
177
+ ⚠️ [trade-api@1.2.3] GET /orders/limit-exceeded WARN trace_id=abc123 span_id=def456
178
+ [trade-api@1.2.3] Order validation failed ERROR trace_id=abc123 span_id=def456
132
179
  ```
133
180
 
134
- **Errors**
181
+ ---
135
182
 
136
- If an error is thrown during an auto traced function:
183
+ ### Spans
137
184
 
138
- - The span is marked with `SpanStatusCode.ERROR`
139
- - The error is recorded via `span.recordException()`
140
- - The span is always ended correctly
185
+ Filtered by `SPAN_LEVEL` — the entire span **tree** is printed only if **at least one** span in the tree matches the status.
141
186
 
142
- #### Manual control
187
+ ```sh
188
+ SPAN_LEVEL=ERROR yarn dev
189
+ ```
143
190
 
144
191
  ```ts
145
- const span = tracer.startSpan('manual-task')
146
- span.setAttribute('manual', true)
147
- // do work...
148
- span.end()
192
+ [test@1.0.0] 12:00:00.000
193
+ └─ express ████████████████████ OK (0 ms–1.00 s)
194
+ └─ middleware:auth ███████ OK (0 ms–0.20 s)
195
+ └─ handler:getUser ████████████████████ ERROR (0 ms–1.00 s)
196
+ ```
197
+
198
+ ```sh
199
+ SPAN_LEVEL=OK,ERROR yarn dev
149
200
  ```
150
201
 
151
- #### Nested span attributes
202
+ ```ts
203
+ [test@1.0.0] 12:01:00.000
204
+ └─ express ████████████████████ OK (0 ms–1.00 s)
205
+ └─ middleware:auth ███████ OK (0 ms–0.20 s)
206
+ ```
152
207
 
153
- Any span created via `withTrace` or `withTraceSync` will automatically inherit these attributes from the parent (if present):
208
+ ---
154
209
 
155
- - `parent_service_name`
156
- - `parent_span_name`
210
+ ### 📈 Metrics
157
211
 
158
- This makes cross‑service tracing easier to follow in tools like **Google Cloud Trace**, **Jaeger** or **Grafana Tempo**.
212
+ Filtered by `METRIC_FILTER`:
213
+
214
+ ```sh
215
+ METRIC_FILTER=http.*,db.* yarn dev
216
+ ```
217
+
218
+ ```ts
219
+ 📊 [trade-api@1.2.3] 12:00:00.000 📊 express http.server.duration 240ms {route=/api/hello method=GET}
220
+ 📊 [trade-api@1.2.3] 12:00:01.000 📊 pg db.query.count 1 {query=SELECT * FROM users}
221
+ ```
package/dist/index.d.mts CHANGED
@@ -13,19 +13,23 @@ declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
13
13
  emergency: (msg: string, attrs?: Attrs) => void;
14
14
  };
15
15
 
16
- declare function getMeter(serviceOverride?: string): _opentelemetry_api.Meter;
16
+ declare function getMeter(componentNameOverride?: string): _opentelemetry_api.Meter;
17
17
 
18
18
  type OtelTracer = ReturnType<typeof trace.getTracer>;
19
19
  type Span = ReturnType<OtelTracer['startSpan']>;
20
- type Func<T> = (span?: Span) => Promise<T> | T;
21
- type SyncFunc<T> = (span?: Span) => T;
20
+ type Func<T> = (span: Span) => Promise<T> | T;
21
+ type SyncFunc<T> = (span: Span) => T;
22
22
  type WithTrace = {
23
23
  <T>(name: string, fn: Func<T>): Promise<T>;
24
24
  <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>;
25
+ <T>(name: string, parent: Span, fn: Func<T>): Promise<T>;
26
+ <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>;
25
27
  };
26
28
  type WithTraceSync = {
27
29
  <T>(name: string, fn: SyncFunc<T>): T;
28
30
  <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T;
31
+ <T>(name: string, parent: Span, fn: SyncFunc<T>): T;
32
+ <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T;
29
33
  };
30
34
  /**
31
35
  * Extended tracer with helper methods for span-wrapped execution
@@ -41,6 +45,6 @@ interface Tracer extends OtelTracer {
41
45
  * @param serviceOverride - Optional override for service name
42
46
  * @returns Tracer with helpers
43
47
  */
44
- declare function getTracer(serviceOverride?: string): Tracer;
48
+ declare function getTracer(componentNameOverride?: string): Tracer;
45
49
 
46
50
  export { getLogger, getMeter, getTracer };
package/dist/index.d.ts CHANGED
@@ -13,19 +13,23 @@ declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
13
13
  emergency: (msg: string, attrs?: Attrs) => void;
14
14
  };
15
15
 
16
- declare function getMeter(serviceOverride?: string): _opentelemetry_api.Meter;
16
+ declare function getMeter(componentNameOverride?: string): _opentelemetry_api.Meter;
17
17
 
18
18
  type OtelTracer = ReturnType<typeof trace.getTracer>;
19
19
  type Span = ReturnType<OtelTracer['startSpan']>;
20
- type Func<T> = (span?: Span) => Promise<T> | T;
21
- type SyncFunc<T> = (span?: Span) => T;
20
+ type Func<T> = (span: Span) => Promise<T> | T;
21
+ type SyncFunc<T> = (span: Span) => T;
22
22
  type WithTrace = {
23
23
  <T>(name: string, fn: Func<T>): Promise<T>;
24
24
  <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>;
25
+ <T>(name: string, parent: Span, fn: Func<T>): Promise<T>;
26
+ <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>;
25
27
  };
26
28
  type WithTraceSync = {
27
29
  <T>(name: string, fn: SyncFunc<T>): T;
28
30
  <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T;
31
+ <T>(name: string, parent: Span, fn: SyncFunc<T>): T;
32
+ <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T;
29
33
  };
30
34
  /**
31
35
  * Extended tracer with helper methods for span-wrapped execution
@@ -41,6 +45,6 @@ interface Tracer extends OtelTracer {
41
45
  * @param serviceOverride - Optional override for service name
42
46
  * @returns Tracer with helpers
43
47
  */
44
- declare function getTracer(serviceOverride?: string): Tracer;
48
+ declare function getTracer(componentNameOverride?: string): Tracer;
45
49
 
46
50
  export { getLogger, getMeter, getTracer };