securenow 4.0.12 → 5.0.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "4.0.12",
4
- "description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces to SigNoz or any OTLP backend",
3
+ "version": "5.0.0",
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",
7
7
  "types": "register.d.ts",
@@ -15,6 +15,8 @@
15
15
  "opentelemetry",
16
16
  "otel",
17
17
  "tracing",
18
+ "logging",
19
+ "logs",
18
20
  "observability",
19
21
  "apm",
20
22
  "monitoring",
@@ -42,6 +44,9 @@
42
44
  "types": "./tracing.d.ts",
43
45
  "default": "./tracing.js"
44
46
  },
47
+ "./console-instrumentation": {
48
+ "default": "./console-instrumentation.js"
49
+ },
45
50
  "./nextjs": {
46
51
  "types": "./nextjs.d.ts",
47
52
  "default": "./nextjs.js"
@@ -70,6 +75,7 @@
70
75
  "register.d.ts",
71
76
  "tracing.js",
72
77
  "tracing.d.ts",
78
+ "console-instrumentation.js",
73
79
  "nextjs.js",
74
80
  "nextjs.d.ts",
75
81
  "nextjs-auto-capture.js",
@@ -88,7 +94,9 @@
88
94
  ],
89
95
  "dependencies": {
90
96
  "@opentelemetry/api": "1.7.0",
97
+ "@opentelemetry/api-logs": "^0.47.0",
91
98
  "@opentelemetry/auto-instrumentations-node": "0.47.0",
99
+ "@opentelemetry/exporter-logs-otlp-http": "^0.47.0",
92
100
  "@opentelemetry/exporter-trace-otlp-http": "0.47.0",
93
101
  "@opentelemetry/instrumentation": "0.47.0",
94
102
  "@opentelemetry/instrumentation-document-load": "0.47.0",
@@ -97,6 +105,7 @@
97
105
  "@opentelemetry/instrumentation-user-interaction": "0.47.0",
98
106
  "@opentelemetry/instrumentation-xml-http-request": "0.47.0",
99
107
  "@opentelemetry/resources": "1.20.0",
108
+ "@opentelemetry/sdk-logs": "^0.47.0",
100
109
  "@opentelemetry/sdk-node": "0.47.0",
101
110
  "@opentelemetry/sdk-trace-web": "1.20.0",
102
111
  "@opentelemetry/semantic-conventions": "1.20.0",
package/tracing.d.ts CHANGED
@@ -70,6 +70,97 @@ export function redactGraphQLQuery(
70
70
  sensitiveFields?: string[]
71
71
  ): string;
72
72
 
73
+ /**
74
+ * OpenTelemetry Logger interface
75
+ */
76
+ export interface Logger {
77
+ emit(logRecord: LogRecord): void;
78
+ }
79
+
80
+ /**
81
+ * OpenTelemetry LogRecord interface
82
+ */
83
+ export interface LogRecord {
84
+ /**
85
+ * Severity number (OpenTelemetry standard)
86
+ * 5 = DEBUG, 9 = INFO, 13 = WARN, 17 = ERROR
87
+ */
88
+ severityNumber: number;
89
+
90
+ /**
91
+ * Human-readable severity text
92
+ */
93
+ severityText: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | string;
94
+
95
+ /**
96
+ * Log message body
97
+ */
98
+ body: string;
99
+
100
+ /**
101
+ * Structured attributes for filtering/searching
102
+ */
103
+ attributes?: Record<string, any>;
104
+ }
105
+
106
+ /**
107
+ * OpenTelemetry LoggerProvider interface
108
+ */
109
+ export interface LoggerProvider {
110
+ getLogger(name: string, version?: string): Logger;
111
+ shutdown?(): Promise<void> | void;
112
+ }
113
+
114
+ /**
115
+ * Get a logger instance for sending structured logs to SigNoz
116
+ *
117
+ * @param name - Logger name (e.g., 'my-service', 'auth-module')
118
+ * @param version - Logger version (optional, defaults to '1.0.0')
119
+ * @returns Logger instance or null if logging is not enabled
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * import { getLogger } from 'securenow/tracing';
124
+ *
125
+ * const logger = getLogger('my-service', '1.0.0');
126
+ *
127
+ * if (logger) {
128
+ * logger.emit({
129
+ * severityNumber: 9,
130
+ * severityText: 'INFO',
131
+ * body: 'User logged in',
132
+ * attributes: {
133
+ * userId: 123,
134
+ * username: 'john',
135
+ * },
136
+ * });
137
+ * }
138
+ * ```
139
+ */
140
+ export function getLogger(name?: string, version?: string): Logger | null;
141
+
142
+ /**
143
+ * Check if logging is enabled
144
+ *
145
+ * @returns true if SECURENOW_LOGGING_ENABLED=1, false otherwise
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * import { isLoggingEnabled } from 'securenow/tracing';
150
+ *
151
+ * if (isLoggingEnabled()) {
152
+ * console.log('Logging is enabled');
153
+ * }
154
+ * ```
155
+ */
156
+ export function isLoggingEnabled(): boolean;
157
+
158
+ /**
159
+ * The OpenTelemetry LoggerProvider instance (if logging is enabled)
160
+ * Use getLogger() instead of accessing this directly
161
+ */
162
+ export const loggerProvider: LoggerProvider | null;
163
+
73
164
  /**
74
165
  * Environment Variables (same as register.js):
75
166
  *
@@ -78,6 +169,7 @@ export function redactGraphQLQuery(
78
169
  * - SECURENOW_INSTANCE=http://host:4318
79
170
  *
80
171
  * Optional:
172
+ * - SECURENOW_LOGGING_ENABLED=1 # Enable logging (default: 1)
81
173
  * - SECURENOW_NO_UUID=1
82
174
  * - SECURENOW_STRICT=1
83
175
  * - SECURENOW_CAPTURE_BODY=1
@@ -86,4 +178,5 @@ export function redactGraphQLQuery(
86
178
  * - SECURENOW_DISABLE_INSTRUMENTATIONS=pkg1,pkg2
87
179
  * - OTEL_LOG_LEVEL=info|debug
88
180
  * - SECURENOW_TEST_SPAN=1
181
+ * - OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=... # Override logs endpoint
89
182
  */
package/tracing.js CHANGED
@@ -21,6 +21,8 @@
21
21
  const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
22
22
  const { NodeSDK } = require('@opentelemetry/sdk-node');
23
23
  const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
24
+ const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http');
25
+ const { LoggerProvider, BatchLogRecordProcessor } = require('@opentelemetry/sdk-logs');
24
26
  const { Resource } = require('@opentelemetry/resources');
25
27
  const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
26
28
  const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
@@ -109,6 +111,7 @@ function redactGraphQLQuery(query, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
109
111
  // -------- endpoints --------
110
112
  const endpointBase = (env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'http://46.62.173.237:4318').replace(/\/$/, '');
111
113
  const tracesUrl = env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
114
+ const logsUrl = env('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') || `${endpointBase}/v1/logs`;
112
115
  const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
113
116
 
114
117
  // -------- naming rules --------
@@ -241,6 +244,35 @@ const httpInstrumentation = new HttpInstrumentation({
241
244
  },
242
245
  });
243
246
 
247
+ // -------- Logging Configuration --------
248
+ const loggingEnabled = String(env('SECURENOW_LOGGING_ENABLED')) !== '0' && String(env('SECURENOW_LOGGING_ENABLED')).toLowerCase() !== 'false';
249
+
250
+ // Create shared resource for both traces and logs
251
+ const sharedResource = new Resource({
252
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
253
+ [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: serviceInstanceId,
254
+ [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'production',
255
+ [SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
256
+ });
257
+
258
+ // Initialize LoggerProvider if logging is enabled
259
+ let loggerProvider = null;
260
+ let globalLogger = null;
261
+
262
+ if (loggingEnabled) {
263
+ const logExporter = new OTLPLogExporter({
264
+ url: logsUrl,
265
+ headers
266
+ });
267
+
268
+ loggerProvider = new LoggerProvider({
269
+ resource: sharedResource,
270
+ processors: [new BatchLogRecordProcessor(logExporter)],
271
+ });
272
+
273
+ globalLogger = loggerProvider.getLogger('securenow', '1.0.0');
274
+ }
275
+
244
276
  // -------- SDK --------
245
277
  const traceExporter = new OTLPTraceExporter({ url: tracesUrl, headers });
246
278
  const sdk = new NodeSDK({
@@ -252,12 +284,7 @@ const sdk = new NodeSDK({
252
284
  '@opentelemetry/instrumentation-http': { enabled: false }, // We use our custom one above
253
285
  }),
254
286
  ],
255
- resource: new Resource({
256
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
257
- [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: serviceInstanceId,
258
- [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: env('NODE_ENV') || 'production',
259
- [SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
260
- }),
287
+ resource: sharedResource,
261
288
  });
262
289
 
263
290
  // -------- start / shutdown (sync/async safe) --------
@@ -265,6 +292,11 @@ const sdk = new NodeSDK({
265
292
  try {
266
293
  await Promise.resolve(sdk.start?.());
267
294
  console.log('[securenow] OTel SDK started → %s', tracesUrl);
295
+ if (loggingEnabled) {
296
+ console.log('[securenow] 📋 Logging: ENABLED → %s', logsUrl);
297
+ } else {
298
+ console.log('[securenow] 📋 Logging: DISABLED (set SECURENOW_LOGGING_ENABLED=1 to enable)');
299
+ }
268
300
  if (captureBody) {
269
301
  console.log('[securenow] 📝 Request body capture: ENABLED (max: %d bytes, redacting %d sensitive fields)', maxBodySize, allSensitiveFields.length);
270
302
  }
@@ -279,9 +311,28 @@ const sdk = new NodeSDK({
279
311
  })();
280
312
 
281
313
  async function safeShutdown(sig) {
282
- try { await Promise.resolve(sdk.shutdown?.()); console.log(`[securenow] Tracing terminated on ${sig}`); }
283
- catch (e) { console.error('[securenow] Tracing shutdown error:', e); }
314
+ try {
315
+ await Promise.resolve(sdk.shutdown?.());
316
+ if (loggerProvider) {
317
+ await Promise.resolve(loggerProvider.shutdown?.());
318
+ }
319
+ console.log(`[securenow] Tracing and logging terminated on ${sig}`);
320
+ }
321
+ catch (e) { console.error('[securenow] Shutdown error:', e); }
284
322
  finally { process.exit(0); }
285
323
  }
286
324
  process.on('SIGINT', () => safeShutdown('SIGINT'));
287
325
  process.on('SIGTERM', () => safeShutdown('SIGTERM'));
326
+
327
+ // -------- Export logger for consuming applications --------
328
+ module.exports = {
329
+ loggerProvider,
330
+ getLogger: (name = 'default', version = '1.0.0') => {
331
+ if (!loggerProvider) {
332
+ console.warn('[securenow] Logging is not enabled. Set SECURENOW_LOGGING_ENABLED=1 to enable logging.');
333
+ return null;
334
+ }
335
+ return loggerProvider.getLogger(name, version);
336
+ },
337
+ isLoggingEnabled: () => loggingEnabled,
338
+ };