securenow 6.0.2 → 6.1.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.
Files changed (87) hide show
  1. package/CONSUMING-APPS-GUIDE.md +455 -0
  2. package/NPM_README.md +2029 -0
  3. package/README.md +297 -40
  4. package/SKILL-API.md +634 -0
  5. package/SKILL-CLI.md +454 -0
  6. package/cidr.js +83 -0
  7. package/cli/apps.js +585 -0
  8. package/cli/auth.js +280 -0
  9. package/cli/client.js +115 -0
  10. package/cli/config.js +173 -0
  11. package/cli/diagnostics.js +387 -0
  12. package/cli/firewall.js +100 -0
  13. package/cli/fp.js +638 -0
  14. package/cli/init.js +201 -0
  15. package/cli/monitor.js +440 -0
  16. package/cli/run.js +148 -0
  17. package/cli/security.js +980 -0
  18. package/cli/ui.js +386 -0
  19. package/cli/utils.js +127 -0
  20. package/cli.js +466 -455
  21. package/console-instrumentation.js +147 -136
  22. package/docs/ALL-FRAMEWORKS-QUICKSTART.md +1377 -455
  23. package/docs/API-KEYS-GUIDE.md +233 -0
  24. package/docs/ARCHITECTURE.md +3 -3
  25. package/docs/AUTO-BODY-CAPTURE.md +1 -1
  26. package/docs/AUTO-SETUP-SUMMARY.md +331 -0
  27. package/docs/AUTO-SETUP.md +4 -4
  28. package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
  29. package/docs/BODY-CAPTURE-FIX.md +261 -0
  30. package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
  31. package/docs/CHANGELOG-NEXTJS.md +1 -35
  32. package/docs/COMPLETION-REPORT.md +408 -0
  33. package/docs/CUSTOMER-GUIDE.md +16 -16
  34. package/docs/EASIEST-SETUP.md +5 -5
  35. package/docs/ENVIRONMENT-VARIABLES.md +880 -652
  36. package/docs/EXPRESS-BODY-CAPTURE.md +13 -12
  37. package/docs/EXPRESS-SETUP-GUIDE.md +719 -720
  38. package/docs/FINAL-SOLUTION.md +335 -0
  39. package/docs/FIREWALL-GUIDE.md +426 -0
  40. package/docs/IMPLEMENTATION-SUMMARY.md +410 -0
  41. package/docs/INDEX.md +22 -4
  42. package/docs/LOGGING-GUIDE.md +701 -708
  43. package/docs/LOGGING-QUICKSTART.md +234 -255
  44. package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +323 -0
  45. package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
  46. package/docs/NEXTJS-GUIDE.md +14 -14
  47. package/docs/NEXTJS-QUICKSTART.md +1 -1
  48. package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
  49. package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
  50. package/docs/NUXT-GUIDE.md +166 -0
  51. package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
  52. package/docs/REDACTION-EXAMPLES.md +1 -1
  53. package/docs/REQUEST-BODY-CAPTURE.md +19 -10
  54. package/docs/SOLUTION-SUMMARY.md +312 -0
  55. package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
  56. package/examples/README.md +6 -6
  57. package/examples/instrumentation-with-auto-capture.ts +1 -1
  58. package/examples/nextjs-env-example.txt +2 -2
  59. package/examples/nextjs-instrumentation.js +1 -1
  60. package/examples/nextjs-instrumentation.ts +1 -1
  61. package/examples/nextjs-with-logging-example.md +6 -6
  62. package/examples/nextjs-with-options.ts +1 -1
  63. package/examples/test-nextjs-setup.js +1 -1
  64. package/firewall-cloud.js +212 -0
  65. package/firewall-iptables.js +139 -0
  66. package/firewall-only.js +38 -0
  67. package/firewall-tcp.js +74 -0
  68. package/firewall.js +720 -0
  69. package/free-trial-banner.js +174 -0
  70. package/nextjs-auto-capture.js +199 -207
  71. package/nextjs-middleware.js +186 -181
  72. package/nextjs-webpack-config.js +88 -53
  73. package/nextjs-wrapper.js +158 -158
  74. package/nextjs.d.ts +1 -1
  75. package/nextjs.js +639 -647
  76. package/nuxt-server-plugin.mjs +423 -0
  77. package/nuxt.d.ts +60 -0
  78. package/nuxt.mjs +75 -0
  79. package/package.json +186 -164
  80. package/postinstall.js +6 -6
  81. package/register.d.ts +1 -1
  82. package/register.js +39 -4
  83. package/resolve-ip.js +77 -0
  84. package/tracing.d.ts +2 -1
  85. package/tracing.js +295 -34
  86. package/web-vite.mjs +239 -156
  87. package/LICENSE +0 -15
