securenow 3.0.7 → 3.0.9

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.
Files changed (3) hide show
  1. package/package.json +14 -5
  2. package/register.js +14 -2
  3. package/tracing.js +34 -19
package/package.json CHANGED
@@ -1,17 +1,26 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "type": "commonjs",
5
5
  "main": "register.js",
6
- "exports": { ".": "./register.js", "./register": "./register.js", "./tracing": "./tracing.js" },
7
- "files": ["register.js", "tracing.js", "README.md"],
6
+ "exports": {
7
+ ".": "./register.js",
8
+ "./register": "./register.js",
9
+ "./tracing": "./tracing.js"
10
+ },
11
+ "files": [
12
+ "register.js",
13
+ "tracing.js",
14
+ "README.md"
15
+ ],
8
16
  "dependencies": {
9
17
  "@opentelemetry/api": "1.7.0",
10
- "@opentelemetry/sdk-node": "0.47.0",
11
- "@opentelemetry/exporter-trace-otlp-http": "0.47.0",
12
18
  "@opentelemetry/auto-instrumentations-node": "0.47.0",
19
+ "@opentelemetry/exporter-trace-otlp-http": "0.47.0",
13
20
  "@opentelemetry/resources": "1.20.0",
21
+ "@opentelemetry/sdk-node": "0.47.0",
14
22
  "@opentelemetry/semantic-conventions": "1.20.0",
23
+ "dotenv": "^17.2.1",
15
24
  "uuid": "^9.0.0"
16
25
  },
