autotel-backends 2.12.33 → 2.12.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel-backends",
3
- "version": "2.12.33",
3
+ "version": "2.12.34",
4
4
  "description": "Vendor backend configurations for Autotel (Honeycomb, Datadog, etc.)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,7 +35,6 @@
35
35
  },
36
36
  "files": [
37
37
  "dist",
38
- "src",
39
38
  "README.md",
40
39
  "skills"
41
40
  ],
@@ -59,7 +58,7 @@
59
58
  "dependencies": {
60
59
  "@opentelemetry/exporter-logs-otlp-http": ">=0.218.0",
61
60
  "@opentelemetry/sdk-logs": ">=0.218.0",
62
- "autotel": "4.1.0"
61
+ "autotel": "4.2.0"
63
62
  },
64
63
  "peerDependencies": {
65
64
  "@opentelemetry/exporter-metrics-otlp-http": ">=0.218.0",
@@ -1,232 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
- import { createDatadogConfig } from './datadog';
3
-
4
- describe('createDatadogConfig()', () => {
5
- describe('validation', () => {
6
- it('should throw if apiKey is missing for direct ingestion', () => {
7
- expect(() => {
8
- createDatadogConfig({
9
- service: 'test-service',
10
- });
11
- }).toThrow('Datadog API key is required for direct cloud ingestion');
12
- });
13
-
14
- it('should not throw if apiKey is missing when useAgent is true', () => {
15
- expect(() => {
16
- createDatadogConfig({
17
- service: 'test-service',
18
- useAgent: true,
19
- });
20
- }).not.toThrow();
21
- });
22
- });
23
-
24
- describe('direct cloud ingestion', () => {
25
- it('should return config with correct endpoint and headers', () => {
26
- const config = createDatadogConfig({
27
- apiKey: 'test-api-key',
28
- service: 'my-service',
29
- });
30
-
31
- expect(config).toMatchObject({
32
- service: 'my-service',
33
- endpoint: 'https://otlp.datadoghq.com',
34
- headers: 'dd-api-key=test-api-key',
35
- });
36
- });
37
-
38
- it('should use correct endpoint for EU site', () => {
39
- const config = createDatadogConfig({
40
- apiKey: 'test-api-key',
41
- service: 'my-service',
42
- site: 'datadoghq.eu',
43
- });
44
-
45
- expect(config.endpoint).toBe('https://otlp.datadoghq.eu');
46
- });
47
-
48
- it('should include environment and version when specified', () => {
49
- const config = createDatadogConfig({
50
- apiKey: 'test-api-key',
51
- service: 'my-service',
52
- environment: 'production',
53
- version: '1.0.0',
54
- });
55
-
56
- expect(config.environment).toBe('production');
57
- expect(config.version).toBe('1.0.0');
58
- });
59
- });
60
-
61
- describe('agent mode', () => {
62
- it('should use agent endpoint when useAgent is true', () => {
63
- const config = createDatadogConfig({
64
- service: 'my-service',
65
- useAgent: true,
66
- });
67
-
68
- expect(config.endpoint).toBe('http://localhost:4318');
69
- expect(config.headers).toBeUndefined();
70
- });
71
-
72
- it('should use custom agent host and port', () => {
73
- const config = createDatadogConfig({
74
- service: 'my-service',
75
- useAgent: true,
76
- agentHost: 'dd-agent',
77
- agentPort: 4319,
78
- });
79
-
80
- expect(config.endpoint).toBe('http://dd-agent:4319');
81
- });
82
- });
83
-
84
- describe('enableLogs env var configuration', () => {
85
- const originalEnv = { ...process.env };
86
-
87
- beforeEach(() => {
88
- // Clear env vars before each test
89
- delete process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT;
90
- delete process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL;
91
- delete process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS;
92
- delete process.env.OTEL_RESOURCE_ATTRIBUTES;
93
- });
94
-
95
- afterEach(() => {
96
- // Restore original env
97
- process.env = { ...originalEnv };
98
- });
99
-
100
- it('sets OTLP logs env vars for direct ingestion', () => {
101
- // Mock the peer dependencies to avoid the error
102
- vi.mock('@opentelemetry/sdk-logs', () => ({
103
- BatchLogRecordProcessor: vi.fn().mockImplementation(() => ({})),
104
- }));
105
- vi.mock('@opentelemetry/exporter-logs-otlp-http', () => ({
106
- OTLPLogExporter: vi.fn().mockImplementation(() => ({})),
107
- }));
108
-
109
- try {
110
- createDatadogConfig({
111
- apiKey: 'test-key',
112
- site: 'datadoghq.eu',
113
- service: 'test-service',
114
- environment: 'production',
115
- version: '1.0.0',
116
- enableLogs: true,
117
- });
118
- } catch {
119
- // Ignore peer dependency error - we just want to test env var setting
120
- }
121
-
122
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBe(
123
- 'https://otlp.datadoghq.eu/v1/logs',
124
- );
125
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBe(
126
- 'http/protobuf',
127
- );
128
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBe(
129
- 'dd-api-key=test-key',
130
- );
131
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toContain(
132
- 'service.name=test-service',
133
- );
134
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toContain(
135
- 'deployment.environment=production',
136
- );
137
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toContain(
138
- 'service.version=1.0.0',
139
- );
140
- });
141
-
142
- it('sets OTLP logs env vars for agent mode (no api key header)', () => {
143
- try {
144
- createDatadogConfig({
145
- service: 'test-service',
146
- useAgent: true,
147
- agentHost: 'dd-agent',
148
- agentPort: 4318,
149
- enableLogs: true,
150
- });
151
- } catch {
152
- // Ignore peer dependency error
153
- }
154
-
155
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBe(
156
- 'http://dd-agent:4318/v1/logs',
157
- );
158
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBe(
159
- 'http/protobuf',
160
- );
161
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBeUndefined();
162
- });
163
-
164
- it('does not override existing env vars', () => {
165
- process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT =
166
- 'http://custom:4318/v1/logs';
167
- process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'grpc';
168
- process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'custom-header=value';
169
- process.env.OTEL_RESOURCE_ATTRIBUTES = 'custom.attr=value';
170
-
171
- try {
172
- createDatadogConfig({
173
- apiKey: 'test-key',
174
- service: 'test-service',
175
- enableLogs: true,
176
- });
177
- } catch {
178
- // Ignore peer dependency error
179
- }
180
-
181
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBe(
182
- 'http://custom:4318/v1/logs',
183
- );
184
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBe('grpc');
185
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBe(
186
- 'custom-header=value',
187
- );
188
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toBe('custom.attr=value');
189
- });
190
-
191
- it('sets resource attributes without optional fields when not provided', () => {
192
- try {
193
- createDatadogConfig({
194
- apiKey: 'test-key',
195
- service: 'test-service',
196
- enableLogs: true,
197
- });
198
- } catch {
199
- // Ignore peer dependency error
200
- }
201
-
202
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toBe(
203
- 'service.name=test-service',
204
- );
205
- });
206
-
207
- it('does not set env vars when enableLogs is false', () => {
208
- createDatadogConfig({
209
- apiKey: 'test-key',
210
- service: 'test-service',
211
- enableLogs: false,
212
- });
213
-
214
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBeUndefined();
215
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBeUndefined();
216
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBeUndefined();
217
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toBeUndefined();
218
- });
219
-
220
- it('does not set env vars by default', () => {
221
- createDatadogConfig({
222
- apiKey: 'test-key',
223
- service: 'test-service',
224
- });
225
-
226
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBeUndefined();
227
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBeUndefined();
228
- expect(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBeUndefined();
229
- expect(process.env.OTEL_RESOURCE_ATTRIBUTES).toBeUndefined();
230
- });
231
- });
232
- });
package/src/datadog.ts DELETED
@@ -1,346 +0,0 @@
1
- /**
2
- * Datadog preset for autotel
3
- *
4
- * Provides a simplified configuration helper for Datadog integration
5
- * with best practices built-in.
6
- *
7
- * @example Direct cloud ingestion (serverless, edge)
8
- * ```typescript
9
- * import { init } from 'autotel';
10
- * import { createDatadogConfig } from 'autotel-backends/datadog';
11
- *
12
- * init(createDatadogConfig({
13
- * apiKey: process.env.DATADOG_API_KEY!,
14
- * service: 'my-lambda',
15
- * enableLogs: true,
16
- * }));
17
- * ```
18
- *
19
- * @example Local Datadog Agent (long-running services, Kubernetes)
20
- * ```typescript
21
- * import { init } from 'autotel';
22
- * import { createDatadogConfig } from 'autotel-backends/datadog';
23
- *
24
- * init(createDatadogConfig({
25
- * service: 'my-api',
26
- * useAgent: true, // No API key needed - Agent handles it
27
- * }));
28
- * ```
29
- */
30
-
31
- import { createRequire } from 'node:module';
32
- import type { AutotelConfig } from 'autotel';
33
- import type { LogRecordProcessor } from '@opentelemetry/sdk-logs';
34
-
35
- // `__filename` exists under CJS (including esbuild's CJS output wrapper) but
36
- // not pure ESM. `typeof` is safe against an undeclared identifier and lets
37
- // the conditional pick the working URL in either format.
38
- declare const __filename: string | undefined;
39
-
40
- /**
41
- * Datadog site regions
42
- */
43
- export type DatadogSite =
44
- | 'datadoghq.com' // US1 (default)
45
- | 'datadoghq.eu' // EU
46
- | 'us3.datadoghq.com' // US3
47
- | 'us5.datadoghq.com' // US5
48
- | 'ap1.datadoghq.com' // AP1
49
- | 'ddog-gov.com'; // US1-FED
50
-
51
- /**
52
- * Configuration options for Datadog preset
53
- */
54
- export interface DatadogPresetConfig {
55
- /**
56
- * Datadog API key (required for direct cloud ingestion).
57
- * Not needed if using local Datadog Agent (useAgent: true).
58
- *
59
- * Get your API key from:
60
- * https://app.datadoghq.com/organization-settings/api-keys
61
- */
62
- apiKey?: string;
63
-
64
- /**
65
- * Datadog site/region.
66
- * Determines which Datadog intake endpoint to use.
67
- *
68
- * @default 'datadoghq.com' (US1)
69
- */
70
- site?: DatadogSite;
71
-
72
- /**
73
- * Service name (required).
74
- * Appears in Datadog APM, Service Catalog, and all telemetry.
75
- */
76
- service: string;
77
-
78
- /**
79
- * Deployment environment (e.g., 'production', 'staging', 'development').
80
- * Used for environment filtering in Datadog.
81
- *
82
- * @default process.env.DD_ENV || process.env.NODE_ENV || 'development'
83
- */
84
- environment?: string;
85
-
86
- /**
87
- * Service version for deployment tracking.
88
- * Enables Deployment Tracking in Datadog APM.
89
- *
90
- * @default process.env.DD_VERSION || auto-detected from package.json
91
- */
92
- version?: string;
93
-
94
- /**
95
- * Enable log export to Datadog via OTLP.
96
- *
97
- * When enabled, this:
98
- * 1. Sets up OTel Logs SDK with OTLP exporter (for direct OTel logs API usage)
99
- * 2. Auto-configures OTEL_EXPORTER_OTLP_LOGS_* env vars for pino-opentelemetry-transport
100
- *
101
- * For Pino users: Just add pino-opentelemetry-transport to your logger config:
102
- * ```typescript
103
- * const logger = pino({
104
- * transport: {
105
- * targets: [
106
- * { target: 'pino-pretty' },
107
- * { target: 'pino-opentelemetry-transport' }, // Auto-configured!
108
- * ],
109
- * },
110
- * });
111
- * ```
112
- *
113
- * @default false
114
- */
115
- enableLogs?: boolean;
116
-
117
- /**
118
- * Use local Datadog Agent instead of direct cloud ingestion.
119
- *
120
- * Benefits:
121
- * - Lower egress costs (Agent aggregates locally)
122
- * - Advanced features: trace-log correlation, multi-line logs, data scrubbing
123
- * - 500+ integrations for enrichment
124
- * - Infrastructure metrics collection
125
- *
126
- * Requires: Datadog Agent 7.35+ with OTLP enabled
127
- *
128
- * @default false
129
- */
130
- useAgent?: boolean;
131
-
132
- /**
133
- * Datadog Agent hostname (when useAgent: true).
134
- *
135
- * @default 'localhost'
136
- */
137
- agentHost?: string;
138
-
139
- /**
140
- * Datadog Agent OTLP port (when useAgent: true).
141
- *
142
- * @default 4318 (OTLP HTTP)
143
- */
144
- agentPort?: number;
145
-
146
- /**
147
- * Custom log record processors (advanced).
148
- * Overrides the default log processor if enableLogs is true.
149
- */
150
- logRecordProcessors?: LogRecordProcessor[];
151
- }
152
-
153
- /**
154
- * Create an autotel configuration optimized for Datadog.
155
- *
156
- * This preset handles:
157
- * - Proper OTLP endpoint configuration (Agent vs direct ingestion)
158
- * - Direct: https://otlp.{site} → SDK appends /v1/traces, /v1/metrics, /v1/logs
159
- * - Agent: http://localhost:4318 (default)
160
- * - Datadog API key authentication headers (direct ingestion only)
161
- * - Unified service tagging (service, env, version)
162
- * - Resource attribute best practices
163
- * - Optional log export configuration
164
- *
165
- * @param config - Datadog-specific configuration options
166
- * @returns AutotelConfig ready to pass to init()
167
- *
168
- * @example Simple cloud ingestion
169
- * ```typescript
170
- * init(createDatadogConfig({
171
- * apiKey: process.env.DATADOG_API_KEY!,
172
- * service: 'my-app',
173
- * }));
174
- * ```
175
- *
176
- * @example With logs and custom environment
177
- * ```typescript
178
- * init(createDatadogConfig({
179
- * apiKey: process.env.DATADOG_API_KEY!,
180
- * service: 'my-app',
181
- * environment: 'production',
182
- * version: '2.1.0',
183
- * enableLogs: true,
184
- * }));
185
- * ```
186
- *
187
- * @example Using local Datadog Agent
188
- * ```typescript
189
- * init(createDatadogConfig({
190
- * service: 'my-api',
191
- * useAgent: true,
192
- * agentHost: 'datadog-agent.default.svc.cluster.local', // Kubernetes
193
- * }));
194
- * ```
195
- */
196
- export function createDatadogConfig(
197
- config: DatadogPresetConfig,
198
- ): AutotelConfig {
199
- const {
200
- apiKey,
201
- site = 'datadoghq.com',
202
- service,
203
- environment,
204
- version,
205
- enableLogs = false,
206
- useAgent = false,
207
- agentHost = 'localhost',
208
- agentPort = 4318,
209
- logRecordProcessors,
210
- } = config;
211
-
212
- // Validation: API key required for direct ingestion
213
- if (!useAgent && !apiKey) {
214
- throw new Error(
215
- 'Datadog API key is required for direct cloud ingestion. ' +
216
- 'Either provide apiKey or set useAgent: true to use local Datadog Agent.',
217
- );
218
- }
219
-
220
- const baseConfig: AutotelConfig = {
221
- service,
222
- environment,
223
- version,
224
- };
225
-
226
- // Local Datadog Agent configuration
227
- if (useAgent) {
228
- const agentEndpoint = `http://${agentHost}:${agentPort}`;
229
-
230
- // Auto-configure env vars for pino-opentelemetry-transport in agent mode
231
- if (enableLogs) {
232
- const logsEndpoint = `http://${agentHost}:${agentPort}/v1/logs`;
233
-
234
- if (!process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) {
235
- process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = logsEndpoint;
236
- }
237
-
238
- if (!process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL) {
239
- process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'http/protobuf';
240
- }
241
-
242
- // No API key header needed for agent mode - Agent handles authentication
243
-
244
- const resourceAttrs = [
245
- `service.name=${service}`,
246
- environment ? `deployment.environment=${environment}` : null,
247
- version ? `service.version=${version}` : null,
248
- ]
249
- .filter(Boolean)
250
- .join(',');
251
-
252
- if (!process.env.OTEL_RESOURCE_ATTRIBUTES) {
253
- process.env.OTEL_RESOURCE_ATTRIBUTES = resourceAttrs;
254
- }
255
- }
256
-
257
- return {
258
- ...baseConfig,
259
- endpoint: agentEndpoint,
260
- // No API key or headers needed - Agent handles authentication
261
- };
262
- }
263
-
264
- // Direct cloud ingestion configuration
265
- // Datadog OTLP endpoint: base URL without path (SDK appends /v1/traces, /v1/metrics, /v1/logs)
266
- const otlpEndpoint = `https://otlp.${site}`;
267
- const authHeaders = `dd-api-key=${apiKey}`;
268
-
269
- const cloudConfig: AutotelConfig = {
270
- ...baseConfig,
271
- endpoint: otlpEndpoint,
272
- headers: authHeaders,
273
- };
274
-
275
- // Add log export if enabled
276
- if (enableLogs) {
277
- // Auto-configure env vars for pino-opentelemetry-transport and other OTel log transports
278
- // These are read by pino-opentelemetry-transport, otlp-logger, and similar libraries
279
- const logsEndpoint = useAgent
280
- ? `http://${agentHost}:${agentPort}/v1/logs`
281
- : `https://otlp.${site}/v1/logs`;
282
-
283
- // Only set if not already configured (allow user override)
284
- if (!process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) {
285
- process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = logsEndpoint;
286
- }
287
-
288
- if (!process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL) {
289
- process.env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'http/protobuf';
290
- }
291
-
292
- // Only set API key header for direct cloud ingestion (not agent mode)
293
- if (!useAgent && apiKey && !process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS) {
294
- process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS = `dd-api-key=${apiKey}`;
295
- }
296
-
297
- // Set resource attributes for service identification
298
- const resourceAttrs = [
299
- `service.name=${service}`,
300
- environment ? `deployment.environment=${environment}` : null,
301
- version ? `service.version=${version}` : null,
302
- ]
303
- .filter(Boolean)
304
- .join(',');
305
-
306
- if (!process.env.OTEL_RESOURCE_ATTRIBUTES) {
307
- process.env.OTEL_RESOURCE_ATTRIBUTES = resourceAttrs;
308
- }
309
-
310
- if (logRecordProcessors) {
311
- // Use custom processors if provided
312
- cloudConfig.logRecordProcessors = logRecordProcessors;
313
- } else {
314
- // Create default OTLP log exporter
315
- try {
316
- const pkgRequire = createRequire(
317
- typeof __filename === 'string' ? __filename : import.meta.url,
318
- );
319
- const { BatchLogRecordProcessor } = pkgRequire(
320
- '@opentelemetry/sdk-logs',
321
- );
322
- const { OTLPLogExporter } = pkgRequire(
323
- '@opentelemetry/exporter-logs-otlp-http',
324
- );
325
-
326
- cloudConfig.logRecordProcessors = [
327
- new BatchLogRecordProcessor(
328
- new OTLPLogExporter({
329
- url: `${otlpEndpoint}/v1/logs`,
330
- headers: {
331
- 'dd-api-key': apiKey,
332
- },
333
- }),
334
- ),
335
- ];
336
- } catch {
337
- throw new Error(
338
- 'Log export requires @opentelemetry/sdk-logs and @opentelemetry/exporter-logs-otlp-http. ' +
339
- 'Install them or set enableLogs: false.',
340
- );
341
- }
342
- }
343
- }
344
-
345
- return cloudConfig;
346
- }
@@ -1,56 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { createGoogleCloudConfig } from './google-cloud';
3
-
4
- describe('createGoogleCloudConfig()', () => {
5
- describe('validation', () => {
6
- it('should throw if projectId is missing', () => {
7
- expect(() => {
8
- createGoogleCloudConfig({
9
- // @ts-expect-error - testing missing projectId
10
- projectId: '',
11
- service: 'test-service',
12
- });
13
- }).toThrow('projectId is required');
14
- });
15
- });
16
-
17
- describe('useCollector mode', () => {
18
- it('should return endpoint and headers when useCollector is true', () => {
19
- const config = createGoogleCloudConfig({
20
- projectId: 'my-project',
21
- service: 'my-service',
22
- useCollector: true,
23
- });
24
-
25
- expect(config).toMatchObject({
26
- service: 'my-service',
27
- endpoint: 'http://localhost:4318',
28
- headers: { 'x-goog-user-project': 'my-project' },
29
- });
30
- });
31
-
32
- it('should use custom collectorEndpoint when provided', () => {
33
- const config = createGoogleCloudConfig({
34
- projectId: 'my-project',
35
- service: 'my-service',
36
- useCollector: true,
37
- collectorEndpoint: 'http://collector:4318',
38
- });
39
-
40
- expect(config.endpoint).toBe('http://collector:4318');
41
- });
42
-
43
- it('should pass through environment and version', () => {
44
- const config = createGoogleCloudConfig({
45
- projectId: 'my-project',
46
- service: 'my-service',
47
- useCollector: true,
48
- environment: 'production',
49
- version: '1.2.3',
50
- });
51
-
52
- expect(config.environment).toBe('production');
53
- expect(config.version).toBe('1.2.3');
54
- });
55
- });
56
- });