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/README.md +42 -2
- package/console-instrumentation.js +136 -0
- package/docs/INDEX.md +21 -3
- package/docs/LOGGING-GUIDE.md +708 -0
- package/docs/LOGGING-QUICKSTART.md +239 -0
- package/examples/express-with-logging.js +137 -0
- package/examples/nextjs-with-logging-example.md +301 -0
- package/package.json +11 -2
- package/tracing.d.ts +93 -0
- package/tracing.js +59 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securenow",
|
|
3
|
-
"version": "
|
|
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:
|
|
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 {
|
|
283
|
-
|
|
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
|
+
};
|