securenow 6.0.0 → 6.0.1

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.
@@ -1,5 +1,39 @@
1
1
  # Changelog - Next.js Support
2
2
 
3
+ ## Version 6.0.1 (Logging hotfix)
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - **Fixed: `logger.emit()` silently dropped every log record in 6.0.0.**
8
+ `tracing.js` constructed the `LoggerProvider` with `{ processors: [new
9
+ BatchLogRecordProcessor(...)] }`, but that constructor option was only added
10
+ in `@opentelemetry/sdk-logs` 0.52 — the pinned 0.47.x silently ignores it,
11
+ leaving the provider with a `NoopLogRecordProcessor`. Every `logger.emit()`
12
+ (and every auto-captured `console.*`) was dropped, and `forceFlush()`
13
+ resolved with nothing to export. No HTTP POST ever reached `/v1/logs`.
14
+ Traces were unaffected (separate pipeline). Fixed by calling
15
+ `loggerProvider.addLogRecordProcessor(...)` after construction, matching the
16
+ 0.47.x API.
17
+
18
+ ### ✨ Improvements
19
+
20
+ - **`registerSecureNow()` (Next.js) now wires the OTLP logs pipeline.** In
21
+ 6.0.0, `securenow/nextjs` only set up traces — calling `registerSecureNow()`
22
+ with `SECURENOW_LOGGING_ENABLED=1` would log the "ENABLED" banner but emit
23
+ nothing. 6.0.1 creates a `LoggerProvider`, registers a
24
+ `BatchLogRecordProcessor(OTLPLogExporter)`, publishes it via
25
+ `logs.setGlobalLoggerProvider()`, and auto-patches
26
+ `console.log/info/warn/error/debug` to emit OTLP log records. Works on both
27
+ the Vercel (`@vercel/otel`) and self-hosted (`NodeSDK`) code paths. Graceful
28
+ flush + shutdown registered on SIGINT/SIGTERM/beforeExit.
29
+ - **`tracing.js` now calls `logs.setGlobalLoggerProvider()`** so consumers can
30
+ retrieve the logger via `@opentelemetry/api-logs` without depending on the
31
+ module export.
32
+ - **Docs updated** (`NPM_README.md`, `docs/LOGGING-QUICKSTART.md`) to
33
+ recommend `registerSecureNow` from `securenow/nextjs` for Next.js apps
34
+ instead of `securenow/register` + `securenow/console-instrumentation`
35
+ (which boots a full `NodeSDK` and conflicts with Next.js / `@vercel/otel`).
36
+
3
37
  ## Version 3.1.0 (Next.js Support Added)
4
38
 
5
39
  ### 🎉 New Features
@@ -101,13 +101,21 @@ app.listen(3000);
101
101
 
102
102
  ### Next.js
103
103
 
104
+ Next.js apps must use `securenow/nextjs` (not `securenow/register`, which
105
+ boots a full NodeSDK and conflicts with Next.js / `@vercel/otel`). Since
106
+ **6.0.1**, `registerSecureNow()` sets up the OTLP logs pipeline and auto-
107
+ patches `console.*` whenever `SECURENOW_LOGGING_ENABLED=1` is set — on both
108
+ Vercel and self-hosted (EC2, PM2, Docker) environments.
109
+
104
110
  ```typescript
105
111
  // instrumentation.ts (in project root)
106
112
  export async function register() {
107
113
  if (process.env.NEXT_RUNTIME === 'nodejs') {
114
+ // Must be set BEFORE loading securenow/nextjs
108
115
  process.env.SECURENOW_LOGGING_ENABLED = '1';
109
- await import('securenow/register');
110
- await import('securenow/console-instrumentation');
116
+
117
+ const { registerSecureNow } = await import('securenow/nextjs');
118
+ registerSecureNow({ captureBody: true });
111
119
  }
112
120
  }
113
121
  ```
@@ -119,6 +127,14 @@ SECURENOW_APPID=my-nextjs-app
119
127
  SECURENOW_INSTANCE=http://localhost:4318
120
128
  ```
121
129
 
130
+ Enable the instrumentation hook in `next.config.js`:
131
+
132
+ ```javascript
133
+ module.exports = {
134
+ experimental: { instrumentationHook: true },
135
+ };
136
+ ```
137
+
122
138
  ### Fastify
123
139
 
124
140
  ```javascript
package/nextjs.js CHANGED
@@ -261,12 +261,18 @@ function registerSecureNow(options = {}) {
261
261
  ).replace(/\/$/, '');
262
262
 
263
263
  const tracesUrl = env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
264
+ const logsUrl = env('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') || `${endpointBase}/v1/logs`;
264
265
 
265
266
  // Set environment variables for @vercel/otel to pick up
266
267
  process.env.OTEL_SERVICE_NAME = serviceName;
267
268
  process.env.OTEL_EXPORTER_OTLP_ENDPOINT = endpointBase;
268
269
  process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = tracesUrl;
269
270
 
271
+ // -------- Logging Configuration --------
272
+ // Opt-in: SECURENOW_LOGGING_ENABLED=1 (or "true").
273
+ const loggingEnabled = String(env('SECURENOW_LOGGING_ENABLED')) === '1' ||
274
+ String(env('SECURENOW_LOGGING_ENABLED')).toLowerCase() === 'true';
275
+
270
276
  console.log('[securenow] 🚀 Next.js App → service.name=%s', serviceName);
271
277
 
272
278
  // -------- Body Capture Configuration --------
@@ -506,6 +512,67 @@ function registerSecureNow(options = {}) {
506
512
  console.log('[securenow] 🎯 Vanilla SDK initialized for self-hosted environment');
507
513
  }
508
514
 
