securenow 7.7.4 → 7.7.5
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/NPM_README.md +11 -2
- package/SKILL-API.md +2 -2
- package/app-config.js +2 -2
- package/cli/diagnostics.js +80 -0
- package/package.json +2 -2
- package/tracing.js +2 -2
package/NPM_README.md
CHANGED
|
@@ -1261,7 +1261,7 @@ Use `npx securenow help firewall` for complete details on all layers.
|
|
|
1261
1261
|
|
|
1262
1262
|
| Variable | Description | Default |
|
|
1263
1263
|
|----------|-------------|---------|
|
|
1264
|
-
| `OTEL_LOG_LEVEL` | OpenTelemetry
|
|
1264
|
+
| `OTEL_LOG_LEVEL` | OpenTelemetry diagnostic override. Options: `debug`, `info`, `warn`, `error`, `none`. Overrides `config.otel.logLevel` for emergency debugging. | `error` |
|
|
1265
1265
|
| `SECURENOW_TEST_SPAN` | Set to `1` to emit a test span on startup. | `0` |
|
|
1266
1266
|
|
|
1267
1267
|
#### Environment
|
|
@@ -1600,7 +1600,16 @@ curl http://localhost:4318/v1/traces
|
|
|
1600
1600
|
# Should return 200 or 405 (method not allowed)
|
|
1601
1601
|
```
|
|
1602
1602
|
|
|
1603
|
-
**Check 3:
|
|
1603
|
+
**Check 3: Run doctor and enable debug diagnostics**
|
|
1604
|
+
|
|
1605
|
+
```bash
|
|
1606
|
+
npx securenow doctor --json
|
|
1607
|
+
OTEL_LOG_LEVEL=debug node -r securenow/register app.js
|
|
1608
|
+
```
|
|
1609
|
+
|
|
1610
|
+
Doctor checks OTLP reachability and flags duplicate `@opentelemetry/api` versions that can silently leave tracing on the OpenTelemetry noop provider.
|
|
1611
|
+
|
|
1612
|
+
For a persistent setting, update credentials:
|
|
1604
1613
|
|
|
1605
1614
|
```json
|
|
1606
1615
|
{
|
package/SKILL-API.md
CHANGED
|
@@ -495,7 +495,7 @@ Local development and production use `.securenow/credentials.json`. Every settin
|
|
|
495
495
|
| `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated packages to skip (e.g. `fs,dns`) | — |
|
|
496
496
|
| `SECURENOW_TEST_SPAN` | `1` to emit a test span on startup | `0` |
|
|
497
497
|
| `SECURENOW_HIDE_BANNER` | `1` to suppress free-trial upgrade banner | `0` |
|
|
498
|
-
| `OTEL_LOG_LEVEL` | SDK
|
|
498
|
+
| `OTEL_LOG_LEVEL` | SDK diagnostic override: `error`, `warn`, `info`, `debug`, or `none` | `error` |
|
|
499
499
|
| `SECURENOW_ENVIRONMENT` / `SECURENOW_DEPLOYMENT_ENVIRONMENT` / `NODE_ENV` | Legacy fallback for `config.runtime.deploymentEnvironment` | `production` |
|
|
500
500
|
|
|
501
501
|
### Firewall
|
|
@@ -634,7 +634,7 @@ On startup, securenow logs its configuration:
|
|
|
634
634
|
[securenow] Firewall: synced 142 blocked IPs
|
|
635
635
|
```
|
|
636
636
|
|
|
637
|
-
Set `config.otel.logLevel` to `debug
|
|
637
|
+
Set `config.otel.logLevel` to `debug`, or temporarily run with `OTEL_LOG_LEVEL=debug`, and run `securenow doctor --json` to troubleshoot connectivity, duplicate OpenTelemetry API packages, and provider registration issues.
|
|
638
638
|
|
|
639
639
|
**CLI equivalent** (works without booting the SDK — useful when the app won't start):
|
|
640
640
|
|
package/app-config.js
CHANGED
|
@@ -46,7 +46,7 @@ const DEFAULT_CONFIG = Object.freeze({
|
|
|
46
46
|
tracesEndpoint: null,
|
|
47
47
|
logsEndpoint: null,
|
|
48
48
|
headers: {},
|
|
49
|
-
logLevel: '
|
|
49
|
+
logLevel: 'error',
|
|
50
50
|
disableInstrumentations: [],
|
|
51
51
|
},
|
|
52
52
|
runtime: {
|
|
@@ -102,7 +102,7 @@ const CONFIG_EXPLANATIONS = Object.freeze({
|
|
|
102
102
|
'config.otel.tracesEndpoint': 'Optional full traces endpoint override, for split collectors.',
|
|
103
103
|
'config.otel.logsEndpoint': 'Optional full logs endpoint override, for split collectors.',
|
|
104
104
|
'config.otel.headers': 'Optional OTLP headers. The SDK auto-adds x-api-key from app.key when missing.',
|
|
105
|
-
'config.otel.logLevel': 'OpenTelemetry diagnostic log level:
|
|
105
|
+
'config.otel.logLevel': 'OpenTelemetry diagnostic log level: error, warn, info, debug, or none.',
|
|
106
106
|
'config.otel.disableInstrumentations': 'Optional OTel instrumentation package names to disable.',
|
|
107
107
|
'config.runtime.deploymentEnvironment': 'deployment.environment resource attribute. Set this in the credentials file for production.',
|
|
108
108
|
'config.runtime.noUuid': 'null means auto: true when app.key is present. Set true/false only for advanced routing needs.',
|
package/cli/diagnostics.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
4
6
|
const url = require('url');
|
|
5
7
|
const ui = require('./ui');
|
|
6
8
|
const config = require('./config');
|
|
@@ -37,6 +39,7 @@ function resolvedConfig(options = {}) {
|
|
|
37
39
|
loggingEnabled: appConfig.boolEnv('SECURENOW_LOGGING_ENABLED', true),
|
|
38
40
|
captureBody: appConfig.boolEnv('SECURENOW_CAPTURE_BODY', true),
|
|
39
41
|
captureMultipart: appConfig.boolEnv('SECURENOW_CAPTURE_MULTIPART', true),
|
|
42
|
+
otelLogLevel: (process.env.OTEL_LOG_LEVEL != null ? process.env.OTEL_LOG_LEVEL : appConfig.env('OTEL_LOG_LEVEL')) || 'error',
|
|
40
43
|
firewallEnabled,
|
|
41
44
|
firewallLayers: {
|
|
42
45
|
http: firewallEnabled,
|
|
@@ -47,6 +50,68 @@ function resolvedConfig(options = {}) {
|
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
function readPackageVersion(packageJsonPath, label) {
|
|
54
|
+
try {
|
|
55
|
+
if (!packageJsonPath || !fs.existsSync(packageJsonPath)) return null;
|
|
56
|
+
const realPath = fs.realpathSync(packageJsonPath);
|
|
57
|
+
const pkg = JSON.parse(fs.readFileSync(realPath, 'utf8').replace(/^\uFEFF/, ''));
|
|
58
|
+
return { label, path: realPath, version: pkg.version || null };
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resolvePackageJson(pkgName, paths, label) {
|
|
65
|
+
try {
|
|
66
|
+
let current = path.dirname(require.resolve(pkgName, { paths }));
|
|
67
|
+
while (current && current !== path.dirname(current)) {
|
|
68
|
+
const candidate = path.join(current, 'package.json');
|
|
69
|
+
const pkg = readPackageVersion(candidate, label);
|
|
70
|
+
if (pkg) return pkg;
|
|
71
|
+
current = path.dirname(current);
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function collectOtelApiPackages() {
|
|
80
|
+
const cwd = process.cwd();
|
|
81
|
+
const packageName = '@opentelemetry/api';
|
|
82
|
+
const candidates = [
|
|
83
|
+
readPackageVersion(path.join(cwd, 'node_modules', '@opentelemetry', 'api', 'package.json'), 'project node_modules'),
|
|
84
|
+
readPackageVersion(path.join(cwd, 'node_modules', 'securenow', 'node_modules', '@opentelemetry', 'api', 'package.json'), 'nested under securenow'),
|
|
85
|
+
resolvePackageJson(packageName, [cwd], 'resolved from project'),
|
|
86
|
+
resolvePackageJson(packageName, [path.resolve(__dirname, '..')], 'resolved from securenow CLI'),
|
|
87
|
+
].filter(Boolean);
|
|
88
|
+
|
|
89
|
+
const byPath = new Map();
|
|
90
|
+
for (const item of candidates) {
|
|
91
|
+
if (!byPath.has(item.path)) byPath.set(item.path, { ...item, labels: [item.label] });
|
|
92
|
+
else byPath.get(item.path).labels.push(item.label);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return [...byPath.values()].map(({ label, labels, ...rest }) => ({
|
|
96
|
+
...rest,
|
|
97
|
+
label: labels.join(', '),
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function otelApiSingletonCheck() {
|
|
102
|
+
const packages = collectOtelApiPackages();
|
|
103
|
+
const versions = [...new Set(packages.map((p) => p.version).filter(Boolean))];
|
|
104
|
+
return {
|
|
105
|
+
name: 'otel-api-singleton',
|
|
106
|
+
ok: versions.length <= 1,
|
|
107
|
+
versions,
|
|
108
|
+
packages,
|
|
109
|
+
...(versions.length > 1 ? {
|
|
110
|
+
error: `Multiple @opentelemetry/api versions detected (${versions.join(', ')}). This can leave tracing on the NoopTracerProvider.`,
|
|
111
|
+
} : {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
50
115
|
function maskSecret(value) {
|
|
51
116
|
if (!value) return '';
|
|
52
117
|
const text = String(value);
|
|
@@ -308,6 +373,7 @@ function env(_args, flags) {
|
|
|
308
373
|
firewallApiKey: cfg.apiKey ? `${cfg.apiKey.slice(0, 12)}...` : null,
|
|
309
374
|
apiUrl: cfg.apiUrl,
|
|
310
375
|
loggingEnabled: cfg.loggingEnabled,
|
|
376
|
+
otelLogLevel: cfg.otelLogLevel,
|
|
311
377
|
captureBody: cfg.captureBody,
|
|
312
378
|
captureMultipart: cfg.captureMultipart,
|
|
313
379
|
noUuid: appConfig.resolveNoUuid(),
|
|
@@ -326,6 +392,7 @@ function env(_args, flags) {
|
|
|
326
392
|
['Environment', cfg.deploymentEnvironment],
|
|
327
393
|
['Traces endpoint', cfg.tracesEndpoint],
|
|
328
394
|
['Logs endpoint', cfg.logsEndpoint],
|
|
395
|
+
['OTel diagnostics', cfg.otelLogLevel],
|
|
329
396
|
['Logging', cfg.loggingEnabled ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
330
397
|
['Body capture', cfg.captureBody ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
331
398
|
['Multipart capture', cfg.captureMultipart ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
@@ -342,6 +409,8 @@ function env(_args, flags) {
|
|
|
342
409
|
async function doctor(_args, flags) {
|
|
343
410
|
const cfg = resolvedConfig();
|
|
344
411
|
const checks = [];
|
|
412
|
+
const otelApiCheck = otelApiSingletonCheck();
|
|
413
|
+
checks.push(otelApiCheck);
|
|
345
414
|
|
|
346
415
|
const jsonHeaders = { 'Content-Type': 'application/json', ...cfg.headers };
|
|
347
416
|
|
|
@@ -386,6 +455,15 @@ async function doctor(_args, flags) {
|
|
|
386
455
|
}
|
|
387
456
|
|
|
388
457
|
const warnings = [];
|
|
458
|
+
const singletonOkMessage = otelApiCheck.ok && otelApiCheck.packages.length
|
|
459
|
+
? `OpenTelemetry API singleton OK (${otelApiCheck.versions[0] || 'unknown'})`
|
|
460
|
+
: null;
|
|
461
|
+
if (!otelApiCheck.ok) {
|
|
462
|
+
warnings.push(`${otelApiCheck.error} Align the app and SecureNow to one 1.9.x copy, then reinstall.`);
|
|
463
|
+
}
|
|
464
|
+
if (String(cfg.otelLogLevel || '').toLowerCase() === 'none') {
|
|
465
|
+
warnings.push('OpenTelemetry diagnostic log level is `none`; provider registration/export errors are hidden. Set config.otel.logLevel to `error`/`warn`, or temporarily run with OTEL_LOG_LEVEL=debug.');
|
|
466
|
+
}
|
|
389
467
|
if (!cfg.appKey) {
|
|
390
468
|
warnings.push('No app key resolved. Run `npx securenow login` or set app.key in .securenow/credentials.json.');
|
|
391
469
|
}
|
|
@@ -410,6 +488,8 @@ async function doctor(_args, flags) {
|
|
|
410
488
|
for (const w of warnings) ui.warn(w);
|
|
411
489
|
}
|
|
412
490
|
|
|
491
|
+
if (singletonOkMessage) ui.success(singletonOkMessage);
|
|
492
|
+
|
|
413
493
|
console.log('');
|
|
414
494
|
if (ok) ui.success('All checks passed.');
|
|
415
495
|
else ui.error('One or more checks failed. Run with --json for details.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securenow",
|
|
3
|
-
"version": "7.7.
|
|
3
|
+
"version": "7.7.5",
|
|
4
4
|
"description": "OpenTelemetry instrumentation for Node.js, Next.js, and Nuxt - Send traces and logs to any OTLP-compatible backend",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "register.js",
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"SKILL-API.md"
|
|
142
142
|
],
|
|
143
143
|
"dependencies": {
|
|
144
|
-
"@opentelemetry/api": "1.9.1",
|
|
144
|
+
"@opentelemetry/api": ">=1.9.0 <1.10.0",
|
|
145
145
|
"@opentelemetry/api-logs": "0.218.0",
|
|
146
146
|
"@opentelemetry/auto-instrumentations-node": "0.76.0",
|
|
147
147
|
"@opentelemetry/core": "2.7.1",
|
package/tracing.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* OTEL_EXPORTER_OTLP_HEADERS="k=v,k2=v2"
|
|
22
22
|
* SECURENOW_DISABLE_INSTRUMENTATIONS="pkg1,pkg2"
|
|
23
23
|
* SECURENOW_CAPTURE_MULTIPART=1 # capture multipart/form-data fields & file metadata (streaming, no file content buffered)
|
|
24
|
-
* OTEL_LOG_LEVEL=info|debug
|
|
24
|
+
* OTEL_LOG_LEVEL=error|warn|info|debug|none
|
|
25
25
|
* SECURENOW_TEST_SPAN=1
|
|
26
26
|
*
|
|
27
27
|
* Safety:
|
|
@@ -264,7 +264,7 @@ function collectMultipartMeta(request, contentType, sensitiveFields, maxTextFiel
|
|
|
264
264
|
})();
|
|
265
265
|
|
|
266
266
|
// -------- diagnostics --------
|
|
267
|
-
const diagLevel = (env('OTEL_LOG_LEVEL') || '').toLowerCase();
|
|
267
|
+
const diagLevel = ((process.env.OTEL_LOG_LEVEL != null ? process.env.OTEL_LOG_LEVEL : env('OTEL_LOG_LEVEL')) || '').toLowerCase();
|
|
268
268
|
(() => {
|
|
269
269
|
const level = diagLevel === 'debug' ? DiagLogLevel.DEBUG :
|
|
270
270
|
diagLevel === 'info' ? DiagLogLevel.INFO :
|