securenow 3.0.5 → 3.0.7
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 +1 -1
- package/tracing.js +75 -97
package/package.json
CHANGED
package/tracing.js
CHANGED
|
@@ -1,37 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* securenow/
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - OTEL_LOG_LEVEL=info|debug # OTel internal diagnostics
|
|
16
|
-
* - SECURENOW_TEST_SPAN=1 # emit a smoke-test span on startup
|
|
4
|
+
* Preload with: NODE_OPTIONS="-r securenow/register"
|
|
5
|
+
* Env:
|
|
6
|
+
* SECURENOW_INSTANCE=http://host:4318
|
|
7
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT=...
|
|
8
|
+
* OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=...
|
|
9
|
+
* OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer abc123,foo=bar"
|
|
10
|
+
* OTEL_SERVICE_NAME=logical-name | SECURENOW_APPID=logical-name
|
|
11
|
+
* SECURENOW_NO_UUID=1 # one service.name across all workers
|
|
12
|
+
* SECURENOW_DISABLE_INSTRUMENTATIONS="pkg1,pkg2"
|
|
13
|
+
* OTEL_LOG_LEVEL=info|debug
|
|
14
|
+
* SECURENOW_TEST_SPAN=1
|
|
17
15
|
*/
|
|
18
16
|
|
|
19
17
|
const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
|
|
20
|
-
const env = k => process.env[k] ?? process.env[k.toUpperCase()] ?? process.env[k.toLowerCase()];
|
|
21
|
-
|
|
22
|
-
// ---------- Diagnostics level ----------
|
|
23
|
-
(() => {
|
|
24
|
-
const L = (env('OTEL_LOG_LEVEL') || '').toLowerCase();
|
|
25
|
-
const level =
|
|
26
|
-
L === 'debug' ? DiagLogLevel.DEBUG :
|
|
27
|
-
L === 'info' ? DiagLogLevel.INFO :
|
|
28
|
-
L === 'warn' ? DiagLogLevel.WARN :
|
|
29
|
-
L === 'error' ? DiagLogLevel.ERROR :
|
|
30
|
-
DiagLogLevel.NONE;
|
|
31
|
-
diag.setLogger(new DiagConsoleLogger(), level);
|
|
32
|
-
console.log('[securenow] preload loaded');
|
|
33
|
-
})();
|
|
34
|
-
|
|
35
18
|
const { NodeSDK } = require('@opentelemetry/sdk-node');
|
|
36
19
|
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
|
|
37
20
|
const { Resource } = require('@opentelemetry/resources');
|
|
@@ -39,103 +22,98 @@ const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventi
|
|
|
39
22
|
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
|
|
40
23
|
const { v4: uuidv4 } = require('uuid');
|
|
41
24
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
25
|
+
const env = k => process.env[k] ?? process.env[k.toUpperCase()] ?? process.env[k.toLowerCase()];
|
|
26
|
+
const parseHeaders = str => {
|
|
27
|
+
const out = {}; if (!str) return out;
|
|
28
|
+
for (const raw of String(str).split(',')) {
|
|
29
|
+
const s = raw.trim(); if (!s) continue;
|
|
30
|
+
const i = s.indexOf('='); if (i === -1) continue;
|
|
31
|
+
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Diagnostics
|
|
37
|
+
(() => {
|
|
38
|
+
const L = (env('OTEL_LOG_LEVEL') || '').toLowerCase();
|
|
39
|
+
const level = L === 'debug' ? DiagLogLevel.DEBUG :
|
|
40
|
+
L === 'info' ? DiagLogLevel.INFO :
|
|
41
|
+
L === 'warn' ? DiagLogLevel.WARN :
|
|
42
|
+
L === 'error' ? DiagLogLevel.ERROR : DiagLogLevel.NONE;
|
|
43
|
+
diag.setLogger(new DiagConsoleLogger(), level);
|
|
44
|
+
console.log('[securenow] preload loaded pid=%d', process.pid);
|
|
45
|
+
})();
|
|
50
46
|
|
|
51
|
-
//
|
|
47
|
+
// Endpoint config
|
|
52
48
|
const endpointBase = (env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'http://46.62.173.237:4318').replace(/\/$/, '');
|
|
53
|
-
const tracesUrl =
|
|
49
|
+
const tracesUrl = env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
|
|
50
|
+
const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
|
|
54
51
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const piece = raw.trim();
|
|
62
|
-
if (!piece) continue;
|
|
63
|
-
const eq = piece.indexOf('=');
|
|
64
|
-
if (eq === -1) continue;
|
|
65
|
-
const k = piece.slice(0, eq).trim();
|
|
66
|
-
const v = piece.slice(eq + 1).trim();
|
|
67
|
-
if (k) headers[k.toLowerCase()] = v;
|
|
68
|
-
}
|
|
69
|
-
return headers;
|
|
70
|
-
}
|
|
71
|
-
const headers = parseOtelHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
|
|
72
|
-
// ---------- Service name with UUID rules ----------
|
|
52
|
+
// Naming rules
|
|
53
|
+
const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
|
|
54
|
+
const baseName = rawBase || null;
|
|
55
|
+
const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
|
|
56
|
+
|
|
57
|
+
// service.name
|
|
73
58
|
let serviceName;
|
|
74
|
-
if (
|
|
75
|
-
serviceName =
|
|
59
|
+
if (baseName) {
|
|
60
|
+
serviceName = noUuid ? baseName : `${baseName}-${uuidv4()}`;
|
|
76
61
|
} else {
|
|
77
|
-
// default can also be unique to avoid collisions
|
|
78
62
|
serviceName = `securenow-free-${uuidv4()}`;
|
|
79
63
|
}
|
|
80
64
|
|
|
81
|
-
//
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
65
|
+
// service.instance.id (always appID+uuid if appID provided)
|
|
66
|
+
const instancePrefix = baseName || 'securenow';
|
|
67
|
+
const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
|
|
68
|
+
|
|
69
|
+
// One loud line per worker
|
|
70
|
+
console.log('[securenow] pid=%d SECURENOW_APPID=%s OTEL_SERVICE_NAME=%s → service.name=%s instance.id=%s',
|
|
71
|
+
process.pid,
|
|
72
|
+
JSON.stringify(env('SECURENOW_APPID')),
|
|
73
|
+
JSON.stringify(env('OTEL_SERVICE_NAME')),
|
|
74
|
+
serviceName,
|
|
75
|
+
serviceInstanceId
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Instrumentations (allow selective disables)
|
|
86
79
|
const disabledMap = {};
|
|
87
|
-
for (const
|
|
80
|
+
for (const n of (env('SECURENOW_DISABLE_INSTRUMENTATIONS') || '').split(',').map(s => s.trim()).filter(Boolean)) {
|
|
81
|
+
disabledMap[n] = { enabled: false };
|
|
82
|
+
}
|
|
88
83
|
|
|
89
|
-
//
|
|
84
|
+
// SDK
|
|
90
85
|
const traceExporter = new OTLPTraceExporter({ url: tracesUrl, headers });
|
|
91
|
-
const serviceInstanceId = `${serviceName}-${uuidv4()}`;
|
|
92
|
-
|
|
93
86
|
const sdk = new NodeSDK({
|
|
94
87
|
traceExporter,
|
|
95
|
-
instrumentations: getNodeAutoInstrumentations({
|
|
96
|
-
// Merge disabled flags (keys must match package names)
|
|
97
|
-
...disabledMap,
|
|
98
|
-
}),
|
|
88
|
+
instrumentations: getNodeAutoInstrumentations({ ...disabledMap }),
|
|
99
89
|
resource: new Resource({
|
|
100
90
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
101
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'development',
|
|
102
91
|
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: serviceInstanceId,
|
|
103
|
-
[SemanticResourceAttributes.
|
|
92
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'development',
|
|
93
|
+
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
|
|
104
94
|
}),
|
|
105
95
|
});
|
|
106
96
|
|
|
107
|
-
//
|
|
97
|
+
// Start (works if start() is sync or async)
|
|
108
98
|
(async () => {
|
|
109
99
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// Optional smoke test to verify export path
|
|
115
|
-
if ((env('SECURENOW_TEST_SPAN') || '') === '1') {
|
|
100
|
+
await Promise.resolve(sdk.start?.());
|
|
101
|
+
console.log('[securenow] OTel SDK started → %s', tracesUrl);
|
|
102
|
+
if (String(env('SECURENOW_TEST_SPAN')) === '1') {
|
|
116
103
|
const api = require('@opentelemetry/api');
|
|
117
104
|
const tracer = api.trace.getTracer('securenow-smoke');
|
|
118
|
-
const span = tracer.startSpan('securenow.startup.smoke');
|
|
119
|
-
span.setAttribute('securenow.test', true);
|
|
120
|
-
span.end();
|
|
121
|
-
console.log('[securenow] emitted startup smoke span');
|
|
105
|
+
const span = tracer.startSpan('securenow.startup.smoke'); span.end();
|
|
122
106
|
}
|
|
123
|
-
} catch (
|
|
124
|
-
console.error('[securenow] OTel start failed:',
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.error('[securenow] OTel start failed:', e && e.stack || e);
|
|
125
109
|
}
|
|
126
110
|
})();
|
|
127
111
|
|
|
128
|
-
//
|
|
112
|
+
// Shutdown
|
|
129
113
|
async function safeShutdown(sig) {
|
|
130
|
-
try {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
console.log(`[securenow] Tracing terminated on ${sig}`);
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error('[securenow] Tracing shutdown error:', err);
|
|
136
|
-
} finally {
|
|
137
|
-
process.exit(0);
|
|
138
|
-
}
|
|
114
|
+
try { await Promise.resolve(sdk.shutdown?.()); console.log(`[securenow] Tracing terminated on ${sig}`); }
|
|
115
|
+
catch (e) { console.error('[securenow] Tracing shutdown error:', e); }
|
|
116
|
+
finally { process.exit(0); }
|
|
139
117
|
}
|
|
140
118
|
process.on('SIGINT', () => safeShutdown('SIGINT'));
|
|
141
119
|
process.on('SIGTERM', () => safeShutdown('SIGTERM'));
|