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 +2 -3
- package/src/datadog.test.ts +0 -232
- package/src/datadog.ts +0 -346
- package/src/google-cloud.test.ts +0 -56
- package/src/google-cloud.ts +0 -259
- package/src/grafana.ts +0 -177
- package/src/honeycomb.test.ts +0 -243
- package/src/honeycomb.ts +0 -184
- package/src/index.ts +0 -43
package/src/google-cloud.ts
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Google Cloud preset for autotel
|
|
3
|
-
*
|
|
4
|
-
* Sends traces (and optionally metrics) to Google Cloud Observability via the
|
|
5
|
-
* Telemetry (OTLP) API. Uses Application Default Credentials (ADC) for auth.
|
|
6
|
-
*
|
|
7
|
-
* @example Direct export to GCP (with google-auth-library)
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { init } from 'autotel';
|
|
10
|
-
* import { createGoogleCloudConfig } from 'autotel-backends/google-cloud';
|
|
11
|
-
*
|
|
12
|
-
* init(createGoogleCloudConfig({
|
|
13
|
-
* projectId: process.env.GOOGLE_CLOUD_PROJECT!,
|
|
14
|
-
* service: 'my-app',
|
|
15
|
-
* }));
|
|
16
|
-
* ```
|
|
17
|
-
*
|
|
18
|
-
* @example Via OpenTelemetry Collector (no auth in app)
|
|
19
|
-
* ```typescript
|
|
20
|
-
* init(createGoogleCloudConfig({
|
|
21
|
-
* projectId: process.env.GOOGLE_CLOUD_PROJECT!,
|
|
22
|
-
* service: 'my-app',
|
|
23
|
-
* useCollector: true,
|
|
24
|
-
* collectorEndpoint: 'http://localhost:4318',
|
|
25
|
-
* }));
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import { createRequire } from 'node:module';
|
|
30
|
-
import type { AutotelConfig } from 'autotel';
|
|
31
|
-
|
|
32
|
-
/** Minimal SpanExporter-compatible interface (avoids @opentelemetry/sdk-trace-base peer at build time). */
|
|
33
|
-
interface SpanExporterLike {
|
|
34
|
-
export(
|
|
35
|
-
spans: unknown[],
|
|
36
|
-
resultCallback: (result: { code: number; error?: Error }) => void,
|
|
37
|
-
): void | Promise<void>;
|
|
38
|
-
forceFlush?(): Promise<void>;
|
|
39
|
-
shutdown?(): Promise<void>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Default Telemetry API base URL (OTLP). */
|
|
43
|
-
const DEFAULT_ENDPOINT = 'https://telemetry.googleapis.com';
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Configuration options for Google Cloud preset
|
|
47
|
-
*/
|
|
48
|
-
export interface GoogleCloudPresetConfig {
|
|
49
|
-
/**
|
|
50
|
-
* Google Cloud project ID (required for direct export).
|
|
51
|
-
* Used for quota and resource attribution. Set GOOGLE_CLOUD_PROJECT or
|
|
52
|
-
* GOOGLE_APPLICATION_CREDENTIALS for ADC.
|
|
53
|
-
*
|
|
54
|
-
* @default process.env.GOOGLE_CLOUD_PROJECT
|
|
55
|
-
*/
|
|
56
|
-
projectId: string;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Service name (required).
|
|
60
|
-
* Appears as service.name in Cloud Trace and Monitoring.
|
|
61
|
-
*/
|
|
62
|
-
service: string;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Deployment environment (e.g., 'production', 'staging').
|
|
66
|
-
*
|
|
67
|
-
* @default process.env.NODE_ENV || 'development'
|
|
68
|
-
*/
|
|
69
|
-
environment?: string;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Service version for deployment tracking.
|
|
73
|
-
*
|
|
74
|
-
* @default process.env.GCP_VERSION || process.env.VERSION
|
|
75
|
-
*/
|
|
76
|
-
version?: string;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Use an OpenTelemetry Collector instead of exporting directly to GCP.
|
|
80
|
-
* When true, the app sends OTLP to collectorEndpoint; the Collector
|
|
81
|
-
* handles authentication to the Telemetry API. No google-auth-library needed.
|
|
82
|
-
*
|
|
83
|
-
* @default false
|
|
84
|
-
*/
|
|
85
|
-
useCollector?: boolean;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Collector OTLP endpoint (when useCollector is true).
|
|
89
|
-
*
|
|
90
|
-
* @default 'http://localhost:4318'
|
|
91
|
-
*/
|
|
92
|
-
collectorEndpoint?: string;
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Telemetry API base URL (when useCollector is false).
|
|
96
|
-
* Only override for testing or special endpoints.
|
|
97
|
-
*
|
|
98
|
-
* @default 'https://telemetry.googleapis.com'
|
|
99
|
-
*/
|
|
100
|
-
endpoint?: string;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create an autotel configuration for Google Cloud Observability (Telemetry API).
|
|
105
|
-
*
|
|
106
|
-
* - With useCollector: false (default), exports directly to the Telemetry API
|
|
107
|
-
* using Application Default Credentials. Requires optional peer dependency
|
|
108
|
-
* google-auth-library for auth. Install: pnpm add google-auth-library
|
|
109
|
-
*
|
|
110
|
-
* - With useCollector: true, sends OTLP to a local Collector; the Collector
|
|
111
|
-
* forwards to GCP with ADC. No google-auth-library needed in the app.
|
|
112
|
-
*
|
|
113
|
-
* @param config - Google Cloud preset options
|
|
114
|
-
* @returns AutotelConfig ready to pass to init()
|
|
115
|
-
*/
|
|
116
|
-
export function createGoogleCloudConfig(
|
|
117
|
-
config: GoogleCloudPresetConfig,
|
|
118
|
-
): AutotelConfig {
|
|
119
|
-
const {
|
|
120
|
-
projectId,
|
|
121
|
-
service,
|
|
122
|
-
environment,
|
|
123
|
-
version,
|
|
124
|
-
useCollector = false,
|
|
125
|
-
collectorEndpoint = 'http://localhost:4318',
|
|
126
|
-
endpoint = DEFAULT_ENDPOINT,
|
|
127
|
-
} = config;
|
|
128
|
-
|
|
129
|
-
if (!projectId) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
'Google Cloud projectId is required. Set it or use process.env.GOOGLE_CLOUD_PROJECT.',
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const baseConfig: AutotelConfig = {
|
|
136
|
-
service,
|
|
137
|
-
environment,
|
|
138
|
-
version,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
if (useCollector) {
|
|
142
|
-
return {
|
|
143
|
-
...baseConfig,
|
|
144
|
-
endpoint: collectorEndpoint,
|
|
145
|
-
// x-goog-user-project for quota when Collector forwards to GCP
|
|
146
|
-
headers: { 'x-goog-user-project': projectId },
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Direct export: need ADC via google-auth-library
|
|
151
|
-
try {
|
|
152
|
-
const userRequire = createRequire(process.cwd() + '/package.json');
|
|
153
|
-
const { GoogleAuth } = userRequire('google-auth-library');
|
|
154
|
-
const { OTLPTraceExporter } = userRequire(
|
|
155
|
-
'@opentelemetry/exporter-trace-otlp-http',
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const tracesUrl = `${endpoint}/v1/traces`;
|
|
159
|
-
const auth = new GoogleAuth({
|
|
160
|
-
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const gcpTraceExporter = createGcpAuthTraceExporter(
|
|
164
|
-
tracesUrl,
|
|
165
|
-
projectId,
|
|
166
|
-
auth,
|
|
167
|
-
OTLPTraceExporter,
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
...baseConfig,
|
|
172
|
-
// Structurally compatible with SpanExporter from @opentelemetry/sdk-trace-base
|
|
173
|
-
spanExporters: [
|
|
174
|
-
gcpTraceExporter as NonNullable<AutotelConfig['spanExporters']>[number],
|
|
175
|
-
],
|
|
176
|
-
};
|
|
177
|
-
} catch (error) {
|
|
178
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
179
|
-
if (
|
|
180
|
-
message.includes('google-auth-library') ||
|
|
181
|
-
message.includes('Cannot find module')
|
|
182
|
-
) {
|
|
183
|
-
throw new Error(
|
|
184
|
-
'Direct export to Google Cloud requires google-auth-library. ' +
|
|
185
|
-
'Install it: pnpm add google-auth-library. ' +
|
|
186
|
-
'Or use useCollector: true and run an OpenTelemetry Collector with GCP auth.',
|
|
187
|
-
{ cause: error },
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
throw error;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/** Minimal auth client: getClient() returns a client with getAccessToken(). */
|
|
195
|
-
interface GoogleAuthLike {
|
|
196
|
-
getClient(): Promise<{ getAccessToken(): Promise<{ token: string | null }> }>;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
type OTLPTraceExporterCtor = new (config: {
|
|
200
|
-
url: string;
|
|
201
|
-
headers?: Record<string, string>;
|
|
202
|
-
}) => SpanExporterLike;
|
|
203
|
-
|
|
204
|
-
function createGcpAuthTraceExporter(
|
|
205
|
-
url: string,
|
|
206
|
-
projectId: string,
|
|
207
|
-
auth: GoogleAuthLike,
|
|
208
|
-
OTLPTraceExporterCtor: OTLPTraceExporterCtor,
|
|
209
|
-
): SpanExporterLike {
|
|
210
|
-
return new GcpAuthSpanExporter(url, projectId, auth, OTLPTraceExporterCtor);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
class GcpAuthSpanExporter implements SpanExporterLike {
|
|
214
|
-
constructor(
|
|
215
|
-
private readonly url: string,
|
|
216
|
-
private readonly projectId: string,
|
|
217
|
-
private readonly auth: GoogleAuthLike,
|
|
218
|
-
private readonly OTLPTraceExporterCtor: OTLPTraceExporterCtor,
|
|
219
|
-
) {}
|
|
220
|
-
|
|
221
|
-
async export(
|
|
222
|
-
spans: unknown[],
|
|
223
|
-
resultCallback: (result: { code: number; error?: Error }) => void,
|
|
224
|
-
): Promise<void> {
|
|
225
|
-
try {
|
|
226
|
-
const client = await this.auth.getClient();
|
|
227
|
-
const tokenResponse = await client.getAccessToken();
|
|
228
|
-
const token = tokenResponse.token;
|
|
229
|
-
if (!token) {
|
|
230
|
-
resultCallback({
|
|
231
|
-
code: 1,
|
|
232
|
-
error: new Error('No access token from ADC'),
|
|
233
|
-
});
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
const exporter = new this.OTLPTraceExporterCtor({
|
|
237
|
-
url: this.url,
|
|
238
|
-
headers: {
|
|
239
|
-
Authorization: `Bearer ${token}`,
|
|
240
|
-
'x-goog-user-project': this.projectId,
|
|
241
|
-
},
|
|
242
|
-
});
|
|
243
|
-
exporter.export(spans, resultCallback);
|
|
244
|
-
} catch (error) {
|
|
245
|
-
resultCallback({
|
|
246
|
-
code: 1,
|
|
247
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
forceFlush(): Promise<void> {
|
|
253
|
-
return Promise.resolve();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
shutdown(): Promise<void> {
|
|
257
|
-
return Promise.resolve();
|
|
258
|
-
}
|
|
259
|
-
}
|
package/src/grafana.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Grafana Cloud preset for autotel
|
|
3
|
-
*
|
|
4
|
-
* Provides a simplified configuration helper for sending traces, metrics,
|
|
5
|
-
* and logs to Grafana Cloud via the OTLP gateway.
|
|
6
|
-
*
|
|
7
|
-
* Get your endpoint and headers from:
|
|
8
|
-
* Grafana Cloud Portal → your stack → Connections → OpenTelemetry → Configure
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { init } from 'autotel';
|
|
13
|
-
* import { createGrafanaConfig } from 'autotel-backends/grafana';
|
|
14
|
-
*
|
|
15
|
-
* init(createGrafanaConfig({
|
|
16
|
-
* endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT!,
|
|
17
|
-
* headers: process.env.OTEL_EXPORTER_OTLP_HEADERS,
|
|
18
|
-
* service: 'my-app',
|
|
19
|
-
* enableLogs: true,
|
|
20
|
-
* }));
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { createRequire } from 'node:module';
|
|
25
|
-
import type { AutotelConfig } from 'autotel';
|
|
26
|
-
import type { LogRecordProcessor } from '@opentelemetry/sdk-logs';
|
|
27
|
-
|
|
28
|
-
// See packages/autotel/src/node-require.ts for why the __filename fallback
|
|
29
|
-
// is necessary alongside import.meta.url.
|
|
30
|
-
declare const __filename: string | undefined;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Configuration options for Grafana Cloud preset
|
|
34
|
-
*/
|
|
35
|
-
export interface GrafanaPresetConfig {
|
|
36
|
-
/**
|
|
37
|
-
* OTLP gateway endpoint (required).
|
|
38
|
-
* From Grafana Cloud: Stack → Connections → OpenTelemetry → Configure.
|
|
39
|
-
* Example: https://otlp-gateway-prod-gb-south-1.grafana.net/otlp
|
|
40
|
-
*/
|
|
41
|
-
endpoint: string;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* OTLP authentication headers.
|
|
45
|
-
* From the same Configure tile; usually Basic auth.
|
|
46
|
-
* Example: "Authorization=Basic%20BASE64_INSTANCE_ID_AND_TOKEN"
|
|
47
|
-
* or object: { Authorization: 'Basic ...' }
|
|
48
|
-
*/
|
|
49
|
-
headers?: string | Record<string, string>;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Service name (required).
|
|
53
|
-
* Appears in Tempo, Mimir, and Loki as service_name.
|
|
54
|
-
*/
|
|
55
|
-
service: string;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Deployment environment (e.g. 'production', 'staging').
|
|
59
|
-
*
|
|
60
|
-
* @default process.env.NODE_ENV || 'development'
|
|
61
|
-
*/
|
|
62
|
-
environment?: string;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Service version for deployment tracking.
|
|
66
|
-
*
|
|
67
|
-
* @default process.env.OTEL_SERVICE_VERSION
|
|
68
|
-
*/
|
|
69
|
-
version?: string;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Enable log export to Grafana Cloud (Loki) via OTLP.
|
|
73
|
-
* When true, configures logRecordProcessors so OTel Logs API records are exported.
|
|
74
|
-
*
|
|
75
|
-
* @default true
|
|
76
|
-
*/
|
|
77
|
-
enableLogs?: boolean;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Custom log record processors (advanced).
|
|
81
|
-
* Overrides the default OTLP log processor when enableLogs is true.
|
|
82
|
-
*/
|
|
83
|
-
logRecordProcessors?: LogRecordProcessor[];
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function normalizeHeaders(
|
|
87
|
-
headers: string | Record<string, string> | undefined,
|
|
88
|
-
): Record<string, string> | undefined {
|
|
89
|
-
if (!headers) return undefined;
|
|
90
|
-
if (typeof headers === 'object') return headers;
|
|
91
|
-
const out: Record<string, string> = {};
|
|
92
|
-
for (const pair of headers.split(',')) {
|
|
93
|
-
const [key, ...valueParts] = pair.split('=');
|
|
94
|
-
if (key && valueParts.length > 0) {
|
|
95
|
-
let value = valueParts.join('=').trim();
|
|
96
|
-
value = value.replaceAll('%20', ' ');
|
|
97
|
-
out[key.trim()] = value;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return Object.keys(out).length > 0 ? out : undefined;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create an autotel configuration for Grafana Cloud OTLP.
|
|
105
|
-
*
|
|
106
|
-
* Sends traces (Tempo), metrics (Mimir), and optionally logs (Loki) to the
|
|
107
|
-
* Grafana Cloud OTLP gateway. Endpoint and headers come from the stack's
|
|
108
|
-
* Connections → OpenTelemetry → Configure tile.
|
|
109
|
-
*
|
|
110
|
-
* @param config - Grafana Cloud configuration options
|
|
111
|
-
* @returns AutotelConfig ready to pass to init()
|
|
112
|
-
*/
|
|
113
|
-
export function createGrafanaConfig(
|
|
114
|
-
config: GrafanaPresetConfig,
|
|
115
|
-
): AutotelConfig {
|
|
116
|
-
const {
|
|
117
|
-
endpoint,
|
|
118
|
-
headers: headersInput,
|
|
119
|
-
service,
|
|
120
|
-
environment,
|
|
121
|
-
version,
|
|
122
|
-
enableLogs = true,
|
|
123
|
-
logRecordProcessors,
|
|
124
|
-
} = config;
|
|
125
|
-
|
|
126
|
-
if (!endpoint) {
|
|
127
|
-
throw new Error(
|
|
128
|
-
'Grafana Cloud endpoint is required. Get it from: Grafana Cloud → your stack → Connections → OpenTelemetry → Configure',
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const headers = normalizeHeaders(headersInput);
|
|
133
|
-
const base = endpoint.replace(/\/v1\/(traces|metrics|logs)$/, '');
|
|
134
|
-
const logsUrl = `${base}${base.endsWith('/') ? '' : '/'}v1/logs`;
|
|
135
|
-
|
|
136
|
-
const result: AutotelConfig = {
|
|
137
|
-
service,
|
|
138
|
-
environment,
|
|
139
|
-
version,
|
|
140
|
-
endpoint,
|
|
141
|
-
headers,
|
|
142
|
-
metrics: true,
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
if (enableLogs) {
|
|
146
|
-
if (logRecordProcessors) {
|
|
147
|
-
result.logRecordProcessors = logRecordProcessors;
|
|
148
|
-
} else {
|
|
149
|
-
try {
|
|
150
|
-
const pkgRequire = createRequire(
|
|
151
|
-
typeof __filename === 'string' ? __filename : import.meta.url,
|
|
152
|
-
);
|
|
153
|
-
const { BatchLogRecordProcessor } = pkgRequire(
|
|
154
|
-
'@opentelemetry/sdk-logs',
|
|
155
|
-
);
|
|
156
|
-
const { OTLPLogExporter } = pkgRequire(
|
|
157
|
-
'@opentelemetry/exporter-logs-otlp-http',
|
|
158
|
-
);
|
|
159
|
-
result.logRecordProcessors = [
|
|
160
|
-
new BatchLogRecordProcessor(
|
|
161
|
-
new OTLPLogExporter({
|
|
162
|
-
url: logsUrl,
|
|
163
|
-
headers,
|
|
164
|
-
}),
|
|
165
|
-
),
|
|
166
|
-
];
|
|
167
|
-
} catch {
|
|
168
|
-
throw new Error(
|
|
169
|
-
'Log export requires @opentelemetry/sdk-logs and @opentelemetry/exporter-logs-otlp-http. ' +
|
|
170
|
-
'Install them or set enableLogs: false.',
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return result;
|
|
177
|
-
}
|
package/src/honeycomb.test.ts
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createHoneycombConfig } from './honeycomb';
|
|
3
|
-
|
|
4
|
-
describe('createHoneycombConfig()', () => {
|
|
5
|
-
describe('validation', () => {
|
|
6
|
-
it('should throw if apiKey is missing', () => {
|
|
7
|
-
expect(() => {
|
|
8
|
-
createHoneycombConfig({
|
|
9
|
-
// @ts-expect-error - testing missing apiKey
|
|
10
|
-
service: 'test-service',
|
|
11
|
-
});
|
|
12
|
-
}).toThrow('Honeycomb API key is required');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should throw if apiKey is empty string', () => {
|
|
16
|
-
expect(() => {
|
|
17
|
-
createHoneycombConfig({
|
|
18
|
-
apiKey: '',
|
|
19
|
-
service: 'test-service',
|
|
20
|
-
});
|
|
21
|
-
}).toThrow('Honeycomb API key is required');
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('basic configuration', () => {
|
|
26
|
-
it('should return minimal config with apiKey and service', () => {
|
|
27
|
-
const config = createHoneycombConfig({
|
|
28
|
-
apiKey: 'test-api-key',
|
|
29
|
-
service: 'my-service',
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
expect(config).toMatchObject({
|
|
33
|
-
service: 'my-service',
|
|
34
|
-
protocol: 'grpc',
|
|
35
|
-
endpoint: 'api.honeycomb.io:443',
|
|
36
|
-
headers: {
|
|
37
|
-
'x-honeycomb-team': 'test-api-key',
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should use gRPC protocol by default', () => {
|
|
43
|
-
const config = createHoneycombConfig({
|
|
44
|
-
apiKey: 'test-api-key',
|
|
45
|
-
service: 'my-service',
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
expect(config.protocol).toBe('grpc');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should use default Honeycomb endpoint', () => {
|
|
52
|
-
const config = createHoneycombConfig({
|
|
53
|
-
apiKey: 'test-api-key',
|
|
54
|
-
service: 'my-service',
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
expect(config.endpoint).toBe('api.honeycomb.io:443');
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('headers', () => {
|
|
62
|
-
it('should set x-honeycomb-team header with API key', () => {
|
|
63
|
-
const config = createHoneycombConfig({
|
|
64
|
-
apiKey: 'my-secret-key',
|
|
65
|
-
service: 'test-service',
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
expect(config.headers).toMatchObject({
|
|
69
|
-
'x-honeycomb-team': 'my-secret-key',
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should add x-honeycomb-dataset header when dataset is specified', () => {
|
|
74
|
-
const config = createHoneycombConfig({
|
|
75
|
-
apiKey: 'test-key',
|
|
76
|
-
service: 'test-service',
|
|
77
|
-
dataset: 'production',
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
expect(config.headers).toMatchObject({
|
|
81
|
-
'x-honeycomb-team': 'test-key',
|
|
82
|
-
'x-honeycomb-dataset': 'production',
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should add x-honeycomb-samplerate header when sampleRate is specified', () => {
|
|
87
|
-
const config = createHoneycombConfig({
|
|
88
|
-
apiKey: 'test-key',
|
|
89
|
-
service: 'test-service',
|
|
90
|
-
sampleRate: 10,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(config.headers).toMatchObject({
|
|
94
|
-
'x-honeycomb-team': 'test-key',
|
|
95
|
-
'x-honeycomb-samplerate': '10',
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('should include all headers when dataset and sampleRate are specified', () => {
|
|
100
|
-
const config = createHoneycombConfig({
|
|
101
|
-
apiKey: 'test-key',
|
|
102
|
-
service: 'test-service',
|
|
103
|
-
dataset: 'my-dataset',
|
|
104
|
-
sampleRate: 100,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
expect(config.headers).toMatchObject({
|
|
108
|
-
'x-honeycomb-team': 'test-key',
|
|
109
|
-
'x-honeycomb-dataset': 'my-dataset',
|
|
110
|
-
'x-honeycomb-samplerate': '100',
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should convert sampleRate to string', () => {
|
|
115
|
-
const config = createHoneycombConfig({
|
|
116
|
-
apiKey: 'test-key',
|
|
117
|
-
service: 'test-service',
|
|
118
|
-
sampleRate: 50,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
expect(typeof config.headers?.['x-honeycomb-samplerate']).toBe('string');
|
|
122
|
-
expect(config.headers?.['x-honeycomb-samplerate']).toBe('50');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('environment and version', () => {
|
|
127
|
-
it('should include environment when specified', () => {
|
|
128
|
-
const config = createHoneycombConfig({
|
|
129
|
-
apiKey: 'test-key',
|
|
130
|
-
service: 'test-service',
|
|
131
|
-
environment: 'production',
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
expect(config.environment).toBe('production');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should include version when specified', () => {
|
|
138
|
-
const config = createHoneycombConfig({
|
|
139
|
-
apiKey: 'test-key',
|
|
140
|
-
service: 'test-service',
|
|
141
|
-
version: '2.1.0',
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
expect(config.version).toBe('2.1.0');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should include both environment and version', () => {
|
|
148
|
-
const config = createHoneycombConfig({
|
|
149
|
-
apiKey: 'test-key',
|
|
150
|
-
service: 'test-service',
|
|
151
|
-
environment: 'staging',
|
|
152
|
-
version: '1.5.3',
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
expect(config.environment).toBe('staging');
|
|
156
|
-
expect(config.version).toBe('1.5.3');
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('custom endpoint', () => {
|
|
161
|
-
it('should allow custom endpoint', () => {
|
|
162
|
-
const config = createHoneycombConfig({
|
|
163
|
-
apiKey: 'test-key',
|
|
164
|
-
service: 'test-service',
|
|
165
|
-
endpoint: 'custom.honeycomb.io:8443',
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
expect(config.endpoint).toBe('custom.honeycomb.io:8443');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should allow EU endpoint', () => {
|
|
172
|
-
const config = createHoneycombConfig({
|
|
173
|
-
apiKey: 'test-key',
|
|
174
|
-
service: 'test-service',
|
|
175
|
-
endpoint: 'api.eu1.honeycomb.io:443',
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
expect(config.endpoint).toBe('api.eu1.honeycomb.io:443');
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
describe('complete configuration', () => {
|
|
183
|
-
it('should handle all options together', () => {
|
|
184
|
-
const config = createHoneycombConfig({
|
|
185
|
-
apiKey: 'complete-test-key',
|
|
186
|
-
service: 'complete-service',
|
|
187
|
-
dataset: 'complete-dataset',
|
|
188
|
-
environment: 'production',
|
|
189
|
-
version: '3.2.1',
|
|
190
|
-
endpoint: 'custom.endpoint.io:9000',
|
|
191
|
-
sampleRate: 25,
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
expect(config).toEqual({
|
|
195
|
-
service: 'complete-service',
|
|
196
|
-
environment: 'production',
|
|
197
|
-
version: '3.2.1',
|
|
198
|
-
protocol: 'grpc',
|
|
199
|
-
endpoint: 'custom.endpoint.io:9000',
|
|
200
|
-
headers: {
|
|
201
|
-
'x-honeycomb-team': 'complete-test-key',
|
|
202
|
-
'x-honeycomb-dataset': 'complete-dataset',
|
|
203
|
-
'x-honeycomb-samplerate': '25',
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe('real-world scenarios', () => {
|
|
210
|
-
it('should configure for classic Honeycomb account with dataset', () => {
|
|
211
|
-
const config = createHoneycombConfig({
|
|
212
|
-
apiKey: process.env.HONEYCOMB_API_KEY || 'test-key',
|
|
213
|
-
service: 'my-app',
|
|
214
|
-
dataset: 'production',
|
|
215
|
-
environment: 'production',
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
expect(config.headers).toHaveProperty('x-honeycomb-dataset');
|
|
219
|
-
expect(config.protocol).toBe('grpc');
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should configure for modern Honeycomb account without dataset', () => {
|
|
223
|
-
const config = createHoneycombConfig({
|
|
224
|
-
apiKey: process.env.HONEYCOMB_API_KEY || 'test-key',
|
|
225
|
-
service: 'my-app',
|
|
226
|
-
environment: 'production',
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
expect(config.headers).not.toHaveProperty('x-honeycomb-dataset');
|
|
230
|
-
expect(config.protocol).toBe('grpc');
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('should configure with head-based sampling', () => {
|
|
234
|
-
const config = createHoneycombConfig({
|
|
235
|
-
apiKey: 'test-key',
|
|
236
|
-
service: 'high-volume-app',
|
|
237
|
-
sampleRate: 100, // Sample 1% of traces
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
expect(config.headers).toHaveProperty('x-honeycomb-samplerate', '100');
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
});
|