@@ -1,720 +1,719 @@
1
- # Express.js Setup Guide - SecureNow Observability
2
-
3
- Complete guide to add distributed tracing and logging to your Express.js application using SecureNow.
4
-
5
- ---
6
-
7
- ## Prerequisites
8
-
9
- - Node.js 18 or higher
10
- - An existing Express.js application
11
- - An OTLP-compatible observability backend
12
-
13
- ---
14
-
15
- ## Installation
16
-
17
- ```bash
18
- npm install securenow express
19
- ```
20
-
21
- ---
22
-
23
- ## Quick Start (5 Minutes)
24
-
25
- ### Step 1: Install Package
26
-
27
- ```bash
28
- npm install securenow
29
- ```
30
-
31
- ### Step 2: Create Environment Variables
32
-
33
- Create a `.env` file in your project root:
34
-
35
- ```env
36
- SECURENOW_APPID=my-express-app
37
- SECURENOW_INSTANCE=http://localhost:4318
38
- SECURENOW_LOGGING_ENABLED=1
39
- SECURENOW_CAPTURE_BODY=1
40
- ```
41
-
42
- ### Step 3: Initialize SecureNow
43
-
44
- Add these lines at the **very top** of your main file (before any other requires):
45
-
46
- ```javascript
47
- // app.js or server.js
48
- require('securenow/register');
49
- require('securenow/console-instrumentation');
50
-
51
- // Now your Express app
52
- const express = require('express');
53
- const app = express();
54
-
55
- app.use(express.json());
56
-
57
- app.get('/', (req, res) => {
58
- console.log('Home page accessed');
59
- res.send('Hello World');
60
- });
61
-
62
- const PORT = process.env.PORT || 3000;
63
- app.listen(PORT, () => {
64
- console.log(`Server running on port ${PORT}`);
65
- });
66
- ```
67
-
68
- ### Step 4: Run Your Application
69
-
70
- ```bash
71
- node app.js
72
- ```
73
-
74
- You should see:
75
-
76
- ```
77
- [securenow] OTel SDK started → http://localhost:4318/v1/traces
78
- [securenow] 📋 Logging: ENABLEDhttp://localhost:4318/v1/logs
79
- [securenow] Console instrumentation installed
80
- Server running on port 3000
81
- ```
82
-
83
- **Done!** Your Express app is now sending traces and logs.
84
-
85
- ---
86
-
87
- ## Complete Example
88
-
89
- ```javascript
90
- // app.js
91
- require('securenow/register');
92
- require('securenow/console-instrumentation');
93
-
94
- const express = require('express');
95
- const app = express();
96
-
97
- // Middleware
98
- app.use(express.json());
99
- app.use(express.urlencoded({ extended: true }));
100
-
101
- // Logging middleware
102
- app.use((req, res, next) => {
103
- console.info('Incoming request', {
104
- method: req.method,
105
- path: req.path,
106
- query: req.query,
107
- ip: req.ip,
108
- userAgent: req.get('user-agent'),
109
- });
110
- next();
111
- });
112
-
113
- // Routes
114
- app.get('/', (req, res) => {
115
- console.log('Home page accessed');
116
- res.json({
117
- message: 'Express with SecureNow',
118
- timestamp: new Date().toISOString(),
119
- });
120
- });
121
-
122
- app.get('/api/users', async (req, res) => {
123
- console.log('Fetching users');
124
-
125
- try {
126
- // Your database logic
127
- const users = await getUsersFromDatabase();
128
-
129
- console.info('Users fetched successfully', {
130
- count: users.length,
131
- });
132
-
133
- res.json(users);
134
- } catch (error) {
135
- console.error('Failed to fetch users', {
136
- error: error.message,
137
- stack: error.stack,
138
- });
139
- res.status(500).json({ error: 'Internal server error' });
140
- }
141
- });
142
-
143
- app.post('/api/users', async (req, res) => {
144
- console.info('Creating new user', {
145
- email: req.body.email,
146
- name: req.body.name,
147
- });
148
-
149
- try {
150
- // Validation
151
- if (!req.body.email || !req.body.name) {
152
- console.warn('Validation failed', {
153
- body: req.body,
154
- });
155
- return res.status(400).json({ error: 'Email and name required' });
156
- }
157
-
158
- // Your database logic
159
- const user = await createUserInDatabase(req.body);
160
-
161
- console.log('User created successfully', {
162
- userId: user.id,
163
- email: user.email,
164
- });
165
-
166
- res.status(201).json(user);
167
- } catch (error) {
168
- console.error('Failed to create user', {
169
- error: error.message,
170
- stack: error.stack,
171
- body: req.body,
172
- });
173
- res.status(500).json({ error: 'Internal server error' });
174
- }
175
- });
176
-
177
- // Error handling middleware
178
- app.use((err, req, res, next) => {
179
- console.error('Express error handler', {
180
- error: err.message,
181
- stack: err.stack,
182
- path: req.path,
183
- method: req.method,
184
- });
185
-
186
- res.status(500).json({
187
- error: 'Internal server error',
188
- message: err.message,
189
- });
190
- });
191
-
192
- // Start server
193
- const PORT = process.env.PORT || 3000;
194
- app.listen(PORT, () => {
195
- console.log('Express server started', {
196
- port: PORT,
197
- nodeVersion: process.version,
198
- env: process.env.NODE_ENV || 'development',
199
- });
200
- });
201
- ```
202
-
203
- ---
204
-
205
- ## Using NODE_OPTIONS (No Code Changes)
206
-
207
- If you don't want to modify your code, use `NODE_OPTIONS`:
208
-
209
- ```bash
210
- NODE_OPTIONS="-r securenow/register -r securenow/console-instrumentation" \
211
- SECURENOW_APPID=my-express-app \
212
- SECURENOW_INSTANCE=http://localhost:4318 \
213
- SECURENOW_LOGGING_ENABLED=1 \
214
- node app.js
215
- ```
216
-
217
- This works with npm scripts too:
218
-
219
- ```json
220
- {
221
- "scripts": {
222
- "start": "node app.js",
223
- "start:instrumented": "NODE_OPTIONS='-r securenow/register -r securenow/console-instrumentation' node app.js"
224
- }
225
- }
226
- ```
227
-
228
- Then run:
229
-
230
- ```bash
231
- npm run start:instrumented
232
- ```
233
-
234
- ---
235
-
236
- ## Environment Variables
237
-
238
- ### Required
239
-
240
- ```env
241
- # Your application identifier
242
- SECURENOW_APPID=my-express-app
243
-
244
- # Your OTLP collector endpoint
245
- SECURENOW_INSTANCE=http://localhost:4318
246
- ```
247
-
248
- ### Recommended
249
-
250
- ```env
251
- # Enable logging
252
- SECURENOW_LOGGING_ENABLED=1
253
-
254
- # Enable request body capture (for debugging)
255
- SECURENOW_CAPTURE_BODY=1
256
-
257
- # Max body size (default: 10KB)
258
- SECURENOW_MAX_BODY_SIZE=10240
259
-
260
- # Environment name
261
- NODE_ENV=production
262
- ```
263
-
264
- ### Optional
265
-
266
- ```env
267
- # Authentication headers for your observability backend
268
- OTEL_EXPORTER_OTLP_HEADERS=x-api-key=your-key
269
-
270
- # Disable UUID suffix on service name
271
- SECURENOW_NO_UUID=1
272
-
273
- # Enable debug logging
274
- OTEL_LOG_LEVEL=debug
275
-
276
- # Additional sensitive fields to redact
277
- SECURENOW_SENSITIVE_FIELDS=internal_token,session_key
278
- ```
279
-
280
- ---
281
-
282
- ## PM2 Setup
283
-
284
- ### Basic PM2 Configuration
285
-
286
- ```javascript
287
- // ecosystem.config.js
288
- module.exports = {
289
- apps: [{
290
- name: 'my-express-app',
291
- script: './app.js',
292
- instances: 4,
293
- exec_mode: 'cluster',
294
- node_args: '-r securenow/register -r securenow/console-instrumentation',
295
- env: {
296
- SECURENOW_APPID: 'my-express-app',
297
- SECURENOW_INSTANCE: 'http://localhost:4318',
298
- SECURENOW_LOGGING_ENABLED: '1',
299
- SECURENOW_NO_UUID: '1', // Same service name for all instances
300
- SECURENOW_CAPTURE_BODY: '1',
301
- NODE_ENV: 'production',
302
- }
303
- }]
304
- };
305
- ```
306
-
307
- Start with PM2:
308
-
309
- ```bash
310
- pm2 start ecosystem.config.js
311
- ```
312
-
313
- ### PM2 with Environment-Specific Config
314
-
315
- ```javascript
316
- // ecosystem.config.js
317
- module.exports = {
318
- apps: [{
319
- name: 'my-app',
320
- script: './app.js',
321
- instances: 4,
322
- exec_mode: 'cluster',
323
- node_args: '-r securenow/register -r securenow/console-instrumentation',
324
- env_development: {
325
- SECURENOW_APPID: 'my-app-dev',
326
- SECURENOW_INSTANCE: 'http://localhost:4318',
327
- SECURENOW_LOGGING_ENABLED: '1',
328
- SECURENOW_CAPTURE_BODY: '1',
329
- OTEL_LOG_LEVEL: 'debug',
330
- NODE_ENV: 'development',
331
- },
332
- env_production: {
333
- SECURENOW_APPID: 'my-app-prod',
334
- SECURENOW_INSTANCE: 'http://collector.prod:4318',
335
- SECURENOW_LOGGING_ENABLED: '1',
336
- SECURENOW_CAPTURE_BODY: '0', // Disable in production
337
- SECURENOW_NO_UUID: '1',
338
- NODE_ENV: 'production',
339
- }
340
- }]
341
- };
342
- ```
343
-
344
- Run with specific environment:
345
-
346
- ```bash
347
- # Development
348
- pm2 start ecosystem.config.js
349
-
350
- # Production
351
- pm2 start ecosystem.config.js --env production
352
- ```
353
-
354
- ---
355
-
356
- ## TypeScript Setup
357
-
358
- ### Step 1: Install
359
-
360
- ```bash
361
- npm install securenow typescript @types/node @types/express ts-node
362
- ```
363
-
364
- ### Step 2: Initialize SecureNow
365
-
366
- ```typescript
367
- // app.ts
368
- require('securenow/register');
369
- require('securenow/console-instrumentation');
370
-
371
- import express, { Request, Response, NextFunction } from 'express';
372
-
373
- const app = express();
374
-
375
- app.use(express.json());
376
-
377
- app.get('/', (req: Request, res: Response) => {
378
- console.log('Home page accessed');
379
- res.json({ message: 'Hello World' });
380
- });
381
-
382
- app.post('/api/users', async (req: Request, res: Response) => {
383
- console.info('Creating user', { body: req.body });
384
-
385
- try {
386
- // Your logic
387
- const user = await createUser(req.body);
388
- console.log('User created', { userId: user.id });
389
- res.status(201).json(user);
390
- } catch (error) {
391
- console.error('Failed to create user', { error });
392
- res.status(500).json({ error: 'Internal server error' });
393
- }
394
- });
395
-
396
- // Error handler
397
- app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
398
- console.error('Express error', {
399
- error: err.message,
400
- stack: err.stack,
401
- path: req.path,
402
- });
403
- res.status(500).json({ error: 'Internal server error' });
404
- });
405
-
406
- const PORT = process.env.PORT || 3000;
407
- app.listen(PORT, () => {
408
- console.log(`Server running on port ${PORT}`);
409
- });
410
- ```
411
-
412
- ### Step 3: Run with ts-node
413
-
414
- ```bash
415
- npx ts-node app.ts
416
- ```
417
-
418
- Or compile and run:
419
-
420
- ```bash
421
- npx tsc
422
- node dist/app.js
423
- ```
424
-
425
- ---
426
-
427
- ## Advanced Features
428
-
429
- ### Request Body Capture
430
-
431
- Enable to see request bodies in your traces:
432
-
433
- ```env
434
- SECURENOW_CAPTURE_BODY=1
435
- SECURENOW_MAX_BODY_SIZE=10240
436
- ```
437
-
438
- **Automatically redacted fields:** passwords, tokens, api_keys, card numbers, etc.
439
-
440
- **Add custom redaction:**
441
-
442
- ```env
443
- SECURENOW_SENSITIVE_FIELDS=internal_token,session_key
444
- ```
445
-
446
- ### Custom Logger
447
-
448
- For more control, use the direct logger API:
449
-
450
- ```javascript
451
- const { getLogger } = require('securenow/tracing');
452
-
453
- const logger = getLogger('express-app', '1.0.0');
454
-
455
- app.post('/api/users', async (req, res) => {
456
- logger.emit({
457
- severityNumber: 9,
458
- severityText: 'INFO',
459
- body: 'User creation started',
460
- attributes: {
461
- email: req.body.email,
462
- ip: req.ip,
463
- timestamp: Date.now(),
464
- },
465
- });
466
-
467
- // Your logic...
468
- });
469
- ```
470
-
471
- ### Disable Specific Instrumentations
472
-
473
- If you don't need certain instrumentations:
474
-
475
- ```env
476
- SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
477
- ```
478
-
479
- ---
480
-
481
- ## Docker Setup
482
-
483
- ### Dockerfile
484
-
485
- ```dockerfile
486
- FROM node:20-alpine
487
-
488
- WORKDIR /app
489
-
490
- # Copy package files
491
- COPY package*.json ./
492
-
493
- # Install dependencies
494
- RUN npm install
495
-
496
- # Copy application code
497
- COPY . .
498
-
499
- # Set environment variables
500
- ENV SECURENOW_APPID=my-express-app
501
- ENV SECURENOW_INSTANCE=http://collector:4318
502
- ENV SECURENOW_LOGGING_ENABLED=1
503
- ENV NODE_ENV=production
504
-
505
- # Expose port
506
- EXPOSE 3000
507
-
508
- # Start application
509
- CMD ["node", "app.js"]
510
- ```
511
-
512
- ### docker-compose.yml
513
-
514
- ```yaml
515
- version: '3.8'
516
-
517
- services:
518
- app:
519
- build: .
520
- ports:
521
- - "3000:3000"
522
- environment:
523
- - SECURENOW_APPID=my-express-app
524
- - SECURENOW_INSTANCE=http://collector:4318
525
- - SECURENOW_LOGGING_ENABLED=1
526
- - SECURENOW_CAPTURE_BODY=1
527
- - NODE_ENV=production
528
- depends_on:
529
- - collector
530
-
531
- collector:
532
- image: otel/opentelemetry-collector:latest
533
- ports:
534
- - "4318:4318"
535
- volumes:
536
- - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
537
- command: ["--config=/etc/otel-collector-config.yaml"]
538
- ```
539
-
540
- Run:
541
-
542
- ```bash
543
- docker-compose up
544
- ```
545
-
546
- ---
547
-
548
- ## Troubleshooting
549
-
550
- ### Traces Not Appearing
551
-
552
- **Check initialization order:**
553
-
554
- ```javascript
555
- // ✅ Correct
556
- require('securenow/register');
557
- require('securenow/console-instrumentation');
558
- const express = require('express');
559
-
560
- // Wrong
561
- const express = require('express');
562
- require('securenow/register');
563
- ```
564
-
565
- **Enable debug logging:**
566
-
567
- ```bash
568
- export OTEL_LOG_LEVEL=debug
569
- node app.js
570
- ```
571
-
572
- **Verify collector is running:**
573
-
574
- ```bash
575
- curl http://localhost:4318/v1/traces
576
- # Should return 200 or 405
577
- ```
578
-
579
- ### Logs Not Appearing
580
-
581
- **Check logging is enabled:**
582
-
583
- ```bash
584
- echo $SECURENOW_LOGGING_ENABLED
585
- # Should output: 1
586
- ```
587
-
588
- **Verify console instrumentation:**
589
-
590
- Look for this in the output:
591
- ```
592
- [securenow] Console instrumentation installed
593
- ```
594
-
595
- ### PM2 Issues
596
-
597
- **Different service names for each worker:**
598
-
599
- ```env
600
- # Add this to use same service name
601
- SECURENOW_NO_UUID=1
602
- ```
603
-
604
- **Workers not instrumented:**
605
-
606
- Use `node_args` in PM2 config:
607
-
608
- ```javascript
609
- {
610
- node_args: '-r securenow/register -r securenow/console-instrumentation'
611
- }
612
- ```
613
-
614
- ---
615
-
616
- ## Best Practices
617
-
618
- ### 1. Use Structured Logging
619
-
620
- ```javascript
621
- // Bad
622
- console.log('User 123 logged in');
623
-
624
- // Good
625
- console.log('User logged in', {
626
- userId: 123,
627
- email: 'user@example.com',
628
- timestamp: Date.now(),
629
- });
630
- ```
631
-
632
- ### 2. Log at Appropriate Levels
633
-
634
- ```javascript
635
- // Normal operations
636
- console.info('Request processed', { userId: 123 });
637
-
638
- // Warnings
639
- console.warn('API rate limit approaching', { remaining: 10 });
640
-
641
- // Errors
642
- console.error('Database error', { error: err.message });
643
- ```
644
-
645
- ### 3. Use Middleware for Request Logging
646
-
647
- ```javascript
648
- app.use((req, res, next) => {
649
- console.info('Request received', {
650
- method: req.method,
651
- path: req.path,
652
- ip: req.ip,
653
- });
654
- next();
655
- });
656
- ```
657
-
658
- ### 4. Don't Enable Body Capture in Production
659
-
660
- ```env
661
- # .env.development
662
- SECURENOW_CAPTURE_BODY=1
663
-
664
- # .env.production
665
- SECURENOW_CAPTURE_BODY=0
666
- ```
667
-
668
- ---
669
-
670
- ## Complete Environment Variables Reference
671
-
672
- ```env
673
- # === Required ===
674
- SECURENOW_APPID=my-express-app
675
- SECURENOW_INSTANCE=http://localhost:4318
676
-
677
- # === Logging ===
678
- SECURENOW_LOGGING_ENABLED=1
679
-
680
- # === Request Body Capture ===
681
- SECURENOW_CAPTURE_BODY=1
682
- SECURENOW_MAX_BODY_SIZE=10240
683
- SECURENOW_SENSITIVE_FIELDS=custom_field1,custom_field2
684
-
685
- # === Service Naming ===
686
- SECURENOW_NO_UUID=1
687
- OTEL_SERVICE_NAME=my-express-app
688
-
689
- # === Connection ===
690
- OTEL_EXPORTER_OTLP_HEADERS=x-api-key=your-key
691
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
692
- OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logs
693
-
694
- # === Debugging ===
695
- OTEL_LOG_LEVEL=debug
696
- SECURENOW_TEST_SPAN=1
697
-
698
- # === Environment ===
699
- NODE_ENV=production
700
- ```
701
-
702
- ---
703
-
704
- ## Next Steps
705
-
706
- - Check your observability backend to see traces and logs
707
- - Set up dashboards and alerts
708
- - Explore the captured data to understand your application behavior
709
-
710
- ---
711
-
712
- ## Support
713
-
714
- - **Documentation:** [Main Docs](../README.md)
715
- - **Examples:** [Express Examples](../examples/)
716
- - **Issues:** GitHub Issues
717
-
718
- ---
719
-
720
- **Your Express app is now fully observable!** 🎉
1
+ # Express.js Setup Guide - SecureNow Observability
2
+
3
+ Complete guide to add distributed tracing and logging to your Express.js application using SecureNow.
4
+ This setup has been **tested end-to-end** with traces and logs flowing to the SecureNow dashboard.
5
+
6
+ ---
7
+
8
+ ## Prerequisites
9
+
10
+ - Node.js 18 or higher
11
+ - An existing Express.js application
12
+ - A SecureNow account (or any OTLP-compatible backend)
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install securenow
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Quick Start (5 Minutes)
25
+
26
+ ### Step 1: Create Environment Variables
27
+
28
+ Create a `.env` file in your project root:
29
+
30
+ ```env
31
+ SECURENOW_APPID=my-express-app
32
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
33
+ SECURENOW_LOGGING_ENABLED=1
34
+ SECURENOW_NO_UUID=1
35
+ ```
36
+
37
+ > Get your `SECURENOW_APPID` by running `npx securenow apps create my-express-app`.
38
+
39
+ ### Step 2: Initialize SecureNow
40
+
41
+ Add `require('securenow/register')` at the **very top** of your main file (before any other requires):
42
+
43
+ ```javascript
44
+ // app.js
45
+ require('securenow/register');
46
+
47
+ const express = require('express');
48
+ const app = express();
49
+
50
+ app.use(express.json());
51
+
52
+ app.get('/health', (req, res) => {
53
+ res.json({ status: 'ok' });
54
+ });
55
+
56
+ app.post('/tasks', (req, res) => {
57
+ const { title } = req.body;
58
+ if (!title) return res.status(400).json({ error: 'title is required' });
59
+ console.log('Created task:', title);
60
+ res.status(201).json({ id: '1', title });
61
+ });
62
+
63
+ const PORT = process.env.PORT || 3000;
64
+ app.listen(PORT, () => {
65
+ console.log(`Server running on port ${PORT}`);
66
+ });
67
+ ```
68
+
69
+ ### Step 3: Run Your Application
70
+
71
+ ```bash
72
+ node app.js
73
+ ```
74
+
75
+ You should see:
76
+
77
+ ```
78
+ [securenow] OTel SDK startedhttps://freetrial.securenow.ai:4318/v1/traces
79
+ [securenow] 📋 Logging: ENABLED → https://freetrial.securenow.ai:4318/v1/logs
80
+ Server running on port 3000
81
+ ```
82
+
83
+ **Done!** Your Express app is now sending traces and logs.
84
+
85
+ Since **v5.6.0**, when `SECURENOW_LOGGING_ENABLED=1`, all `console.log`/`warn`/`error` calls are **automatically** forwarded as OTLP log records — no separate `require('securenow/console-instrumentation')` needed.
86
+
87
+ ---
88
+
89
+ ## Complete Example
90
+
91
+ ```javascript
92
+ // app.js
93
+ require('securenow/register');
94
+
95
+ const express = require('express');
96
+ const app = express();
97
+
98
+ // Middleware
99
+ app.use(express.json());
100
+ app.use(express.urlencoded({ extended: true }));
101
+
102
+ // Logging middleware
103
+ app.use((req, res, next) => {
104
+ console.info('Incoming request', {
105
+ method: req.method,
106
+ path: req.path,
107
+ query: req.query,
108
+ ip: req.ip,
109
+ userAgent: req.get('user-agent'),
110
+ });
111
+ next();
112
+ });
113
+
114
+ // Routes
115
+ app.get('/', (req, res) => {
116
+ console.log('Home page accessed');
117
+ res.json({
118
+ message: 'Express with SecureNow',
119
+ timestamp: new Date().toISOString(),
120
+ });
121
+ });
122
+
123
+ app.get('/api/users', async (req, res) => {
124
+ console.log('Fetching users');
125
+
126
+ try {
127
+ // Your database logic
128
+ const users = await getUsersFromDatabase();
129
+
130
+ console.info('Users fetched successfully', {
131
+ count: users.length,
132
+ });
133
+
134
+ res.json(users);
135
+ } catch (error) {
136
+ console.error('Failed to fetch users', {
137
+ error: error.message,
138
+ stack: error.stack,
139
+ });
140
+ res.status(500).json({ error: 'Internal server error' });
141
+ }
142
+ });
143
+
144
+ app.post('/api/users', async (req, res) => {
145
+ console.info('Creating new user', {
146
+ email: req.body.email,
147
+ name: req.body.name,
148
+ });
149
+
150
+ try {
151
+ // Validation
152
+ if (!req.body.email || !req.body.name) {
153
+ console.warn('Validation failed', {
154
+ body: req.body,
155
+ });
156
+ return res.status(400).json({ error: 'Email and name required' });
157
+ }
158
+
159
+ // Your database logic
160
+ const user = await createUserInDatabase(req.body);
161
+
162
+ console.log('User created successfully', {
163
+ userId: user.id,
164
+ email: user.email,
165
+ });
166
+
167
+ res.status(201).json(user);
168
+ } catch (error) {
169
+ console.error('Failed to create user', {
170
+ error: error.message,
171
+ stack: error.stack,
172
+ body: req.body,
173
+ });
174
+ res.status(500).json({ error: 'Internal server error' });
175
+ }
176
+ });
177
+
178
+ // Error handling middleware
179
+ app.use((err, req, res, next) => {
180
+ console.error('Express error handler', {
181
+ error: err.message,
182
+ stack: err.stack,
183
+ path: req.path,
184
+ method: req.method,
185
+ });
186
+
187
+ res.status(500).json({
188
+ error: 'Internal server error',
189
+ message: err.message,
190
+ });
191
+ });
192
+
193
+ // Start server
194
+ const PORT = process.env.PORT || 3000;
195
+ app.listen(PORT, () => {
196
+ console.log('Express server started', {
197
+ port: PORT,
198
+ nodeVersion: process.version,
199
+ env: process.env.NODE_ENV || 'development',
200
+ });
201
+ });
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Using NODE_OPTIONS (No Code Changes)
207
+
208
+ If you don't want to modify your code, use `NODE_OPTIONS`:
209
+
210
+ ```bash
211
+ NODE_OPTIONS="-r securenow/register" \
212
+ SECURENOW_APPID=my-express-app \
213
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318 \
214
+ SECURENOW_LOGGING_ENABLED=1 \
215
+ node app.js
216
+ ```
217
+
218
+ This works with npm scripts too:
219
+
220
+ ```json
221
+ {
222
+ "scripts": {
223
+ "start": "node app.js",
224
+ "start:instrumented": "NODE_OPTIONS='-r securenow/register' node app.js"
225
+ }
226
+ }
227
+ ```
228
+
229
+ Then run:
230
+
231
+ ```bash
232
+ npm run start:instrumented
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Environment Variables
238
+
239
+ ### Required
240
+
241
+ ```env
242
+ # Your application identifier
243
+ SECURENOW_APPID=my-express-app
244
+
245
+ # Your OTLP collector endpoint
246
+ SECURENOW_INSTANCE=http://localhost:4318
247
+ ```
248
+
249
+ ### Recommended
250
+
251
+ ```env
252
+ # Enable logging
253
+ SECURENOW_LOGGING_ENABLED=1
254
+
255
+ # Enable request body capture (for debugging)
256
+ SECURENOW_CAPTURE_BODY=1
257
+
258
+ # Max body size (default: 10KB)
259
+ SECURENOW_MAX_BODY_SIZE=10240
260
+
261
+ # Environment name
262
+ NODE_ENV=production
263
+ ```
264
+
265
+ ### Optional
266
+
267
+ ```env
268
+ # Authentication headers for your observability backend
269
+ OTEL_EXPORTER_OTLP_HEADERS=x-api-key=your-key
270
+
271
+ # Disable UUID suffix on service name
272
+ SECURENOW_NO_UUID=1
273
+
274
+ # Enable debug logging
275
+ OTEL_LOG_LEVEL=debug
276
+
277
+ # Additional sensitive fields to redact
278
+ SECURENOW_SENSITIVE_FIELDS=internal_token,session_key
279
+ ```
280
+
281
+ ---
282
+
283
+ ## PM2 Setup
284
+
285
+ ### Basic PM2 Configuration
286
+
287
+ ```javascript
288
+ // ecosystem.config.js
289
+ module.exports = {
290
+ apps: [{
291
+ name: 'my-express-app',
292
+ script: './app.js',
293
+ instances: 4,
294
+ exec_mode: 'cluster',
295
+ node_args: '-r securenow/register',
296
+ env: {
297
+ SECURENOW_APPID: 'my-express-app',
298
+ SECURENOW_INSTANCE: 'http://localhost:4318',
299
+ SECURENOW_LOGGING_ENABLED: '1',
300
+ SECURENOW_NO_UUID: '1', // Same service name for all instances
301
+ SECURENOW_CAPTURE_BODY: '1',
302
+ NODE_ENV: 'production',
303
+ }
304
+ }]
305
+ };
306
+ ```
307
+
308
+ Start with PM2:
309
+
310
+ ```bash
311
+ pm2 start ecosystem.config.js
312
+ ```
313
+
314
+ ### PM2 with Environment-Specific Config
315
+
316
+ ```javascript
317
+ // ecosystem.config.js
318
+ module.exports = {
319
+ apps: [{
320
+ name: 'my-app',
321
+ script: './app.js',
322
+ instances: 4,
323
+ exec_mode: 'cluster',
324
+ node_args: '-r securenow/register',
325
+ env_development: {
326
+ SECURENOW_APPID: 'my-app-dev',
327
+ SECURENOW_INSTANCE: 'http://localhost:4318',
328
+ SECURENOW_LOGGING_ENABLED: '1',
329
+ SECURENOW_CAPTURE_BODY: '1',
330
+ OTEL_LOG_LEVEL: 'debug',
331
+ NODE_ENV: 'development',
332
+ },
333
+ env_production: {
334
+ SECURENOW_APPID: 'my-app-prod',
335
+ SECURENOW_INSTANCE: 'http://collector.prod:4318',
336
+ SECURENOW_LOGGING_ENABLED: '1',
337
+ SECURENOW_CAPTURE_BODY: '0', // Disable in production
338
+ SECURENOW_NO_UUID: '1',
339
+ NODE_ENV: 'production',
340
+ }
341
+ }]
342
+ };
343
+ ```
344
+
345
+ Run with specific environment:
346
+
347
+ ```bash
348
+ # Development
349
+ pm2 start ecosystem.config.js
350
+
351
+ # Production
352
+ pm2 start ecosystem.config.js --env production
353
+ ```
354
+
355
+ ---
356
+
357
+ ## TypeScript Setup
358
+
359
+ ### Step 1: Install
360
+
361
+ ```bash
362
+ npm install securenow typescript @types/node @types/express ts-node
363
+ ```
364
+
365
+ ### Step 2: Initialize SecureNow
366
+
367
+ ```typescript
368
+ // app.ts
369
+ require('securenow/register');
370
+
371
+ import express, { Request, Response, NextFunction } from 'express';
372
+
373
+ const app = express();
374
+
375
+ app.use(express.json());
376
+
377
+ app.get('/', (req: Request, res: Response) => {
378
+ console.log('Home page accessed');
379
+ res.json({ message: 'Hello World' });
380
+ });
381
+
382
+ app.post('/api/users', async (req: Request, res: Response) => {
383
+ console.info('Creating user', { body: req.body });
384
+
385
+ try {
386
+ // Your logic
387
+ const user = await createUser(req.body);
388
+ console.log('User created', { userId: user.id });
389
+ res.status(201).json(user);
390
+ } catch (error) {
391
+ console.error('Failed to create user', { error });
392
+ res.status(500).json({ error: 'Internal server error' });
393
+ }
394
+ });
395
+
396
+ // Error handler
397
+ app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
398
+ console.error('Express error', {
399
+ error: err.message,
400
+ stack: err.stack,
401
+ path: req.path,
402
+ });
403
+ res.status(500).json({ error: 'Internal server error' });
404
+ });
405
+
406
+ const PORT = process.env.PORT || 3000;
407
+ app.listen(PORT, () => {
408
+ console.log(`Server running on port ${PORT}`);
409
+ });
410
+ ```
411
+
412
+ ### Step 3: Run with ts-node
413
+
414
+ ```bash
415
+ npx ts-node app.ts
416
+ ```
417
+
418
+ Or compile and run:
419
+
420
+ ```bash
421
+ npx tsc
422
+ node dist/app.js
423
+ ```
424
+
425
+ ---
426
+
427
+ ## Advanced Features
428
+
429
+ ### Request Body Capture
430
+
431
+ Enable to see request bodies in your traces:
432
+
433
+ ```env
434
+ SECURENOW_CAPTURE_BODY=1
435
+ SECURENOW_MAX_BODY_SIZE=10240
436
+ ```
437
+
438
+ **Automatically redacted fields:** passwords, tokens, api_keys, card numbers, etc.
439
+
440
+ **Add custom redaction:**
441
+
442
+ ```env
443
+ SECURENOW_SENSITIVE_FIELDS=internal_token,session_key
444
+ ```
445
+
446
+ ### Custom Logger
447
+
448
+ For more control, use the direct logger API:
449
+
450
+ ```javascript
451
+ const { getLogger } = require('securenow/tracing');
452
+
453
+ const logger = getLogger('express-app', '1.0.0');
454
+
455
+ app.post('/api/users', async (req, res) => {
456
+ logger.emit({
457
+ severityNumber: 9,
458
+ severityText: 'INFO',
459
+ body: 'User creation started',
460
+ attributes: {
461
+ email: req.body.email,
462
+ ip: req.ip,
463
+ timestamp: Date.now(),
464
+ },
465
+ });
466
+
467
+ // Your logic...
468
+ });
469
+ ```
470
+
471
+ ### Disable Specific Instrumentations
472
+
473
+ If you don't need certain instrumentations:
474
+
475
+ ```env
476
+ SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Docker Setup
482
+
483
+ ### Dockerfile
484
+
485
+ ```dockerfile
486
+ FROM node:20-alpine
487
+
488
+ WORKDIR /app
489
+
490
+ # Copy package files
491
+ COPY package*.json ./
492
+
493
+ # Install dependencies
494
+ RUN npm install
495
+
496
+ # Copy application code
497
+ COPY . .
498
+
499
+ # Set environment variables
500
+ ENV SECURENOW_APPID=my-express-app
501
+ ENV SECURENOW_INSTANCE=http://collector:4318
502
+ ENV SECURENOW_LOGGING_ENABLED=1
503
+ ENV NODE_ENV=production
504
+
505
+ # Expose port
506
+ EXPOSE 3000
507
+
508
+ # Start application
509
+ CMD ["node", "app.js"]
510
+ ```
511
+
512
+ ### docker-compose.yml
513
+
514
+ ```yaml
515
+ version: '3.8'
516
+
517
+ services:
518
+ app:
519
+ build: .
520
+ ports:
521
+ - "3000:3000"
522
+ environment:
523
+ - SECURENOW_APPID=my-express-app
524
+ - SECURENOW_INSTANCE=http://collector:4318
525
+ - SECURENOW_LOGGING_ENABLED=1
526
+ - SECURENOW_CAPTURE_BODY=1
527
+ - NODE_ENV=production
528
+ depends_on:
529
+ - collector
530
+
531
+ collector:
532
+ image: otel/opentelemetry-collector:latest
533
+ ports:
534
+ - "4318:4318"
535
+ volumes:
536
+ - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
537
+ command: ["--config=/etc/otel-collector-config.yaml"]
538
+ ```
539
+
540
+ Run:
541
+
542
+ ```bash
543
+ docker-compose up
544
+ ```
545
+
546
+ ---
547
+
548
+ ## Troubleshooting
549
+
550
+ ### Traces Not Appearing
551
+
552
+ **Check initialization order:**
553
+
554
+ ```javascript
555
+ // ✅ Correct
556
+ require('securenow/register');
557
+ const express = require('express');
558
+
559
+ // ❌ Wrong
560
+ const express = require('express');
561
+ require('securenow/register');
562
+ ```
563
+
564
+ **Enable debug logging:**
565
+
566
+ ```bash
567
+ export OTEL_LOG_LEVEL=debug
568
+ node app.js
569
+ ```
570
+
571
+ **Verify collector is running:**
572
+
573
+ ```bash
574
+ curl http://localhost:4318/v1/traces
575
+ # Should return 200 or 405
576
+ ```
577
+
578
+ ### Logs Not Appearing
579
+
580
+ **Check logging is enabled:**
581
+
582
+ ```bash
583
+ echo $SECURENOW_LOGGING_ENABLED
584
+ # Should output: 1
585
+ ```
586
+
587
+ **Verify console instrumentation:**
588
+
589
+ Look for this in the output:
590
+ ```
591
+ [securenow] Console instrumentation installed
592
+ ```
593
+
594
+ ### PM2 Issues
595
+
596
+ **Different service names for each worker:**
597
+
598
+ ```env
599
+ # Add this to use same service name
600
+ SECURENOW_NO_UUID=1
601
+ ```
602
+
603
+ **Workers not instrumented:**
604
+
605
+ Use `node_args` in PM2 config:
606
+
607
+ ```javascript
608
+ {
609
+ node_args: '-r securenow/register'
610
+ }
611
+ ```
612
+
613
+ ---
614
+
615
+ ## Best Practices
616
+
617
+ ### 1. Use Structured Logging
618
+
619
+ ```javascript
620
+ // ❌ Bad
621
+ console.log('User 123 logged in');
622
+
623
+ // ✅ Good
624
+ console.log('User logged in', {
625
+ userId: 123,
626
+ email: 'user@example.com',
627
+ timestamp: Date.now(),
628
+ });
629
+ ```
630
+
631
+ ### 2. Log at Appropriate Levels
632
+
633
+ ```javascript
634
+ // Normal operations
635
+ console.info('Request processed', { userId: 123 });
636
+
637
+ // Warnings
638
+ console.warn('API rate limit approaching', { remaining: 10 });
639
+
640
+ // Errors
641
+ console.error('Database error', { error: err.message });
642
+ ```
643
+
644
+ ### 3. Use Middleware for Request Logging
645
+
646
+ ```javascript
647
+ app.use((req, res, next) => {
648
+ console.info('Request received', {
649
+ method: req.method,
650
+ path: req.path,
651
+ ip: req.ip,
652
+ });
653
+ next();
654
+ });
655
+ ```
656
+
657
+ ### 4. Don't Enable Body Capture in Production
658
+
659
+ ```env
660
+ # .env.development
661
+ SECURENOW_CAPTURE_BODY=1
662
+
663
+ # .env.production
664
+ SECURENOW_CAPTURE_BODY=0
665
+ ```
666
+
667
+ ---
668
+
669
+ ## Complete Environment Variables Reference
670
+
671
+ ```env
672
+ # === Required ===
673
+ SECURENOW_APPID=my-express-app
674
+ SECURENOW_INSTANCE=http://localhost:4318
675
+
676
+ # === Logging ===
677
+ SECURENOW_LOGGING_ENABLED=1
678
+
679
+ # === Request Body Capture ===
680
+ SECURENOW_CAPTURE_BODY=1
681
+ SECURENOW_MAX_BODY_SIZE=10240
682
+ SECURENOW_SENSITIVE_FIELDS=custom_field1,custom_field2
683
+
684
+ # === Service Naming ===
685
+ SECURENOW_NO_UUID=1
686
+ OTEL_SERVICE_NAME=my-express-app
687
+
688
+ # === Connection ===
689
+ OTEL_EXPORTER_OTLP_HEADERS=x-api-key=your-key
690
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
691
+ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logs
692
+
693
+ # === Debugging ===
694
+ OTEL_LOG_LEVEL=debug
695
+ SECURENOW_TEST_SPAN=1
696
+
697
+ # === Environment ===
698
+ NODE_ENV=production
699
+ ```
700
+
701
+ ---
702
+
703
+ ## Next Steps
704
+
705
+ - Check your observability backend to see traces and logs
706
+ - Set up dashboards and alerts
707
+ - Explore the captured data to understand your application behavior
708
+
709
+ ---
710
+
711
+ ## Support
712
+
713
+ - **Documentation:** [Main Docs](../README.md)
714
+ - **Examples:** [Express Examples](../examples/)
715
+ - **Issues:** GitHub Issues
716
+
717
+ ---
718
+
719
+ **Your Express app is now fully observable!** 🎉