@kabran-tecnologia/kabran-config 1.6.0 → 1.8.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 +283 -0
- package/package.json +63 -8
- package/src/schemas/ci-result.v2.schema.json +125 -0
- package/src/scripts/ci/ci-core.sh +131 -1
- package/src/scripts/ci/ci-runner.sh +88 -0
- package/src/scripts/ci-result-history.mjs +245 -0
- package/src/scripts/ci-result-trends.mjs +296 -0
- package/src/scripts/ci-result-utils.mjs +104 -0
- package/src/scripts/generate-ci-result.mjs +92 -11
- package/src/scripts/pr-quality-comment.mjs +36 -0
- package/src/scripts/setup.mjs +91 -4
- package/src/telemetry/README.md +407 -0
- package/src/telemetry/config/defaults.mjs +421 -0
- package/src/telemetry/config/index.mjs +132 -0
- package/src/telemetry/edge/index.mjs +446 -0
- package/src/telemetry/frontend/index.mjs +366 -0
- package/src/telemetry/logger/index.mjs +236 -0
- package/src/telemetry/node/index.mjs +386 -0
- package/src/telemetry/shared/helpers.mjs +133 -0
- package/src/telemetry/shared/index.mjs +15 -0
- package/src/telemetry/shared/types.d.ts +123 -0
- package/templates/telemetry/.env.telemetry.example +118 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry Configuration Defaults
|
|
3
|
+
*
|
|
4
|
+
* Smart defaults that work for most Kabran projects.
|
|
5
|
+
* All values can be overridden via environment variables.
|
|
6
|
+
*
|
|
7
|
+
* @module telemetry/config/defaults
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Environment Variable Helpers
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get environment variable with fallback
|
|
16
|
+
* @param {string} key - Environment variable key
|
|
17
|
+
* @param {string} fallback - Fallback value
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
function getEnv(key, fallback) {
|
|
21
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
22
|
+
return process.env[key] || fallback
|
|
23
|
+
}
|
|
24
|
+
if (typeof Deno !== 'undefined') {
|
|
25
|
+
return Deno.env.get(key) || fallback
|
|
26
|
+
}
|
|
27
|
+
return fallback
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get numeric environment variable with fallback
|
|
32
|
+
* @param {string} key - Environment variable key
|
|
33
|
+
* @param {number} fallback - Fallback value
|
|
34
|
+
* @returns {number}
|
|
35
|
+
*/
|
|
36
|
+
function getEnvNumber(key, fallback) {
|
|
37
|
+
const value = getEnv(key, '')
|
|
38
|
+
if (value === '') return fallback
|
|
39
|
+
const parsed = parseInt(value, 10)
|
|
40
|
+
return isNaN(parsed) ? fallback : parsed
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Parse CORS URLs from environment variable
|
|
45
|
+
* @param {string} value - Comma-separated URL patterns
|
|
46
|
+
* @returns {RegExp[]}
|
|
47
|
+
*/
|
|
48
|
+
function parseCorsUrls(value) {
|
|
49
|
+
if (!value) return null
|
|
50
|
+
return value.split(',').map((pattern) => new RegExp(pattern.trim()))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Parse event names from environment variable
|
|
55
|
+
* @param {string} value - Comma-separated event names
|
|
56
|
+
* @returns {string[]}
|
|
57
|
+
*/
|
|
58
|
+
function parseEventNames(value) {
|
|
59
|
+
if (!value) return null
|
|
60
|
+
return value.split(',').map((name) => name.trim())
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Parse ignore paths from environment variable
|
|
65
|
+
* @param {string} value - Comma-separated paths
|
|
66
|
+
* @returns {string[]}
|
|
67
|
+
*/
|
|
68
|
+
function parseIgnorePaths(value) {
|
|
69
|
+
if (!value) return null
|
|
70
|
+
return value.split(',').map((path) => path.trim())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// Default Constants
|
|
75
|
+
// =============================================================================
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Default OTLP endpoint
|
|
79
|
+
* Override: OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_ENDPOINT
|
|
80
|
+
*/
|
|
81
|
+
export const DEFAULT_ENDPOINT = 'https://otel.kabran.com.br'
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Default OTLP traces path
|
|
85
|
+
* Override: OTEL_EXPORTER_OTLP_TRACES_PATH
|
|
86
|
+
*/
|
|
87
|
+
export const DEFAULT_TRACES_PATH = '/v1/traces'
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Default sampling rate (10%)
|
|
91
|
+
* Override: OTEL_SAMPLE_RATE
|
|
92
|
+
*/
|
|
93
|
+
export const DEFAULT_SAMPLE_RATE = 0.1
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Default service version
|
|
97
|
+
* Override: SERVICE_VERSION
|
|
98
|
+
*/
|
|
99
|
+
export const DEFAULT_SERVICE_VERSION = '1.0.0'
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Default namespace
|
|
103
|
+
* Override: OTEL_NAMESPACE or SERVICE_NAMESPACE
|
|
104
|
+
*/
|
|
105
|
+
export const DEFAULT_NAMESPACE = 'kabran'
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Default CORS URLs for trace header propagation
|
|
109
|
+
* Override: OTEL_PROPAGATE_TRACE_HEADER_CORS_URLS (comma-separated regex patterns)
|
|
110
|
+
*/
|
|
111
|
+
export const DEFAULT_CORS_URLS = [
|
|
112
|
+
/.*\.supabase\.co/,
|
|
113
|
+
/.*\.kabran\.com\.br/,
|
|
114
|
+
/localhost/,
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Default instrumentation options
|
|
119
|
+
* Override: OTEL_INSTRUMENTATION_FETCH, OTEL_INSTRUMENTATION_DOCUMENT_LOAD, etc.
|
|
120
|
+
*/
|
|
121
|
+
export const DEFAULT_INSTRUMENTATION = {
|
|
122
|
+
fetch: true,
|
|
123
|
+
documentLoad: true,
|
|
124
|
+
userInteraction: true,
|
|
125
|
+
database: true,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Default user interaction events
|
|
130
|
+
* Override: OTEL_USER_INTERACTION_EVENTS (comma-separated)
|
|
131
|
+
*/
|
|
132
|
+
export const DEFAULT_USER_INTERACTION_EVENTS = ['click', 'submit']
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Default paths to ignore in middleware
|
|
136
|
+
* Override: OTEL_IGNORE_PATHS (comma-separated)
|
|
137
|
+
*/
|
|
138
|
+
export const DEFAULT_IGNORE_PATHS = ['/health', '/ready', '/metrics']
|
|
139
|
+
|
|
140
|
+
// =============================================================================
|
|
141
|
+
// Exporter Configuration
|
|
142
|
+
// =============================================================================
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Default OTLP export timeout (ms) for Node.js
|
|
146
|
+
* Override: OTEL_EXPORTER_OTLP_TIMEOUT
|
|
147
|
+
*/
|
|
148
|
+
export const DEFAULT_EXPORT_TIMEOUT_NODE = 10000
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Default OTLP export timeout (ms) for Edge/Serverless
|
|
152
|
+
* Override: OTEL_EXPORTER_OTLP_TIMEOUT_EDGE
|
|
153
|
+
*/
|
|
154
|
+
export const DEFAULT_EXPORT_TIMEOUT_EDGE = 5000
|
|
155
|
+
|
|
156
|
+
// =============================================================================
|
|
157
|
+
// Batch Span Processor Configuration - Node.js
|
|
158
|
+
// =============================================================================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Default max queue size for Node.js BatchSpanProcessor
|
|
162
|
+
* Override: OTEL_BSP_MAX_QUEUE_SIZE
|
|
163
|
+
*/
|
|
164
|
+
export const DEFAULT_BSP_MAX_QUEUE_SIZE_NODE = 2048
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Default max export batch size for Node.js BatchSpanProcessor
|
|
168
|
+
* Override: OTEL_BSP_MAX_EXPORT_BATCH_SIZE
|
|
169
|
+
*/
|
|
170
|
+
export const DEFAULT_BSP_MAX_EXPORT_BATCH_SIZE_NODE = 512
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Default scheduled delay (ms) for Node.js BatchSpanProcessor
|
|
174
|
+
* Override: OTEL_BSP_SCHEDULE_DELAY
|
|
175
|
+
*/
|
|
176
|
+
export const DEFAULT_BSP_SCHEDULE_DELAY_NODE = 5000
|
|
177
|
+
|
|
178
|
+
// =============================================================================
|
|
179
|
+
// Batch Span Processor Configuration - Frontend
|
|
180
|
+
// =============================================================================
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Default max queue size for Frontend BatchSpanProcessor
|
|
184
|
+
* Override: OTEL_BSP_MAX_QUEUE_SIZE_FRONTEND
|
|
185
|
+
*/
|
|
186
|
+
export const DEFAULT_BSP_MAX_QUEUE_SIZE_FRONTEND = 100
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Default max export batch size for Frontend BatchSpanProcessor
|
|
190
|
+
* Override: OTEL_BSP_MAX_EXPORT_BATCH_SIZE_FRONTEND
|
|
191
|
+
*/
|
|
192
|
+
export const DEFAULT_BSP_MAX_EXPORT_BATCH_SIZE_FRONTEND = 10
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Default scheduled delay (ms) for Frontend BatchSpanProcessor
|
|
196
|
+
* Override: OTEL_BSP_SCHEDULE_DELAY_FRONTEND
|
|
197
|
+
*/
|
|
198
|
+
export const DEFAULT_BSP_SCHEDULE_DELAY_FRONTEND = 500
|
|
199
|
+
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// Tracer Names (fallbacks)
|
|
202
|
+
// =============================================================================
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Default tracer name for Node.js
|
|
206
|
+
*/
|
|
207
|
+
export const DEFAULT_TRACER_NAME_NODE = 'kabran-node'
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Default tracer name for Frontend
|
|
211
|
+
*/
|
|
212
|
+
export const DEFAULT_TRACER_NAME_FRONTEND = 'kabran-frontend'
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Default tracer name for Edge
|
|
216
|
+
*/
|
|
217
|
+
export const DEFAULT_TRACER_NAME_EDGE = 'kabran-edge'
|
|
218
|
+
|
|
219
|
+
// =============================================================================
|
|
220
|
+
// Logger Configuration
|
|
221
|
+
// =============================================================================
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Default trace ID display length in logs
|
|
225
|
+
* Override: OTEL_LOG_TRACE_ID_LENGTH
|
|
226
|
+
*/
|
|
227
|
+
export const DEFAULT_LOG_TRACE_ID_LENGTH = 8
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Check if colors should be disabled
|
|
231
|
+
* Override: NO_COLOR or FORCE_COLOR=false
|
|
232
|
+
*/
|
|
233
|
+
export function shouldDisableColors() {
|
|
234
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
235
|
+
if (process.env.NO_COLOR !== undefined) return true
|
|
236
|
+
if (process.env.FORCE_COLOR === 'false' || process.env.FORCE_COLOR === '0') return true
|
|
237
|
+
}
|
|
238
|
+
return false
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// =============================================================================
|
|
242
|
+
// Error Response Configuration (Edge)
|
|
243
|
+
// =============================================================================
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Default error message for unhandled errors
|
|
247
|
+
* Override: OTEL_ERROR_MESSAGE
|
|
248
|
+
*/
|
|
249
|
+
export const DEFAULT_ERROR_MESSAGE = 'Internal server error'
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Default error code for unhandled errors
|
|
253
|
+
* Override: OTEL_ERROR_CODE
|
|
254
|
+
*/
|
|
255
|
+
export const DEFAULT_ERROR_CODE = 'INTERNAL_ERROR'
|
|
256
|
+
|
|
257
|
+
// =============================================================================
|
|
258
|
+
// Runtime Configuration Getters
|
|
259
|
+
// =============================================================================
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get configured traces path
|
|
263
|
+
* @returns {string}
|
|
264
|
+
*/
|
|
265
|
+
export function getTracesPath() {
|
|
266
|
+
return getEnv('OTEL_EXPORTER_OTLP_TRACES_PATH', DEFAULT_TRACES_PATH)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Get configured namespace
|
|
271
|
+
* @returns {string}
|
|
272
|
+
*/
|
|
273
|
+
export function getNamespace() {
|
|
274
|
+
return getEnv('OTEL_NAMESPACE', getEnv('SERVICE_NAMESPACE', DEFAULT_NAMESPACE))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Get configured CORS URLs
|
|
279
|
+
* @returns {RegExp[]}
|
|
280
|
+
*/
|
|
281
|
+
export function getCorsUrls() {
|
|
282
|
+
const envValue = getEnv('OTEL_PROPAGATE_TRACE_HEADER_CORS_URLS', '')
|
|
283
|
+
return parseCorsUrls(envValue) || DEFAULT_CORS_URLS
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get configured user interaction events
|
|
288
|
+
* @returns {string[]}
|
|
289
|
+
*/
|
|
290
|
+
export function getUserInteractionEvents() {
|
|
291
|
+
const envValue = getEnv('OTEL_USER_INTERACTION_EVENTS', '')
|
|
292
|
+
return parseEventNames(envValue) || DEFAULT_USER_INTERACTION_EVENTS
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Get configured ignore paths for middleware
|
|
297
|
+
* @returns {string[]}
|
|
298
|
+
*/
|
|
299
|
+
export function getIgnorePaths() {
|
|
300
|
+
const envValue = getEnv('OTEL_IGNORE_PATHS', '')
|
|
301
|
+
return parseIgnorePaths(envValue) || DEFAULT_IGNORE_PATHS
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get export timeout for Node.js
|
|
306
|
+
* @returns {number}
|
|
307
|
+
*/
|
|
308
|
+
export function getExportTimeoutNode() {
|
|
309
|
+
return getEnvNumber('OTEL_EXPORTER_OTLP_TIMEOUT', DEFAULT_EXPORT_TIMEOUT_NODE)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Get export timeout for Edge
|
|
314
|
+
* @returns {number}
|
|
315
|
+
*/
|
|
316
|
+
export function getExportTimeoutEdge() {
|
|
317
|
+
return getEnvNumber('OTEL_EXPORTER_OTLP_TIMEOUT_EDGE',
|
|
318
|
+
getEnvNumber('OTEL_EXPORTER_OTLP_TIMEOUT', DEFAULT_EXPORT_TIMEOUT_EDGE))
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get BatchSpanProcessor config for Node.js
|
|
323
|
+
* @returns {{ maxQueueSize: number, maxExportBatchSize: number, scheduledDelayMillis: number }}
|
|
324
|
+
*/
|
|
325
|
+
export function getBspConfigNode() {
|
|
326
|
+
return {
|
|
327
|
+
maxQueueSize: getEnvNumber('OTEL_BSP_MAX_QUEUE_SIZE', DEFAULT_BSP_MAX_QUEUE_SIZE_NODE),
|
|
328
|
+
maxExportBatchSize: getEnvNumber('OTEL_BSP_MAX_EXPORT_BATCH_SIZE', DEFAULT_BSP_MAX_EXPORT_BATCH_SIZE_NODE),
|
|
329
|
+
scheduledDelayMillis: getEnvNumber('OTEL_BSP_SCHEDULE_DELAY', DEFAULT_BSP_SCHEDULE_DELAY_NODE),
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Get BatchSpanProcessor config for Frontend
|
|
335
|
+
* @returns {{ maxQueueSize: number, maxExportBatchSize: number, scheduledDelayMillis: number }}
|
|
336
|
+
*/
|
|
337
|
+
export function getBspConfigFrontend() {
|
|
338
|
+
return {
|
|
339
|
+
maxQueueSize: getEnvNumber('OTEL_BSP_MAX_QUEUE_SIZE_FRONTEND', DEFAULT_BSP_MAX_QUEUE_SIZE_FRONTEND),
|
|
340
|
+
maxExportBatchSize: getEnvNumber('OTEL_BSP_MAX_EXPORT_BATCH_SIZE_FRONTEND', DEFAULT_BSP_MAX_EXPORT_BATCH_SIZE_FRONTEND),
|
|
341
|
+
scheduledDelayMillis: getEnvNumber('OTEL_BSP_SCHEDULE_DELAY_FRONTEND', DEFAULT_BSP_SCHEDULE_DELAY_FRONTEND),
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Get error response config for Edge
|
|
347
|
+
* @returns {{ message: string, code: string }}
|
|
348
|
+
*/
|
|
349
|
+
export function getErrorResponseConfig() {
|
|
350
|
+
return {
|
|
351
|
+
message: getEnv('OTEL_ERROR_MESSAGE', DEFAULT_ERROR_MESSAGE),
|
|
352
|
+
code: getEnv('OTEL_ERROR_CODE', DEFAULT_ERROR_CODE),
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Get trace ID display length for logs
|
|
358
|
+
* @returns {number}
|
|
359
|
+
*/
|
|
360
|
+
export function getLogTraceIdLength() {
|
|
361
|
+
return getEnvNumber('OTEL_LOG_TRACE_ID_LENGTH', DEFAULT_LOG_TRACE_ID_LENGTH)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Detect if telemetry should be enabled based on environment
|
|
366
|
+
*
|
|
367
|
+
* Rules:
|
|
368
|
+
* - Explicit setting via OTEL_ENABLED/VITE_OTEL_ENABLED takes precedence
|
|
369
|
+
* - Production: enabled by default
|
|
370
|
+
* - Development/Test: disabled by default
|
|
371
|
+
*
|
|
372
|
+
* @param {string|undefined} explicitSetting - Explicit enable setting
|
|
373
|
+
* @param {string} mode - Environment mode (production, development, test)
|
|
374
|
+
* @returns {boolean} Whether telemetry should be enabled
|
|
375
|
+
*/
|
|
376
|
+
export function detectEnabled(explicitSetting, mode) {
|
|
377
|
+
if (explicitSetting !== undefined) {
|
|
378
|
+
return explicitSetting === 'true'
|
|
379
|
+
}
|
|
380
|
+
return mode === 'production'
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Detect environment from various sources
|
|
385
|
+
*
|
|
386
|
+
* @returns {string} Environment name
|
|
387
|
+
*/
|
|
388
|
+
export function detectEnvironment() {
|
|
389
|
+
// Node.js
|
|
390
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
391
|
+
return process.env.ENVIRONMENT || process.env.NODE_ENV || 'development'
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Deno
|
|
395
|
+
if (typeof Deno !== 'undefined') {
|
|
396
|
+
return Deno.env.get('ENVIRONMENT') || 'production'
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return 'development'
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get default configuration
|
|
404
|
+
*
|
|
405
|
+
* @param {string} serviceName - Service name
|
|
406
|
+
* @returns {import('./types').ResolvedTelemetryConfig} Default configuration
|
|
407
|
+
*/
|
|
408
|
+
export function getDefaults(serviceName) {
|
|
409
|
+
return {
|
|
410
|
+
serviceName,
|
|
411
|
+
serviceVersion: DEFAULT_SERVICE_VERSION,
|
|
412
|
+
environment: detectEnvironment(),
|
|
413
|
+
endpoint: DEFAULT_ENDPOINT,
|
|
414
|
+
sampleRate: DEFAULT_SAMPLE_RATE,
|
|
415
|
+
enabled: false, // Will be resolved by detectEnabled()
|
|
416
|
+
namespace: DEFAULT_NAMESPACE,
|
|
417
|
+
resourceAttributes: {},
|
|
418
|
+
propagateTraceHeaderCorsUrls: DEFAULT_CORS_URLS,
|
|
419
|
+
instrumentation: { ...DEFAULT_INSTRUMENTATION },
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry Configuration Module
|
|
3
|
+
*
|
|
4
|
+
* Provides configuration management for telemetry with:
|
|
5
|
+
* - Smart defaults for Kabran projects
|
|
6
|
+
* - Environment variable support
|
|
7
|
+
* - Config file support
|
|
8
|
+
* - Validation
|
|
9
|
+
*
|
|
10
|
+
* @module telemetry/config
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_ENDPOINT,
|
|
15
|
+
DEFAULT_SAMPLE_RATE,
|
|
16
|
+
DEFAULT_SERVICE_VERSION,
|
|
17
|
+
DEFAULT_NAMESPACE,
|
|
18
|
+
DEFAULT_CORS_URLS,
|
|
19
|
+
DEFAULT_INSTRUMENTATION,
|
|
20
|
+
detectEnabled,
|
|
21
|
+
detectEnvironment,
|
|
22
|
+
getDefaults,
|
|
23
|
+
} from './defaults.mjs'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Define telemetry configuration with type checking and defaults
|
|
27
|
+
*
|
|
28
|
+
* @param {import('../shared/types').TelemetryConfig} config - Configuration options
|
|
29
|
+
* @returns {import('../shared/types').TelemetryConfig} Validated configuration
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { defineTelemetryConfig } from '@kabran-tecnologia/kabran-config/telemetry/config'
|
|
34
|
+
*
|
|
35
|
+
* export default defineTelemetryConfig({
|
|
36
|
+
* serviceName: 'my-app',
|
|
37
|
+
* sampleRate: 0.5,
|
|
38
|
+
* })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function defineTelemetryConfig(config) {
|
|
42
|
+
if (!config.serviceName) {
|
|
43
|
+
throw new Error('[Telemetry] serviceName is required')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return config
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolve configuration by merging:
|
|
51
|
+
* 1. Explicit config (highest priority)
|
|
52
|
+
* 2. Environment variables
|
|
53
|
+
* 3. Defaults (lowest priority)
|
|
54
|
+
*
|
|
55
|
+
* @param {import('../shared/types').TelemetryConfig} config - User configuration
|
|
56
|
+
* @param {Object} env - Environment variables object
|
|
57
|
+
* @param {string} mode - Environment mode (production, development, test)
|
|
58
|
+
* @returns {import('../shared/types').ResolvedTelemetryConfig} Resolved configuration
|
|
59
|
+
*/
|
|
60
|
+
export function resolveConfig(config, env = {}, mode = 'development') {
|
|
61
|
+
const defaults = getDefaults(config.serviceName)
|
|
62
|
+
|
|
63
|
+
// Resolve from environment variables (frontend style: VITE_*)
|
|
64
|
+
const envEndpoint = env.VITE_OTEL_ENDPOINT || env.OTEL_ENDPOINT
|
|
65
|
+
const envServiceName = env.VITE_SERVICE_NAME || env.SERVICE_NAME
|
|
66
|
+
const envServiceVersion = env.VITE_SERVICE_VERSION || env.SERVICE_VERSION
|
|
67
|
+
const envEnvironment = env.VITE_ENVIRONMENT || env.ENVIRONMENT || env.NODE_ENV
|
|
68
|
+
const envSampleRate = env.VITE_OTEL_SAMPLE_RATE || env.OTEL_SAMPLE_RATE
|
|
69
|
+
const envEnabled = env.VITE_OTEL_ENABLED || env.OTEL_ENABLED
|
|
70
|
+
|
|
71
|
+
// Merge configuration
|
|
72
|
+
const resolved = {
|
|
73
|
+
serviceName: config.serviceName || envServiceName || defaults.serviceName,
|
|
74
|
+
serviceVersion: config.serviceVersion || envServiceVersion || defaults.serviceVersion,
|
|
75
|
+
environment: config.environment || envEnvironment || defaults.environment,
|
|
76
|
+
endpoint: config.endpoint || envEndpoint || defaults.endpoint,
|
|
77
|
+
sampleRate: config.sampleRate ?? (envSampleRate ? parseFloat(envSampleRate) : defaults.sampleRate),
|
|
78
|
+
enabled: config.enabled ?? detectEnabled(envEnabled, mode),
|
|
79
|
+
namespace: config.namespace || defaults.namespace,
|
|
80
|
+
resourceAttributes: {
|
|
81
|
+
...defaults.resourceAttributes,
|
|
82
|
+
...config.resourceAttributes,
|
|
83
|
+
},
|
|
84
|
+
propagateTraceHeaderCorsUrls: config.propagateTraceHeaderCorsUrls || defaults.propagateTraceHeaderCorsUrls,
|
|
85
|
+
instrumentation: {
|
|
86
|
+
...defaults.instrumentation,
|
|
87
|
+
...config.instrumentation,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return resolved
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Validate configuration
|
|
96
|
+
*
|
|
97
|
+
* @param {import('../shared/types').ResolvedTelemetryConfig} config - Configuration to validate
|
|
98
|
+
* @returns {{ valid: boolean, errors: string[] }} Validation result
|
|
99
|
+
*/
|
|
100
|
+
export function validateConfig(config) {
|
|
101
|
+
const errors = []
|
|
102
|
+
|
|
103
|
+
if (!config.serviceName) {
|
|
104
|
+
errors.push('serviceName is required')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (config.sampleRate < 0 || config.sampleRate > 1) {
|
|
108
|
+
errors.push('sampleRate must be between 0 and 1')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (config.endpoint && !config.endpoint.startsWith('http')) {
|
|
112
|
+
errors.push('endpoint must be a valid URL')
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
valid: errors.length === 0,
|
|
117
|
+
errors,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Re-export defaults for convenience
|
|
122
|
+
export {
|
|
123
|
+
DEFAULT_ENDPOINT,
|
|
124
|
+
DEFAULT_SAMPLE_RATE,
|
|
125
|
+
DEFAULT_SERVICE_VERSION,
|
|
126
|
+
DEFAULT_NAMESPACE,
|
|
127
|
+
DEFAULT_CORS_URLS,
|
|
128
|
+
DEFAULT_INSTRUMENTATION,
|
|
129
|
+
detectEnabled,
|
|
130
|
+
detectEnvironment,
|
|
131
|
+
getDefaults,
|
|
132
|
+
}
|