17
26
  "overrides": {
package/register.js CHANGED
@@ -1,2 +1,14 @@
1
- // tiny entry so users can always do: --require securenow/register
2
- require('./tracing');
1
+ // securenow/preload.js
2
+ 'use strict';
3
+
4
+ // load .env into process.env before anything else
5
+ try {
6
+ require('dotenv').config();
7
+ console.log('[securenow] dotenv loaded from', process.env.DOTENV_CONFIG_PATH || '.env');
8
+ } catch (e) {
9
+ // dotenv is optional — only warn if it’s missing
10
+ console.warn('[securenow] dotenv not found or failed to load');
11
+ }
12
+
13
+ // then run the real tracer preload
14
+ require('./register');
package/tracing.js CHANGED
@@ -2,16 +2,20 @@
2
2
 
3
3
  /**
4
4
  * Preload with: NODE_OPTIONS="-r securenow/register"
5
+ *
5
6
  * 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
7
+ * SECURENOW_APPID=logical-name # or OTEL_SERVICE_NAME=logical-name
8
+ * SECURENOW_NO_UUID=1 # one service.name across all workers
9
+ * SECURENOW_INSTANCE=http://host:4318 # OTLP/HTTP base (default http://46.62.173.237:4318)
10
+ * OTEL_EXPORTER_OTLP_ENDPOINT=... # alternative base
11
+ * OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=... # full traces URL
12
+ * OTEL_EXPORTER_OTLP_HEADERS="k=v,k2=v2"
12
13
  * SECURENOW_DISABLE_INSTRUMENTATIONS="pkg1,pkg2"
13
14
  * OTEL_LOG_LEVEL=info|debug
14
15
  * SECURENOW_TEST_SPAN=1
16
+ *
17
+ * Safety:
18
+ * SECURENOW_STRICT=1 -> if no appid/name is provided in cluster, exit(1) so PM2 restarts the worker
15
19
  */
16
20
 
17
21
  const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
@@ -33,7 +37,7 @@ const parseHeaders = str => {
33
37
  return out;
34
38
  };
35
39
 
36
- // Diagnostics
40
+ // -------- diagnostics --------
37
41
  (() => {
38
42
  const L = (env('OTEL_LOG_LEVEL') || '').toLowerCase();
39
43
  const level = L === 'debug' ? DiagLogLevel.DEBUG :
@@ -44,44 +48,56 @@ const parseHeaders = str => {
44
48
  console.log('[securenow] preload loaded pid=%d', process.pid);
45
49
  })();
46
50
 
47
- // Endpoint config
51
+ // -------- endpoints --------
48
52
  const endpointBase = (env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'http://46.62.173.237:4318').replace(/\/$/, '');
49
53
  const tracesUrl = env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
50
54
  const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
51
55
 
52
- // Naming rules
56
+ // -------- naming rules --------
53
57
  const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
54
58
  const baseName = rawBase || null;
55
- const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
59
+ const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
60
+ const strict = String(env('SECURENOW_STRICT')) === '1' || String(env('SECURENOW_STRICT')).toLowerCase() === 'true';
61
+ const inPm2Cluster = !!(process.env.NODE_APP_INSTANCE || process.env.pm_id);
62
+
63
+ // Fail fast in cluster if base is missing (no more "free" names)
64
+ if (!baseName && inPm2Cluster && strict) {
65
+ console.error('[securenow] FATAL: SECURENOW_APPID/OTEL_SERVICE_NAME missing in cluster (pid=%d). Exiting due to SECURENOW_STRICT=1.', process.pid);
66
+ // small delay so the log flushes
67
+ setTimeout(() => process.exit(1), 10);
68
+ }
56
69
 
57
70
  // service.name
58
71
  let serviceName;
59
72
  if (baseName) {
60
73
  serviceName = noUuid ? baseName : `${baseName}-${uuidv4()}`;
61
74
  } else {
75
+ // last-resort fallback (only if STRlCT is off). You can rename this to make it obvious in monitoring.
62
76
  serviceName = `securenow-free-${uuidv4()}`;
63
77
  }
64
78
 
65
- // service.instance.id (always appID+uuid if appID provided)
66
- const instancePrefix = baseName || 'securenow';
79
+ // service.instance.id = <appid-or-fallback>-<uuid> (unique per worker)
80
+ const instancePrefix = baseName || 'securenow';
67
81
  const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
68
82
 
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',
83
+ // Loud line per worker to prove what was used
84
+ console.log('[securenow] pid=%d SECURENOW_APPID=%s OTEL_SERVICE_NAME=%s SECURENOW_NO_UUID=%s SECURENOW_STRICT=%s → service.name=%s instance.id=%s',
71
85
  process.pid,
72
86
  JSON.stringify(env('SECURENOW_APPID')),
73
87
  JSON.stringify(env('OTEL_SERVICE_NAME')),
88
+ JSON.stringify(env('SECURENOW_NO_UUID')),
89
+ JSON.stringify(env('SECURENOW_STRICT')),
74
90
  serviceName,
75
91
  serviceInstanceId
76
92
  );
77
93
 
78
- // Instrumentations (allow selective disables)
94
+ // -------- instrumentations --------
79
95
  const disabledMap = {};
80
96
  for (const n of (env('SECURENOW_DISABLE_INSTRUMENTATIONS') || '').split(',').map(s => s.trim()).filter(Boolean)) {
81
97
  disabledMap[n] = { enabled: false };
82
98
  }
83
99
 
84
- // SDK
100
+ // -------- SDK --------
85
101
  const traceExporter = new OTLPTraceExporter({ url: tracesUrl, headers });
86
102
  const sdk = new NodeSDK({
87
103
  traceExporter,
@@ -89,12 +105,12 @@ const sdk = new NodeSDK({
89
105
  resource: new Resource({
90
106
  [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
91
107
  [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: serviceInstanceId,
92
- [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'development',
108
+ [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'production',
93
109
  [SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
94
110
  }),
95
111
  });
96
112
 
97
- // Start (works if start() is sync or async)
113
+ // -------- start / shutdown (sync/async safe) --------
98
114
  (async () => {
99
115
  try {
100
116
  await Promise.resolve(sdk.start?.());
@@ -109,7 +125,6 @@ const sdk = new NodeSDK({
109
125
  }
110
126
  })();
111
127
 
112
- // Shutdown
113
128
  async function safeShutdown(sig) {
114
129
  try { await Promise.resolve(sdk.shutdown?.()); console.log(`[securenow] Tracing terminated on ${sig}`); }
115
130
  catch (e) { console.error('[securenow] Tracing shutdown error:', e); }