515
+ // -------- Logging pipeline (both Vercel and self-hosted) --------
516
+ // Neither @vercel/otel nor NodeSDK 0.47.x wires OTLP logs for us, so we
517
+ // create the LoggerProvider ourselves, register a BatchLogRecordProcessor
518
+ // (addLogRecordProcessor — the `processors` constructor option was only
519
+ // added in sdk-logs 0.52 and is silently ignored in 0.47), publish it as
520
+ // the global logger provider, and auto-patch console.* to emit records.
521
+ if (loggingEnabled) {
522
+ const { LoggerProvider, BatchLogRecordProcessor } = require('@opentelemetry/sdk-logs');
523
+ const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http');
524
+ const { logs } = require('@opentelemetry/api-logs');
525
+ const { Resource } = require('@opentelemetry/resources');
526
+ const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
527
+
528
+ const logResource = new Resource({
529
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
530
+ [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || env('VERCEL_ENV') || 'production',
531
+ [SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || process.env.VERCEL_GIT_COMMIT_SHA || undefined,
532
+ });
533
+
534
+ const logExporter = new OTLPLogExporter({
535
+ url: logsUrl,
536
+ headers: parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS')),
537
+ });
538
+ const loggerProvider = new LoggerProvider({ resource: logResource });
539
+ loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
540
+ logs.setGlobalLoggerProvider(loggerProvider);
541
+
542
+ const _logger = loggerProvider.getLogger('console', '1.0.0');
543
+ const _orig = { log: console.log, info: console.info, warn: console.warn, error: console.error, debug: console.debug };
544
+ const SEV = { DEBUG: 5, INFO: 9, WARN: 13, ERROR: 17 };
545
+ const _emit = (sn, st, args) => {
546
+ try {
547
+ _logger.emit({
548
+ severityNumber: sn,
549
+ severityText: st,
550
+ body: args.map(a => (typeof a === 'object' && a !== null)
551
+ ? (() => { try { return JSON.stringify(a); } catch { return String(a); } })()
552
+ : String(a)).join(' '),
553
+ attributes: { 'log.source': 'console', 'log.method': st.toLowerCase() },
554
+ });
555
+ } catch (_) {}
556
+ };
557
+ console.log = function (...a) { _emit(SEV.INFO, 'INFO', a); _orig.log.apply(console, a); };
558
+ console.info = function (...a) { _emit(SEV.INFO, 'INFO', a); _orig.info.apply(console, a); };
559
+ console.warn = function (...a) { _emit(SEV.WARN, 'WARN', a); _orig.warn.apply(console, a); };
560
+ console.error = function (...a) { _emit(SEV.ERROR, 'ERROR', a); _orig.error.apply(console, a); };
561
+ console.debug = function (...a) { _emit(SEV.DEBUG, 'DEBUG', a); _orig.debug.apply(console, a); };
562
+
563
+ const _shutdownLogs = async () => {
564
+ try { await Promise.resolve(loggerProvider.forceFlush?.()); } catch (_) {}
565
+ try { await Promise.resolve(loggerProvider.shutdown?.()); } catch (_) {}
566
+ };
567
+ process.on('SIGINT', _shutdownLogs);
568
+ process.on('SIGTERM', _shutdownLogs);
569
+ process.on('beforeExit', _shutdownLogs);
570
+
571
+ console.log('[securenow] 📋 Logging: ENABLED → %s', logsUrl);
572
+ } else {
573
+ console.log('[securenow] 📋 Logging: DISABLED (set SECURENOW_LOGGING_ENABLED=1 to enable)');
574
+ }
575
+
509
576
  isRegistered = true;
510
577
  console.log('[securenow] ✅ OpenTelemetry started for Next.js → %s', tracesUrl);
511
578
  console.log('[securenow] 📊 Auto-capturing comprehensive request metadata:');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "6.0.0",
3
+ "version": "6.0.1",
4
4
  "description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces and logs to SigNoz or any OTLP backend",
5
5
  "type": "commonjs",
6
6
  "main": "register.js",
@@ -13,11 +13,11 @@
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git+https://github.com/securenow/securenow-npm.git"
16
+ "url": "git+https://github.com/securenow-ai/securenow-npm.git"
17
17
  },
18
18
  "homepage": "https://securenow.ai",
19
19
  "bugs": {
20
- "url": "https://github.com/securenow/securenow-npm/issues",
20
+ "url": "https://github.com/securenow-ai/securenow-npm/issues",
21
21
  "email": "support@securenow.ai"
22
22
  },
23
23
  "author": "SecureNow <support@securenow.ai> (https://securenow.ai)",
package/tracing.js CHANGED
@@ -23,6 +23,7 @@ const { NodeSDK } = require('@opentelemetry/sdk-node');
23
23
  const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
24
24
  const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http');
25
25
  const { LoggerProvider, BatchLogRecordProcessor } = require('@opentelemetry/sdk-logs');
26
+ const { logs: apiLogs } = require('@opentelemetry/api-logs');
26
27
  const { Resource } = require('@opentelemetry/resources');
27
28
  const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
28
29
  const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
@@ -267,9 +268,13 @@ if (loggingEnabled) {
267
268
 
268
269
  loggerProvider = new LoggerProvider({
269
270
  resource: sharedResource,
270
- processors: [new BatchLogRecordProcessor(logExporter)],
271
271
  });
272
-
272
+ // sdk-logs 0.47.x ignores the `processors` constructor option (added in 0.52),
273
+ // so the provider would silently keep a NoopLogRecordProcessor and drop every
274
+ // emit(). Register the processor explicitly instead.
275
+ loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
276
+ apiLogs.setGlobalLoggerProvider(loggerProvider);
277
+
273
278
  globalLogger = loggerProvider.getLogger('securenow', '1.0.0');
274
279
  }
275
280