securenow 5.6.0 → 5.7.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/NPM_README.md CHANGED
@@ -1,1609 +1,1594 @@
1
- # SecureNow - Complete OpenTelemetry Observability for Node.js
2
-
3
- OpenTelemetry instrumentation library for Node.js applications. Send distributed traces and logs to any OTLP-compatible observability backend.
4
-
5
- **Features:**
6
- - 🚀 Zero-config automatic instrumentation
7
- - 📊 Distributed tracing for all popular frameworks
8
- - 📋 Automatic logging with console instrumentation
9
- - 🔐 Built-in sensitive data redaction
10
- - 🎯 Request body capture for debugging
11
- - 🔧 Fully configurable via environment variables
12
-
13
- ---
14
-
15
- ## Table of Contents
16
-
17
- - [Installation](#installation)
18
- - [Quick Start](#quick-start)
19
- - [CLI — Command Line Interface](#cli--command-line-interface)
20
- - [Framework-Specific Setup](#framework-specific-setup)
21
- - [Express.js](#expressjs)
22
- - [Next.js](#nextjs)
23
- - [Fastify](#fastify)
24
- - [NestJS](#nestjs)
25
- - [Koa](#koa)
26
- - [Hapi](#hapi)
27
- - [Environment Variables Reference](#environment-variables-reference)
28
- - [Logging Setup](#logging-setup)
29
- - [Request Body Capture](#request-body-capture)
30
- - [Advanced Configuration](#advanced-configuration)
31
- - [TypeScript Support](#typescript-support)
32
- - [Troubleshooting](#troubleshooting)
33
-
34
- ---
35
-
36
- ## Installation
37
-
38
- ```bash
39
- npm install securenow
40
- ```
41
-
42
- Or with yarn:
43
-
44
- ```bash
45
- yarn add securenow
46
- ```
47
-
48
- ---
49
-
50
- ## Quick Start
51
-
52
- ### 1. Set Environment Variables
53
-
54
- ```bash
55
- # Required: Your application identifier
56
- export SECURENOW_APPID=my-app
57
-
58
- # Required: Your OTLP collector endpoint
59
- export SECURENOW_INSTANCE=http://your-otlp-collector:4318
60
-
61
- # Optional: Enable logging
62
- export SECURENOW_LOGGING_ENABLED=1
63
- ```
64
-
65
- ### 2. Initialize in Your Application
66
-
67
- **Option A: Using NODE_OPTIONS (Recommended)**
68
-
69
- ```bash
70
- NODE_OPTIONS="-r securenow/register" node app.js
71
- ```
72
-
73
- **Option B: Code-based initialization**
74
-
75
- ```javascript
76
- // At the very top of your main file
77
- require('securenow/register');
78
-
79
- // Your application code
80
- const express = require('express');
81
- const app = express();
82
- // ...
83
- ```
84
-
85
- ### 3. Run Your Application
86
-
87
- ```bash
88
- node app.js
89
- ```
90
-
91
- You'll see confirmation in the console:
92
-
93
- ```
94
- [securenow] OTel SDK started → http://your-otlp-collector:4318/v1/traces
95
- [securenow] 📝 Request body capture: ENABLED
96
- ```
97
-
98
- ---
99
-
100
- ## CLI Command Line Interface
101
-
102
- The `securenow` CLI gives you full access to the SecureNow platform from the terminal — no browser required for day-to-day workflows. Zero additional dependencies.
103
-
104
- ### Getting Started
105
-
106
- ```bash
107
- # Log in (opens browser for OAuth)
108
- npx securenow login
109
-
110
- # Or use a token for CI/headless environments
111
- npx securenow login --token <YOUR_JWT>
112
-
113
- # Check who you're logged in as
114
- npx securenow whoami
115
- ```
116
-
117
- ### Managing Applications
118
-
119
- ```bash
120
- # List all applications
121
- npx securenow apps
122
-
123
- # Create a new application
124
- npx securenow apps create my-production-app --hosts api.example.com,app.example.com
125
-
126
- # Get application details (including the app key)
127
- npx securenow apps info <app-id>
128
-
129
- # Set a default app so you don't need --app on every command
130
- npx securenow apps default <app-key>
131
-
132
- # Delete an application
133
- npx securenow apps delete <app-id> --force
134
- ```
135
-
136
- ### Viewing Traces
137
-
138
- ```bash
139
- # List recent traces (uses default app, or specify --app)
140
- npx securenow traces
141
- npx securenow traces --app <key> --limit 50
142
-
143
- # Show detailed spans for a trace
144
- npx securenow traces show <traceId>
145
-
146
- # AI-powered security analysis of a trace
147
- npx securenow traces analyze <traceId>
148
- ```
149
-
150
- ### Viewing Logs
151
-
152
- ```bash
153
- # List recent logs
154
- npx securenow logs
155
- npx securenow logs --app <key> --minutes 30 --level error
156
-
157
- # Show logs for a specific trace
158
- npx securenow logs trace <traceId>
159
- ```
160
-
161
- ### Security Issues
162
-
163
- ```bash
164
- # List all issues
165
- npx securenow issues
166
- npx securenow issues --status open
167
-
168
- # Show issue details with AI analysis
169
- npx securenow issues show <issue-id>
170
-
171
- # Resolve an issue
172
- npx securenow issues resolve <issue-id>
173
- ```
174
-
175
- ### Notifications
176
-
177
- ```bash
178
- # List notifications
179
- npx securenow notifications
180
-
181
- # Check unread count
182
- npx securenow notifications unread
183
-
184
- # Mark as read
185
- npx securenow notifications read <id>
186
- npx securenow notifications read-all
187
- ```
188
-
189
- ### Alerting
190
-
191
- ```bash
192
- # View alert rules, channels, and history
193
- npx securenow alerts rules
194
- npx securenow alerts channels
195
- npx securenow alerts history --limit 20
196
- ```
197
-
198
- ### IP Intelligence & Blocklist
199
-
200
- ```bash
201
- # Look up any IP — geo, abuse score, verdict, risk factors
202
- npx securenow ip 203.0.113.42
203
-
204
- # Show traces from a specific IP
205
- npx securenow ip traces 203.0.113.42
206
-
207
- # Manage the blocklist
208
- npx securenow blocklist
209
- npx securenow blocklist add 203.0.113.42 --reason "Brute force scanner"
210
- npx securenow blocklist remove <id>
211
- npx securenow blocklist stats
212
-
213
- # Manage trusted IPs
214
- npx securenow trusted
215
- npx securenow trusted add 10.0.0.1 --label "Office VPN"
216
- npx securenow trusted remove <id>
217
- ```
218
-
219
- ### Forensic Queries
220
-
221
- Ask questions in plain English — the AI translates them to SQL and runs them against your data.
222
-
223
- ```bash
224
- # Run a forensic query
225
- npx securenow forensics "show top 10 attacking IPs in the last hour"
226
- npx securenow forensics "which endpoints had 5xx errors today"
227
-
228
- # Browse the saved query library
229
- npx securenow forensics library
230
- ```
231
-
232
- ### API Map
233
-
234
- ```bash
235
- # View all discovered API endpoints
236
- npx securenow api-map
237
-
238
- # API map statistics
239
- npx securenow api-map stats
240
- ```
241
-
242
- ### Analytics & Dashboard
243
-
244
- ```bash
245
- # Response code analytics
246
- npx securenow analytics --app <key>
247
-
248
- # Full dashboard overview (apps, protection status, unread alerts)
249
- npx securenow status
250
- ```
251
-
252
- ### Instances
253
-
254
- ```bash
255
- # List ClickHouse instances
256
- npx securenow instances
257
-
258
- # Test an instance connection
259
- npx securenow instances test <id>
260
- ```
261
-
262
- ### Configuration
263
-
264
- ```bash
265
- # View all config
266
- npx securenow config get
267
-
268
- # Set values
269
- npx securenow config set apiUrl https://custom-api.example.com
270
- npx securenow config set defaultApp <app-key>
271
- npx securenow config set format json
272
-
273
- # Show config file paths
274
- npx securenow config path
275
- ```
276
-
277
- Config files are stored in `~/.securenow/`:
278
-
279
- | File | Description |
280
- |------|-------------|
281
- | `config.json` | API URL, default app, output format |
282
- | `credentials.json` | Auth token (file permissions: 0600) |
283
-
284
- ### Initialize Instrumentation
285
-
286
- ```bash
287
- # Interactive setup — creates instrumentation files for Next.js
288
- npx securenow init
289
- npx securenow init --ts --src --force
290
- ```
291
-
292
- ### Global Flags
293
-
294
- Every command supports these flags:
295
-
296
- | Flag | Short | Description |
297
- |------|-------|-------------|
298
- | `--json` | `-j` | Output as JSON for scripting and CI/CD |
299
- | `--help` | | Show help for the command |
300
- | `--app <key>` | | Override the default application key |
301
-
302
- ### Environment Variables
303
-
304
- | Variable | Description |
305
- |----------|-------------|
306
- | `SECURENOW_API_URL` | Override the API base URL |
307
- | `SECURENOW_DEBUG` | Show stack traces on errors |
308
- | `NO_COLOR` | Disable colored output |
309
-
310
- ### CI/CD Integration
311
-
312
- ```bash
313
- # Authenticate with a token in CI
314
- npx securenow login --token $SECURENOW_TOKEN
315
-
316
- # Use --json for machine-readable output
317
- npx securenow issues --json | jq '.[] | select(.severity == "critical")'
318
-
319
- # Check for critical issues in a pipeline
320
- ISSUES=$(npx securenow issues --json --status open)
321
- CRITICAL=$(echo "$ISSUES" | jq '[.[] | select(.severity == "critical")] | length')
322
- if [ "$CRITICAL" -gt "0" ]; then
323
- echo "Found $CRITICAL critical issues!"
324
- exit 1
325
- fi
326
- ```
327
-
328
- ### Complete Command Reference
329
-
330
- | Category | Command | Description |
331
- |----------|---------|-------------|
332
- | **Auth** | `login` | Authenticate via browser or `--token` |
333
- | | `logout` | Clear credentials |
334
- | | `whoami` | Show session info |
335
- | **Apps** | `apps` | List applications |
336
- | | `apps create <name>` | Create application |
337
- | | `apps info <id>` | Application details |
338
- | | `apps delete <id>` | Delete application |
339
- | | `apps default <key>` | Set default app |
340
- | **Observe** | `traces` | List traces |
341
- | | `traces show <id>` | Trace details |
342
- | | `traces analyze <id>` | AI trace analysis |
343
- | | `logs` | List logs |
344
- | | `logs trace <id>` | Logs for a trace |
345
- | | `analytics` | Response analytics |
346
- | | `status` | Dashboard overview |
347
- | **Detect** | `issues` | List issues |
348
- | | `issues show <id>` | Issue details |
349
- | | `issues resolve <id>` | Resolve issue |
350
- | | `notifications` | List notifications |
351
- | | `notifications unread` | Unread count |
352
- | | `notifications read <id>` | Mark read |
353
- | | `notifications read-all` | Mark all read |
354
- | | `alerts rules` | Alert rules |
355
- | | `alerts channels` | Alert channels |
356
- | | `alerts history` | Alert history |
357
- | **Investigate** | `ip <addr>` | IP intelligence |
358
- | | `ip traces <addr>` | Traces from IP |
359
- | | `forensics "<query>"` | NL forensic query |
360
- | | `forensics library` | Saved queries |
361
- | | `api-map` | API endpoints |
362
- | | `api-map stats` | API stats |
363
- | **Remediate** | `blocklist` | Blocked IPs |
364
- | | `blocklist add <ip>` | Block IP |
365
- | | `blocklist remove <id>` | Unblock IP |
366
- | | `blocklist stats` | Block stats |
367
- | | `trusted` | Trusted IPs |
368
- | | `trusted add <ip>` | Add trusted IP |
369
- | | `trusted remove <id>` | Remove trusted |
370
- | **Settings** | `instances` | List instances |
371
- | | `instances test <id>` | Test connection |
372
- | | `config get` | Show config |
373
- | | `config set <k> <v>` | Set config value |
374
- | | `config path` | Config file paths |
375
- | | `init` | Setup instrumentation |
376
- | | `version` | Show version |
377
-
378
- ---
379
-
380
- ## Framework-Specific Setup
381
-
382
- ### Express.js
383
-
384
- #### Basic Tracing Setup
385
-
386
- **Step 1: Install**
387
-
388
- ```bash
389
- npm install securenow express
390
- ```
391
-
392
- **Step 2: Create `.env` file**
393
-
394
- ```env
395
- SECURENOW_APPID=my-express-app
396
- SECURENOW_INSTANCE=http://localhost:4318
397
- SECURENOW_LOGGING_ENABLED=1
398
- ```
399
-
400
- **Step 3: Initialize at the top of your main file**
401
-
402
- ```javascript
403
- // app.js or server.js
404
- require('securenow/register');
405
- require('securenow/console-instrumentation'); // Optional: for automatic logging
406
-
407
- const express = require('express');
408
- const app = express();
409
-
410
- app.use(express.json());
411
-
412
- app.get('/', (req, res) => {
413
- console.log('Home page accessed'); // Automatically logged if console-instrumentation is enabled
414
- res.send('Hello World');
415
- });
416
-
417
- app.post('/api/users', (req, res) => {
418
- console.info('User created', { userId: 123 });
419
- res.json({ success: true });
420
- });
421
-
422
- const PORT = process.env.PORT || 3000;
423
- app.listen(PORT, () => {
424
- console.log(`Server running on port ${PORT}`);
425
- });
426
- ```
427
-
428
- **Step 4: Run**
429
-
430
- ```bash
431
- # With NODE_OPTIONS
432
- NODE_OPTIONS="-r securenow/register -r securenow/console-instrumentation" node app.js
433
-
434
- # Or directly (if you added require statements)
435
- node app.js
436
- ```
437
-
438
- #### With PM2
439
-
440
- ```javascript
441
- // ecosystem.config.js
442
- module.exports = {
443
- apps: [{
444
- name: 'my-app',
445
- script: './app.js',
446
- instances: 4,
447
- exec_mode: 'cluster',
448
- node_args: '-r securenow/register -r securenow/console-instrumentation',
449
- env: {
450
- SECURENOW_APPID: 'my-express-app',
451
- SECURENOW_INSTANCE: 'http://localhost:4318',
452
- SECURENOW_LOGGING_ENABLED: '1',
453
- SECURENOW_NO_UUID: '1', // Use same service name across all instances
454
- SECURENOW_CAPTURE_BODY: '1' // Enable request body capture
455
- }
456
- }]
457
- };
458
- ```
459
-
460
- ```bash
461
- pm2 start ecosystem.config.js
462
- ```
463
-
464
- ---
465
-
466
- ### Next.js
467
-
468
- #### App Router (Next.js 13+)
469
-
470
- **Step 1: Install**
471
-
472
- ```bash
473
- npm install securenow
474
- ```
475
-
476
- **Step 2: Create `instrumentation.ts` (or `.js`) in your project root**
477
-
478
- ```typescript
479
- // instrumentation.ts
480
- export async function register() {
481
- if (process.env.NEXT_RUNTIME === 'nodejs') {
482
- // Enable logging
483
- process.env.SECURENOW_LOGGING_ENABLED = '1';
484
-
485
- // Initialize tracing and logging
486
- await import('securenow/register');
487
- await import('securenow/console-instrumentation');
488
-
489
- console.log('SecureNow observability initialized');
490
- }
491
- }
492
- ```
493
-
494
- **Step 3: Enable instrumentation hook in `next.config.js`**
495
-
496
- ```javascript
497
- // next.config.js
498
- /** @type {import('next').NextConfig} */
499
- const nextConfig = {
500
- experimental: {
501
- instrumentationHook: true,
502
- },
503
- };
504
-
505
- module.exports = nextConfig;
506
- ```
507
-
508
- **Step 4: Create `.env.local`**
509
-
510
- ```env
511
- SECURENOW_APPID=my-nextjs-app
512
- SECURENOW_INSTANCE=http://localhost:4318
513
- SECURENOW_LOGGING_ENABLED=1
514
- SECURENOW_CAPTURE_BODY=1
515
- ```
516
-
517
- **Step 5: Use in your application**
518
-
519
- ```typescript
520
- // app/api/users/route.ts
521
- import { NextRequest, NextResponse } from 'next/server';
522
-
523
- export async function GET(request: NextRequest) {
524
- console.log('GET /api/users called');
525
-
526
- // Your logic here
527
- const users = await fetchUsers();
528
-
529
- console.info('Users fetched', { count: users.length });
530
- return NextResponse.json(users);
531
- }
532
-
533
- export async function POST(request: NextRequest) {
534
- const body = await request.json();
535
- console.info('Creating user', { email: body.email });
536
-
537
- try {
538
- const user = await createUser(body);
539
- console.log('User created successfully', { userId: user.id });
540
- return NextResponse.json(user, { status: 201 });
541
- } catch (error) {
542
- console.error('Failed to create user', { error: error.message });
543
- return NextResponse.json({ error: 'Failed' }, { status: 500 });
544
- }
545
- }
546
- ```
547
-
548
- **Step 6: Run**
549
-
550
- ```bash
551
- npm run dev
552
- ```
553
-
554
- #### Pages Router (Next.js 12 and below)
555
-
556
- **Step 1: Create `_app.js` or `_app.tsx`**
557
-
558
- ```javascript
559
- // pages/_app.js
560
- if (typeof window === 'undefined') {
561
- require('securenow/register');
562
- require('securenow/console-instrumentation');
563
- }
564
-
565
- function MyApp({ Component, pageProps }) {
566
- return <Component {...pageProps} />;
567
- }
568
-
569
- export default MyApp;
570
- ```
571
-
572
- **Step 2: Same `.env.local` as above**
573
-
574
- **Step 3: Run**
575
-
576
- ```bash
577
- npm run dev
578
- ```
579
-
580
- ---
581
-
582
- ### Fastify
583
-
584
- **Step 1: Install**
585
-
586
- ```bash
587
- npm install securenow fastify
588
- ```
589
-
590
- **Step 2: Create `.env`**
591
-
592
- ```env
593
- SECURENOW_APPID=my-fastify-app
594
- SECURENOW_INSTANCE=http://localhost:4318
595
- SECURENOW_LOGGING_ENABLED=1
596
- ```
597
-
598
- **Step 3: Initialize at the top**
599
-
600
- ```javascript
601
- // server.js
602
- require('securenow/register');
603
- require('securenow/console-instrumentation');
604
-
605
- const fastify = require('fastify')({ logger: false });
606
-
607
- // Logging hook
608
- fastify.addHook('onRequest', async (request, reply) => {
609
- console.info('Request received', {
610
- method: request.method,
611
- url: request.url,
612
- });
613
- });
614
-
615
- fastify.get('/', async (request, reply) => {
616
- console.log('Root endpoint called');
617
- return { hello: 'world' };
618
- });
619
-
620
- fastify.post('/users', async (request, reply) => {
621
- console.info('Creating user', { body: request.body });
622
- // Your logic
623
- return { success: true };
624
- });
625
-
626
- // Error handler
627
- fastify.setErrorHandler((error, request, reply) => {
628
- console.error('Fastify error', {
629
- error: error.message,
630
- stack: error.stack,
631
- url: request.url,
632
- });
633
- reply.status(500).send({ error: 'Internal server error' });
634
- });
635
-
636
- const start = async () => {
637
- try {
638
- await fastify.listen({ port: 3000 });
639
- console.log('Fastify server running on port 3000');
640
- } catch (err) {
641
- console.error('Server start failed', { error: err });
642
- process.exit(1);
643
- }
644
- };
645
-
646
- start();
647
- ```
648
-
649
- **Step 4: Run**
650
-
651
- ```bash
652
- node server.js
653
- ```
654
-
655
- ---
656
-
657
- ### NestJS
658
-
659
- **Step 1: Install**
660
-
661
- ```bash
662
- npm install securenow
663
- ```
664
-
665
- **Step 2: Create `.env`**
666
-
667
- ```env
668
- SECURENOW_APPID=my-nestjs-app
669
- SECURENOW_INSTANCE=http://localhost:4318
670
- SECURENOW_LOGGING_ENABLED=1
671
- ```
672
-
673
- **Step 3: Initialize in `main.ts`**
674
-
675
- ```typescript
676
- // src/main.ts
677
- require('securenow/register');
678
- require('securenow/console-instrumentation');
679
-
680
- import { NestFactory } from '@nestjs/core';
681
- import { AppModule } from './app.module';
682
-
683
- async function bootstrap() {
684
- const app = await NestFactory.create(AppModule);
685
-
686
- console.log('NestJS application starting');
687
-
688
- await app.listen(3000);
689
- console.log('Application is running on: http://localhost:3000');
690
- }
691
-
692
- bootstrap();
693
- ```
694
-
695
- **Step 4: Use in services**
696
-
697
- ```typescript
698
- // src/users/users.service.ts
699
- import { Injectable } from '@nestjs/common';
700
-
701
- @Injectable()
702
- export class UsersService {
703
- async findAll() {
704
- console.log('Fetching all users');
705
- const users = await this.fetchFromDatabase();
706
- console.info('Users retrieved', { count: users.length });
707
- return users;
708
- }
709
-
710
- async create(userData: any) {
711
- console.info('Creating user', { email: userData.email });
712
-
713
- try {
714
- const user = await this.saveToDatabase(userData);
715
- console.log('User created', { userId: user.id });
716
- return user;
717
- } catch (error) {
718
- console.error('Failed to create user', {
719
- error: error.message,
720
- email: userData.email,
721
- });
722
- throw error;
723
- }
724
- }
725
- }
726
- ```
727
-
728
- **Step 5: Run**
729
-
730
- ```bash
731
- npm run start
732
- ```
733
-
734
- ---
735
-
736
- ### Koa
737
-
738
- **Step 1: Install**
739
-
740
- ```bash
741
- npm install securenow koa
742
- ```
743
-
744
- **Step 2: Create `.env`**
745
-
746
- ```env
747
- SECURENOW_APPID=my-koa-app
748
- SECURENOW_INSTANCE=http://localhost:4318
749
- SECURENOW_LOGGING_ENABLED=1
750
- ```
751
-
752
- **Step 3: Initialize**
753
-
754
- ```javascript
755
- // app.js
756
- require('securenow/register');
757
- require('securenow/console-instrumentation');
758
-
759
- const Koa = require('koa');
760
- const Router = require('@koa/router');
761
-
762
- const app = new Koa();
763
- const router = new Router();
764
-
765
- // Logging middleware
766
- app.use(async (ctx, next) => {
767
- console.info('Request received', {
768
- method: ctx.method,
769
- path: ctx.path,
770
- });
771
- await next();
772
- });
773
-
774
- router.get('/', (ctx) => {
775
- console.log('Home page accessed');
776
- ctx.body = { message: 'Hello World' };
777
- });
778
-
779
- router.post('/users', (ctx) => {
780
- console.info('Creating user', { body: ctx.request.body });
781
- ctx.body = { success: true };
782
- });
783
-
784
- app.use(router.routes());
785
-
786
- const PORT = 3000;
787
- app.listen(PORT, () => {
788
- console.log(`Koa server running on port ${PORT}`);
789
- });
790
- ```
791
-
792
- **Step 4: Run**
793
-
794
- ```bash
795
- node app.js
796
- ```
797
-
798
- ---
799
-
800
- ### Hapi
801
-
802
- **Step 1: Install**
803
-
804
- ```bash
805
- npm install securenow @hapi/hapi
806
- ```
807
-
808
- **Step 2: Create `.env`**
809
-
810
- ```env
811
- SECURENOW_APPID=my-hapi-app
812
- SECURENOW_INSTANCE=http://localhost:4318
813
- SECURENOW_LOGGING_ENABLED=1
814
- ```
815
-
816
- **Step 3: Initialize**
817
-
818
- ```javascript
819
- // server.js
820
- require('securenow/register');
821
- require('securenow/console-instrumentation');
822
-
823
- const Hapi = require('@hapi/hapi');
824
-
825
- const init = async () => {
826
- const server = Hapi.server({
827
- port: 3000,
828
- host: 'localhost'
829
- });
830
-
831
- // Logging extension
832
- server.ext('onRequest', (request, h) => {
833
- console.info('Request received', {
834
- method: request.method,
835
- path: request.path,
836
- });
837
- return h.continue;
838
- });
839
-
840
- server.route({
841
- method: 'GET',
842
- path: '/',
843
- handler: (request, h) => {
844
- console.log('Home page accessed');
845
- return { message: 'Hello World' };
846
- }
847
- });
848
-
849
- server.route({
850
- method: 'POST',
851
- path: '/users',
852
- handler: (request, h) => {
853
- console.info('Creating user', { payload: request.payload });
854
- return { success: true };
855
- }
856
- });
857
-
858
- await server.start();
859
- console.log('Hapi server running on:', server.info.uri);
860
- };
861
-
862
- init();
863
- ```
864
-
865
- **Step 4: Run**
866
-
867
- ```bash
868
- node server.js
869
- ```
870
-
871
- ---
872
-
873
- ## Environment Variables Reference
874
-
875
- ### Required Variables
876
-
877
- | Variable | Description | Example |
878
- |----------|-------------|---------|
879
- | `SECURENOW_APPID` | Your application identifier. Used as the service name in traces. | `my-app` |
880
- | `SECURENOW_INSTANCE` | Base URL of your OTLP collector endpoint. | `http://localhost:4318` |
881
-
882
- ### Optional Configuration
883
-
884
- #### Service Naming
885
-
886
- | Variable | Description | Default |
887
- |----------|-------------|---------|
888
- | `OTEL_SERVICE_NAME` | Alternative to SECURENOW_APPID. Standard OpenTelemetry variable. | - |
889
- | `SECURENOW_NO_UUID` | Set to `1` to disable UUID suffix on service name. Useful for clustered apps. | `0` |
890
- | `SECURENOW_STRICT` | Set to `1` to exit process if SECURENOW_APPID is not set in cluster mode. | `0` |
891
-
892
- #### Connection Settings
893
-
894
- | Variable | Description | Default |
895
- |----------|-------------|---------|
896
- | `OTEL_EXPORTER_OTLP_ENDPOINT` | Alternative to SECURENOW_INSTANCE. Standard OpenTelemetry variable. | - |
897
- | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically. | `{SECURENOW_INSTANCE}/v1/traces` |
898
- | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically. | `{SECURENOW_INSTANCE}/v1/logs` |
899
- | `OTEL_EXPORTER_OTLP_HEADERS` | Headers to send with OTLP exports. Format: `key1=value1,key2=value2` | - |
900
-
901
- #### Logging
902
-
903
- | Variable | Description | Default |
904
- |----------|-------------|---------|
905
- | `SECURENOW_LOGGING_ENABLED` | Enable automatic logging to OTLP backend. Set to `1` to enable, `0` to disable. | `1` |
906
-
907
- #### Request Body Capture
908
-
909
- | Variable | Description | Default |
910
- |----------|-------------|---------|
911
- | `SECURENOW_CAPTURE_BODY` | Enable request body capture in traces. Set to `1` to enable. | `0` |
912
- | `SECURENOW_MAX_BODY_SIZE` | Maximum body size to capture in bytes. Bodies larger than this are truncated. | `10240` (10KB) |
913
- | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated list of additional field names to redact. | - |
914
-
915
- **Default sensitive fields (auto-redacted):** `password`, `passwd`, `pwd`, `secret`, `token`, `api_key`, `apikey`, `access_token`, `auth`, `credentials`, `mysql_pwd`, `stripeToken`, `card`, `cardnumber`, `ccv`, `cvc`, `cvv`, `ssn`, `pin`
916
-
917
- #### Instrumentation Control
918
-
919
- | Variable | Description | Default |
920
- |----------|-------------|---------|
921
- | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated list of instrumentation packages to disable. | - |
922
-
923
- **Example:** `SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns` disables filesystem and DNS instrumentations.
924
-
925
- #### Debugging
926
-
927
- | Variable | Description | Default |
928
- |----------|-------------|---------|
929
- | `OTEL_LOG_LEVEL` | OpenTelemetry SDK log level. Options: `debug`, `info`, `warn`, `error` | `none` |
930
- | `SECURENOW_TEST_SPAN` | Set to `1` to emit a test span on startup. | `0` |
931
-
932
- #### Environment
933
-
934
- | Variable | Description | Default |
935
- |----------|-------------|---------|
936
- | `NODE_ENV` | Deployment environment name. Sent as `deployment.environment` attribute. | `production` |
937
-
938
- ---
939
-
940
- ## Logging Setup
941
-
942
- ### Automatic Console Logging
943
-
944
- The easiest way to send logs is to use the console instrumentation wrapper:
945
-
946
- ```javascript
947
- // At the top of your main file
948
- require('securenow/register');
949
- require('securenow/console-instrumentation');
950
-
951
- // Now all console logs are automatically sent
952
- console.log('Application started');
953
- console.info('User action', { userId: 123, action: 'login' });
954
- console.warn('Deprecation warning');
955
- console.error('Error occurred', { error: 'Something failed' });
956
- console.debug('Debug info');
957
- ```
958
-
959
- **Severity mapping:**
960
- - `console.log()` → INFO
961
- - `console.info()` → INFO
962
- - `console.warn()` WARN
963
- - `console.error()` → ERROR
964
- - `console.debug()` DEBUG
965
-
966
- **Environment variable:**
967
- ```bash
968
- SECURENOW_LOGGING_ENABLED=1
969
- ```
970
-
971
- ### Direct Logger API
972
-
973
- For more control, use the OpenTelemetry logger API:
974
-
975
- ```javascript
976
- require('securenow/register');
977
- const { getLogger } = require('securenow/tracing');
978
-
979
- // Get a logger instance
980
- const logger = getLogger('my-module', '1.0.0');
981
-
982
- // Emit structured logs
983
- logger.emit({
984
- severityNumber: 9, // INFO
985
- severityText: 'INFO',
986
- body: 'User logged in',
987
- attributes: {
988
- userId: 123,
989
- username: 'john',
990
- sessionId: 'abc123',
991
- },
992
- });
993
- ```
994
-
995
- **Severity numbers:**
996
- - `5` - DEBUG
997
- - `9` - INFO
998
- - `13` - WARN
999
- - `17` - ERROR
1000
-
1001
- ### Using with NODE_OPTIONS
1002
-
1003
- ```bash
1004
- # Enable both tracing and logging
1005
- NODE_OPTIONS="-r securenow/register -r securenow/console-instrumentation" \
1006
- SECURENOW_APPID=my-app \
1007
- SECURENOW_INSTANCE=http://localhost:4318 \
1008
- SECURENOW_LOGGING_ENABLED=1 \
1009
- node app.js
1010
- ```
1011
-
1012
- ---
1013
-
1014
- ## Request Body Capture
1015
-
1016
- SecureNow can capture HTTP request bodies in traces for debugging purposes. This is disabled by default.
1017
-
1018
- ### Enable Body Capture
1019
-
1020
- ```bash
1021
- export SECURENOW_CAPTURE_BODY=1
1022
- export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
1023
- ```
1024
-
1025
- ### Supported Content Types
1026
-
1027
- - `application/json`
1028
- - `application/x-www-form-urlencoded`
1029
- - `application/graphql`
1030
-
1031
- **Note:** Multipart form data (file uploads) are NOT captured by design.
1032
-
1033
- ### Sensitive Data Redaction
1034
-
1035
- All request bodies are automatically scanned and sensitive fields are redacted:
1036
-
1037
- **Automatically redacted fields:** `password`, `secret`, `token`, `api_key`, `card`, `cvv`, `ssn`, and more.
1038
-
1039
- **Add custom fields to redact:**
1040
-
1041
- ```bash
1042
- export SECURENOW_SENSITIVE_FIELDS="custom_secret,internal_token"
1043
- ```
1044
-
1045
- ### Example
1046
-
1047
- ```javascript
1048
- // POST /api/users with body:
1049
- {
1050
- "email": "user@example.com",
1051
- "password": "secret123",
1052
- "name": "John Doe"
1053
- }
1054
-
1055
- // Captured in trace as:
1056
- {
1057
- "email": "user@example.com",
1058
- "password": "[REDACTED]",
1059
- "name": "John Doe"
1060
- }
1061
- ```
1062
-
1063
- ---
1064
-
1065
- ## Advanced Configuration
1066
-
1067
- ### Complete Example with All Options
1068
-
1069
- ```bash
1070
- # Service identification
1071
- export SECURENOW_APPID=my-production-app
1072
- export SECURENOW_NO_UUID=1
1073
- export SECURENOW_STRICT=1
1074
-
1075
- # OTLP backend
1076
- export SECURENOW_INSTANCE=http://collector.example.com:4318
1077
- export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key"
1078
-
1079
- # Logging
1080
- export SECURENOW_LOGGING_ENABLED=1
1081
-
1082
- # Request body capture
1083
- export SECURENOW_CAPTURE_BODY=1
1084
- export SECURENOW_MAX_BODY_SIZE=20480
1085
- export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
1086
-
1087
- # Environment
1088
- export NODE_ENV=production
1089
-
1090
- # Debugging
1091
- export OTEL_LOG_LEVEL=info
1092
-
1093
- # Disable specific instrumentations
1094
- export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
1095
-
1096
- # Run application
1097
- NODE_OPTIONS="-r securenow/register -r securenow/console-instrumentation" node app.js
1098
- ```
1099
-
1100
- ### Using Multiple Logger Instances
1101
-
1102
- ```javascript
1103
- const { getLogger } = require('securenow/tracing');
1104
-
1105
- const authLogger = getLogger('auth-service', '1.0.0');
1106
- const dbLogger = getLogger('database', '1.0.0');
1107
- const apiLogger = getLogger('api-handler', '1.0.0');
1108
-
1109
- authLogger.emit({
1110
- severityNumber: 9,
1111
- severityText: 'INFO',
1112
- body: 'User authenticated',
1113
- attributes: { userId: 123 },
1114
- });
1115
-
1116
- dbLogger.emit({
1117
- severityNumber: 13,
1118
- severityText: 'WARN',
1119
- body: 'Slow query detected',
1120
- attributes: { queryTime: 5000 },
1121
- });
1122
- ```
1123
-
1124
- ### Check if Logging is Enabled
1125
-
1126
- ```javascript
1127
- const { isLoggingEnabled } = require('securenow/tracing');
1128
-
1129
- if (isLoggingEnabled()) {
1130
- console.log('Logging is enabled');
1131
- } else {
1132
- console.log('Logging is disabled');
1133
- }
1134
- ```
1135
-
1136
- ### Programmatic Configuration
1137
-
1138
- While environment variables are recommended, you can also configure programmatically:
1139
-
1140
- ```javascript
1141
- // Set environment variables before requiring securenow
1142
- process.env.SECURENOW_APPID = 'my-app';
1143
- process.env.SECURENOW_INSTANCE = 'http://localhost:4318';
1144
- process.env.SECURENOW_LOGGING_ENABLED = '1';
1145
-
1146
- // Then initialize
1147
- require('securenow/register');
1148
- require('securenow/console-instrumentation');
1149
- ```
1150
-
1151
- ---
1152
-
1153
- ## TypeScript Support
1154
-
1155
- SecureNow includes full TypeScript definitions.
1156
-
1157
- ### Type Definitions
1158
-
1159
- ```typescript
1160
- import { getLogger, isLoggingEnabled, Logger, LogRecord } from 'securenow/tracing';
1161
-
1162
- // Get a typed logger
1163
- const logger: Logger | null = getLogger('my-service', '1.0.0');
1164
-
1165
- // Emit a log with type checking
1166
- if (logger) {
1167
- const logRecord: LogRecord = {
1168
- severityNumber: 9,
1169
- severityText: 'INFO',
1170
- body: 'User action',
1171
- attributes: {
1172
- userId: 123,
1173
- action: 'login',
1174
- },
1175
- };
1176
-
1177
- logger.emit(logRecord);
1178
- }
1179
-
1180
- // Check if enabled
1181
- const enabled: boolean = isLoggingEnabled();
1182
- ```
1183
-
1184
- ### Next.js with TypeScript
1185
-
1186
- ```typescript
1187
- // instrumentation.ts
1188
- export async function register() {
1189
- if (process.env.NEXT_RUNTIME === 'nodejs') {
1190
- process.env.SECURENOW_LOGGING_ENABLED = '1';
1191
-
1192
- await import('securenow/register');
1193
- await import('securenow/console-instrumentation');
1194
- }
1195
- }
1196
- ```
1197
-
1198
- ### NestJS with TypeScript
1199
-
1200
- ```typescript
1201
- // main.ts
1202
- require('securenow/register');
1203
- require('securenow/console-instrumentation');
1204
-
1205
- import { NestFactory } from '@nestjs/core';
1206
- import { AppModule } from './app.module';
1207
-
1208
- async function bootstrap() {
1209
- const app = await NestFactory.create(AppModule);
1210
- await app.listen(3000);
1211
- }
1212
-
1213
- bootstrap();
1214
- ```
1215
-
1216
- ---
1217
-
1218
- ## Troubleshooting
1219
-
1220
- ### Traces Not Appearing
1221
-
1222
- **Check 1: Verify environment variables**
1223
-
1224
- ```bash
1225
- echo $SECURENOW_APPID
1226
- echo $SECURENOW_INSTANCE
1227
- ```
1228
-
1229
- Both should output values.
1230
-
1231
- **Check 2: Verify OTLP collector is running**
1232
-
1233
- ```bash
1234
- curl http://localhost:4318/v1/traces
1235
- # Should return 200 or 405 (method not allowed)
1236
- ```
1237
-
1238
- **Check 3: Enable debug logging**
1239
-
1240
- ```bash
1241
- export OTEL_LOG_LEVEL=debug
1242
- node app.js
1243
- ```
1244
-
1245
- Look for lines like:
1246
- ```
1247
- [securenow] OTel SDK started http://localhost:4318/v1/traces
1248
- ```
1249
-
1250
- **Check 4: Verify initialization order**
1251
-
1252
- SecureNow must be required BEFORE any other modules:
1253
-
1254
- ```javascript
1255
- // ✅ Correct
1256
- require('securenow/register');
1257
- const express = require('express');
1258
-
1259
- // ❌ Wrong - too late!
1260
- const express = require('express');
1261
- require('securenow/register');
1262
- ```
1263
-
1264
- ### Logs Not Appearing
1265
-
1266
- **Check 1: Is logging enabled?**
1267
-
1268
- ```bash
1269
- echo $SECURENOW_LOGGING_ENABLED
1270
- # Should output: 1
1271
- ```
1272
-
1273
- **Check 2: Verify console instrumentation is loaded**
1274
-
1275
- ```javascript
1276
- // Must load after register
1277
- require('securenow/register');
1278
- require('securenow/console-instrumentation');
1279
- ```
1280
-
1281
- **Check 3: Check console output**
1282
-
1283
- You should see:
1284
- ```
1285
- [securenow] 📋 Logging: ENABLED → http://localhost:4318/v1/logs
1286
- [securenow] Console instrumentation installed
1287
- ```
1288
-
1289
- **Check 4: Verify OTLP logs endpoint**
1290
-
1291
- ```bash
1292
- curl http://localhost:4318/v1/logs
1293
- # Should return 200 or 405
1294
- ```
1295
-
1296
- ### Request Body Not Captured
1297
-
1298
- **Check 1: Is body capture enabled?**
1299
-
1300
- ```bash
1301
- export SECURENOW_CAPTURE_BODY=1
1302
- ```
1303
-
1304
- **Check 2: Verify content type**
1305
-
1306
- Body capture only works for:
1307
- - `application/json`
1308
- - `application/x-www-form-urlencoded`
1309
- - `application/graphql`
1310
-
1311
- **Check 3: Check body size**
1312
-
1313
- Bodies larger than `SECURENOW_MAX_BODY_SIZE` are truncated:
1314
-
1315
- ```bash
1316
- export SECURENOW_MAX_BODY_SIZE=20480 # Increase to 20KB
1317
- ```
1318
-
1319
- ### High Memory Usage
1320
-
1321
- **Option 1: Disable body capture**
1322
-
1323
- ```bash
1324
- export SECURENOW_CAPTURE_BODY=0
1325
- ```
1326
-
1327
- **Option 2: Reduce body size limit**
1328
-
1329
- ```bash
1330
- export SECURENOW_MAX_BODY_SIZE=5120 # 5KB
1331
- ```
1332
-
1333
- **Option 3: Disable specific instrumentations**
1334
-
1335
- ```bash
1336
- export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
1337
- ```
1338
-
1339
- ### Next.js Instrumentation Not Working
1340
-
1341
- **Check 1: Verify instrumentation file location**
1342
-
1343
- `instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
1344
-
1345
- **Check 2: Enable instrumentation hook**
1346
-
1347
- ```javascript
1348
- // next.config.js
1349
- module.exports = {
1350
- experimental: {
1351
- instrumentationHook: true,
1352
- },
1353
- };
1354
- ```
1355
-
1356
- **Check 3: Restart dev server**
1357
-
1358
- ```bash
1359
- # Kill the server and restart
1360
- npm run dev
1361
- ```
1362
-
1363
- ### PM2 Cluster Issues
1364
-
1365
- **Problem: Different service names for each worker**
1366
-
1367
- **Solution: Use SECURENOW_NO_UUID**
1368
-
1369
- ```bash
1370
- export SECURENOW_NO_UUID=1
1371
- ```
1372
-
1373
- This uses the same service name for all workers.
1374
-
1375
- **Problem: Workers not instrumented**
1376
-
1377
- **Solution: Use node_args in PM2 config**
1378
-
1379
- ```javascript
1380
- // ecosystem.config.js
1381
- module.exports = {
1382
- apps: [{
1383
- name: 'my-app',
1384
- script: './app.js',
1385
- instances: 4,
1386
- node_args: '-r securenow/register',
1387
- env: {
1388
- SECURENOW_APPID: 'my-app',
1389
- SECURENOW_INSTANCE: 'http://localhost:4318',
1390
- }
1391
- }]
1392
- };
1393
- ```
1394
-
1395
- ---
1396
-
1397
- ## Best Practices
1398
-
1399
- ### 1. Use Environment Variables
1400
-
1401
- Don't hardcode configuration. Use environment variables:
1402
-
1403
- ```javascript
1404
- // Bad
1405
- process.env.SECURENOW_APPID = 'hardcoded-value';
1406
-
1407
- // ✅ Good - use .env file or export
1408
- // .env
1409
- SECURENOW_APPID=my-app
1410
- SECURENOW_INSTANCE=http://localhost:4318
1411
- ```
1412
-
1413
- ### 2. Use Structured Logging
1414
-
1415
- Pass objects to console methods for better filtering:
1416
-
1417
- ```javascript
1418
- // ❌ Less useful
1419
- console.log('User 123 logged in');
1420
-
1421
- // ✅ Better - structured attributes
1422
- console.log('User logged in', {
1423
- userId: 123,
1424
- email: 'user@example.com',
1425
- timestamp: new Date().toISOString(),
1426
- });
1427
- ```
1428
-
1429
- ### 3. Choose Appropriate Severity Levels
1430
-
1431
- ```javascript
1432
- // Normal operations
1433
- console.log('Request processed');
1434
- console.info('User created', { userId: 123 });
1435
-
1436
- // Warnings
1437
- console.warn('API rate limit approaching', { remaining: 10 });
1438
-
1439
- // Errors
1440
- console.error('Database connection failed', { error: err.message });
1441
-
1442
- // Debug (only in development)
1443
- console.debug('Cache hit', { key: 'user:123' });
1444
- ```
1445
-
1446
- ### 4. Don't Log Sensitive Data
1447
-
1448
- Even though SecureNow automatically redacts common sensitive fields, avoid logging:
1449
-
1450
- ```javascript
1451
- // ❌ Bad
1452
- console.log('Login attempt', {
1453
- email: 'user@example.com',
1454
- password: 'secret123', // Will be redacted, but don't log it!
1455
- });
1456
-
1457
- // ✅ Good
1458
- console.log('Login attempt', {
1459
- email: 'user@example.com',
1460
- timestamp: Date.now(),
1461
- });
1462
- ```
1463
-
1464
- ### 5. Use Different Logger Instances for Different Modules
1465
-
1466
- ```javascript
1467
- // auth-service.js
1468
- const authLogger = getLogger('auth-service', '1.0.0');
1469
-
1470
- // database.js
1471
- const dbLogger = getLogger('database', '1.0.0');
1472
-
1473
- // api.js
1474
- const apiLogger = getLogger('api', '1.0.0');
1475
- ```
1476
-
1477
- ### 6. Enable Body Capture Only in Development
1478
-
1479
- ```bash
1480
- # .env.development
1481
- SECURENOW_CAPTURE_BODY=1
1482
-
1483
- # .env.production
1484
- SECURENOW_CAPTURE_BODY=0
1485
- ```
1486
-
1487
- ---
1488
-
1489
- ## Supported Runtimes
1490
-
1491
- - **Node.js:** 18+
1492
- - **Frameworks:** Express, Next.js, Fastify, NestJS, Koa, Hapi, and more
1493
- - **Databases:** PostgreSQL, MySQL, MongoDB, Redis
1494
- - **HTTP Clients:** axios, fetch, node-fetch, got, request
1495
- - **GraphQL:** Apollo Server, GraphQL.js
1496
- - **Message Queues:** Redis, BullMQ
1497
- - **And many more via OpenTelemetry auto-instrumentation**
1498
-
1499
- ---
1500
-
1501
- ## Automatic Instrumentations
1502
-
1503
- SecureNow automatically instruments:
1504
-
1505
- - HTTP/HTTPS (incoming and outgoing)
1506
- - Express.js
1507
- - Fastify
1508
- - Koa
1509
- - Hapi
1510
- - Next.js
1511
- - PostgreSQL
1512
- - MySQL/MySQL2
1513
- - MongoDB
1514
- - Redis
1515
- - GraphQL
1516
- - gRPC
1517
- - DNS
1518
- - File System
1519
- - And 50+ more libraries
1520
-
1521
- No code changes needed!
1522
-
1523
- ---
1524
-
1525
- ## Architecture
1526
-
1527
- ```
1528
- ┌─────────────────────────────────┐
1529
- Your Application
1530
- (Express/Next.js/etc)
1531
- └───────────────┬─────────────────┘
1532
-
1533
-
1534
- ┌─────────────────────────────────┐
1535
- SecureNow Library
1536
- - Auto-instrumentation
1537
- │ - Console wrapper (optional) │
1538
- │ - Body capture (optional) │
1539
- └───────────────┬─────────────────┘
1540
-
1541
-
1542
- ┌─────────────────────────────────┐
1543
- │ OpenTelemetry SDK │
1544
- - Trace/Log processors │
1545
- - OTLP exporters │
1546
- └───────────────┬─────────────────┘
1547
-
1548
-
1549
- ┌─────────────────────────────────┐
1550
- │ OTLP Collector/Backend │
1551
- │ (Your observability platform) │
1552
- └─────────────────────────────────┘
1553
- ```
1554
-
1555
- ---
1556
-
1557
- ## Performance
1558
-
1559
- - **Minimal overhead:** < 1% CPU and memory impact
1560
- - **Batch export:** Traces and logs are batched before sending
1561
- - **Async processing:** No blocking of application threads
1562
- - **Configurable:** Disable instrumentations you don't need
1563
-
1564
- ---
1565
-
1566
- ## Security
1567
-
1568
- - **Automatic redaction** of sensitive fields (passwords, tokens, keys)
1569
- - **Configurable** sensitive field patterns
1570
- - **No data stored** locally - everything sent to your OTLP backend
1571
- - **Open source** - audit the code yourself
1572
-
1573
- ---
1574
-
1575
- ## License
1576
-
1577
- ISC
1578
-
1579
- ---
1580
-
1581
- ## Support
1582
-
1583
- - **Documentation:** [GitHub Docs](https://github.com/your-repo/securenow-npm/tree/main/docs)
1584
- - **Issues:** [GitHub Issues](https://github.com/your-repo/securenow-npm/issues)
1585
- - **Examples:** [GitHub Examples](https://github.com/your-repo/securenow-npm/tree/main/examples)
1586
-
1587
- ---
1588
-
1589
- ## Changelog
1590
-
1591
- See [CHANGELOG.md](CHANGELOG.md) for version history.
1592
-
1593
- ---
1594
-
1595
- ## Contributing
1596
-
1597
- Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
1598
-
1599
- ---
1600
-
1601
- ## Related Packages
1602
-
1603
- - [@opentelemetry/sdk-node](https://www.npmjs.com/package/@opentelemetry/sdk-node) - Core OpenTelemetry SDK
1604
- - [@opentelemetry/auto-instrumentations-node](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) - Auto-instrumentation
1605
- - [@opentelemetry/exporter-trace-otlp-http](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http) - OTLP exporter
1606
-
1607
- ---
1608
-
1609
- **Made with ❤️ for the Node.js community**
1
+ # SecureNow - Complete OpenTelemetry Observability for Node.js
2
+
3
+ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt applications. Send distributed traces and logs to any OTLP-compatible observability backend.
4
+
5
+ **Features:**
6
+ - 🚀 Zero-config automatic instrumentation
7
+ - 📊 Distributed tracing for all popular frameworks
8
+ - 📋 Automatic logging with console instrumentation
9
+ - 🔐 Built-in sensitive data redaction
10
+ - 🎯 Request body capture for debugging
11
+ - 🔧 Fully configurable via environment variables
12
+ - 🖥️ Single `-r securenow/register` flag — works for both CJS and ESM apps
13
+ - 🟢 Native Nuxt 3 module (`securenow/nuxt`)
14
+
15
+ ---
16
+
17
+ ## Table of Contents
18
+
19
+ - [Installation](#installation)
20
+ - [Quick Start](#quick-start)
21
+ - [CLI — Command Line Interface](#cli--command-line-interface)
22
+ - [Framework-Specific Setup](#framework-specific-setup)
23
+ - [Express.js](#expressjs)
24
+ - [Next.js](#nextjs)
25
+ - [Nuxt 3](#nuxt-3)
26
+ - [Fastify](#fastify)
27
+ - [NestJS](#nestjs)
28
+ - [Koa](#koa)
29
+ - [Hapi](#hapi)
30
+ - [Environment Variables Reference](#environment-variables-reference)
31
+ - [Logging Setup](#logging-setup)
32
+ - [Request Body Capture](#request-body-capture)
33
+ - [Advanced Configuration](#advanced-configuration)
34
+ - [TypeScript Support](#typescript-support)
35
+ - [Troubleshooting](#troubleshooting)
36
+
37
+ ---
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install securenow
43
+ ```
44
+
45
+ Or with yarn:
46
+
47
+ ```bash
48
+ yarn add securenow
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Quick Start
54
+
55
+ ### 1. Set Environment Variables
56
+
57
+ ```bash
58
+ # Required: Your application identifier
59
+ export SECURENOW_APPID=my-app
60
+
61
+ # Required: Your OTLP collector endpoint
62
+ export SECURENOW_INSTANCE=http://your-otlp-collector:4318
63
+
64
+ # Optional: Enable logging
65
+ export SECURENOW_LOGGING_ENABLED=1
66
+ ```
67
+
68
+ ### 2. Run Your Application
69
+
70
+ Add `-r securenow/register` to your start command — that's the only change:
71
+
72
+ ```bash
73
+ node -r securenow/register app.js
74
+ ```
75
+
76
+ ESM and CJS apps are both handled automatically (Node >=20.6 auto-registers the ESM loader hook via `module.register()`).
77
+
78
+ **package.json** example:
79
+
80
+ ```json
81
+ "scripts": {
82
+ "start": "node -r securenow/register app.js",
83
+ "dev": "node -r securenow/register --watch app.js"
84
+ }
85
+ ```
86
+
87
+ **Alternative: Use NODE_OPTIONS** so your existing scripts stay unchanged:
88
+
89
+ ```bash
90
+ NODE_OPTIONS="-r securenow/register" npm start
91
+ ```
92
+
93
+ **CJS only: Code-based initialization**
94
+
95
+ ```javascript
96
+ // At the very top of your main file, before any other require
97
+ require('securenow/register');
98
+
99
+ const express = require('express');
100
+ const app = express();
101
+ // ...
102
+ ```
103
+
104
+ You'll see confirmation in the console:
105
+
106
+ ```
107
+ [securenow] OTel SDK started http://your-otlp-collector:4318/v1/traces
108
+ [securenow] 📝 Request body capture: ENABLED
109
+ ```
110
+
111
+ ---
112
+
113
+ ## CLI Command Line Interface
114
+
115
+ The `securenow` CLI gives you full access to the SecureNow platform from the terminal — no browser required for day-to-day workflows. Zero additional dependencies.
116
+
117
+ ### Getting Started
118
+
119
+ ```bash
120
+ # Log in (opens browser for OAuth)
121
+ npx securenow login
122
+
123
+ # Or use a token for CI/headless environments
124
+ npx securenow login --token <YOUR_JWT>
125
+
126
+ # Check who you're logged in as
127
+ npx securenow whoami
128
+ ```
129
+
130
+ ### Managing Applications
131
+
132
+ ```bash
133
+ # List all applications
134
+ npx securenow apps
135
+
136
+ # Create a new application
137
+ npx securenow apps create my-production-app --hosts api.example.com,app.example.com
138
+
139
+ # Get application details (including the app key)
140
+ npx securenow apps info <app-id>
141
+
142
+ # Set a default app so you don't need --app on every command
143
+ npx securenow apps default <app-key>
144
+
145
+ # Delete an application
146
+ npx securenow apps delete <app-id> --force
147
+ ```
148
+
149
+ ### Viewing Traces
150
+
151
+ ```bash
152
+ # List recent traces (uses default app, or specify --app)
153
+ npx securenow traces
154
+ npx securenow traces --app <key> --limit 50
155
+
156
+ # Show detailed spans for a trace
157
+ npx securenow traces show <traceId>
158
+
159
+ # AI-powered security analysis of a trace
160
+ npx securenow traces analyze <traceId>
161
+ ```
162
+
163
+ ### Viewing Logs
164
+
165
+ ```bash
166
+ # List recent logs
167
+ npx securenow logs
168
+ npx securenow logs --app <key> --minutes 30 --level error
169
+
170
+ # Show logs for a specific trace
171
+ npx securenow logs trace <traceId>
172
+ ```
173
+
174
+ ### Security Issues
175
+
176
+ ```bash
177
+ # List all issues
178
+ npx securenow issues
179
+ npx securenow issues --status open
180
+
181
+ # Show issue details with AI analysis
182
+ npx securenow issues show <issue-id>
183
+
184
+ # Resolve an issue
185
+ npx securenow issues resolve <issue-id>
186
+ ```
187
+
188
+ ### Notifications
189
+
190
+ ```bash
191
+ # List notifications
192
+ npx securenow notifications
193
+
194
+ # Check unread count
195
+ npx securenow notifications unread
196
+
197
+ # Mark as read
198
+ npx securenow notifications read <id>
199
+ npx securenow notifications read-all
200
+ ```
201
+
202
+ ### Alerting
203
+
204
+ ```bash
205
+ # View alert rules, channels, and history
206
+ npx securenow alerts rules
207
+ npx securenow alerts channels
208
+ npx securenow alerts history --limit 20
209
+ ```
210
+
211
+ ### IP Intelligence & Blocklist
212
+
213
+ ```bash
214
+ # Look up any IP — geo, abuse score, verdict, risk factors
215
+ npx securenow ip 203.0.113.42
216
+
217
+ # Show traces from a specific IP
218
+ npx securenow ip traces 203.0.113.42
219
+
220
+ # Manage the blocklist
221
+ npx securenow blocklist
222
+ npx securenow blocklist add 203.0.113.42 --reason "Brute force scanner"
223
+ npx securenow blocklist remove <id>
224
+ npx securenow blocklist stats
225
+
226
+ # Manage trusted IPs
227
+ npx securenow trusted
228
+ npx securenow trusted add 10.0.0.1 --label "Office VPN"
229
+ npx securenow trusted remove <id>
230
+ ```
231
+
232
+ ### Forensic Queries
233
+
234
+ Ask questions in plain English — the AI translates them to SQL and runs them against your data.
235
+
236
+ ```bash
237
+ # Run a forensic query
238
+ npx securenow forensics "show top 10 attacking IPs in the last hour"
239
+ npx securenow forensics "which endpoints had 5xx errors today"
240
+
241
+ # Browse the saved query library
242
+ npx securenow forensics library
243
+ ```
244
+
245
+ ### API Map
246
+
247
+ ```bash
248
+ # View all discovered API endpoints
249
+ npx securenow api-map
250
+
251
+ # API map statistics
252
+ npx securenow api-map stats
253
+ ```
254
+
255
+ ### Analytics & Dashboard
256
+
257
+ ```bash
258
+ # Response code analytics
259
+ npx securenow analytics --app <key>
260
+
261
+ # Full dashboard overview (apps, protection status, unread alerts)
262
+ npx securenow status
263
+ ```
264
+
265
+ ### Instances
266
+
267
+ ```bash
268
+ # List ClickHouse instances
269
+ npx securenow instances
270
+
271
+ # Test an instance connection
272
+ npx securenow instances test <id>
273
+ ```
274
+
275
+ ### Configuration
276
+
277
+ ```bash
278
+ # View all config
279
+ npx securenow config get
280
+
281
+ # Set values
282
+ npx securenow config set apiUrl https://custom-api.example.com
283
+ npx securenow config set defaultApp <app-key>
284
+ npx securenow config set format json
285
+
286
+ # Show config file paths
287
+ npx securenow config path
288
+ ```
289
+
290
+ Config files are stored in `~/.securenow/`:
291
+
292
+ | File | Description |
293
+ |------|-------------|
294
+ | `config.json` | API URL, default app, output format |
295
+ | `credentials.json` | Auth token (file permissions: 0600) |
296
+
297
+ ### Initialize Instrumentation
298
+
299
+ ```bash
300
+ # Interactive setup creates instrumentation files for Next.js
301
+ npx securenow init
302
+ npx securenow init --ts --src --force
303
+ ```
304
+
305
+ ### Global Flags
306
+
307
+ Every command supports these flags:
308
+
309
+ | Flag | Short | Description |
310
+ |------|-------|-------------|
311
+ | `--json` | `-j` | Output as JSON for scripting and CI/CD |
312
+ | `--help` | | Show help for the command |
313
+ | `--app <key>` | | Override the default application key |
314
+
315
+ ### Environment Variables
316
+
317
+ | Variable | Description |
318
+ |----------|-------------|
319
+ | `SECURENOW_API_URL` | Override the API base URL |
320
+ | `SECURENOW_DEBUG` | Show stack traces on errors |
321
+ | `NO_COLOR` | Disable colored output |
322
+
323
+ ### CI/CD Integration
324
+
325
+ ```bash
326
+ # Authenticate with a token in CI
327
+ npx securenow login --token $SECURENOW_TOKEN
328
+
329
+ # Use --json for machine-readable output
330
+ npx securenow issues --json | jq '.[] | select(.severity == "critical")'
331
+
332
+ # Check for critical issues in a pipeline
333
+ ISSUES=$(npx securenow issues --json --status open)
334
+ CRITICAL=$(echo "$ISSUES" | jq '[.[] | select(.severity == "critical")] | length')
335
+ if [ "$CRITICAL" -gt "0" ]; then
336
+ echo "Found $CRITICAL critical issues!"
337
+ exit 1
338
+ fi
339
+ ```
340
+
341
+ ### Complete Command Reference
342
+
343
+ | Category | Command | Description |
344
+ |----------|---------|-------------|
345
+ | **Auth** | `login` | Authenticate via browser or `--token` |
346
+ | | `logout` | Clear credentials |
347
+ | | `whoami` | Show session info |
348
+ | **Apps** | `apps` | List applications |
349
+ | | `apps create <name>` | Create application |
350
+ | | `apps info <id>` | Application details |
351
+ | | `apps delete <id>` | Delete application |
352
+ | | `apps default <key>` | Set default app |
353
+ | **Observe** | `traces` | List traces |
354
+ | | `traces show <id>` | Trace details |
355
+ | | `traces analyze <id>` | AI trace analysis |
356
+ | | `logs` | List logs |
357
+ | | `logs trace <id>` | Logs for a trace |
358
+ | | `analytics` | Response analytics |
359
+ | | `status` | Dashboard overview |
360
+ | **Detect** | `issues` | List issues |
361
+ | | `issues show <id>` | Issue details |
362
+ | | `issues resolve <id>` | Resolve issue |
363
+ | | `notifications` | List notifications |
364
+ | | `notifications unread` | Unread count |
365
+ | | `notifications read <id>` | Mark read |
366
+ | | `notifications read-all` | Mark all read |
367
+ | | `alerts rules` | Alert rules |
368
+ | | `alerts channels` | Alert channels |
369
+ | | `alerts history` | Alert history |
370
+ | **Investigate** | `ip <addr>` | IP intelligence |
371
+ | | `ip traces <addr>` | Traces from IP |
372
+ | | `forensics "<query>"` | NL forensic query |
373
+ | | `forensics library` | Saved queries |
374
+ | | `api-map` | API endpoints |
375
+ | | `api-map stats` | API stats |
376
+ | **Remediate** | `blocklist` | Blocked IPs |
377
+ | | `blocklist add <ip>` | Block IP |
378
+ | | `blocklist remove <id>` | Unblock IP |
379
+ | | `blocklist stats` | Block stats |
380
+ | | `trusted` | Trusted IPs |
381
+ | | `trusted add <ip>` | Add trusted IP |
382
+ | | `trusted remove <id>` | Remove trusted |
383
+ | **Settings** | `instances` | List instances |
384
+ | | `instances test <id>` | Test connection |
385
+ | | `config get` | Show config |
386
+ | | `config set <k> <v>` | Set config value |
387
+ | | `config path` | Config file paths |
388
+ | | `init` | Setup instrumentation |
389
+ | | `version` | Show version |
390
+
391
+ ---
392
+
393
+ ## Framework-Specific Setup
394
+
395
+ > **v5.6.0+:** When `SECURENOW_LOGGING_ENABLED=1`, all `console.log`/`warn`/`error`/`info`/`debug` calls
396
+ > are **automatically** forwarded as OTLP log records. The separate `require('securenow/console-instrumentation')` is no longer needed (but still available for backward compat).
397
+
398
+ ### Express.js
399
+
400
+ ```bash
401
+ npm install securenow express
402
+ ```
403
+
404
+ ```javascript
405
+ // app.js
406
+ require('securenow/register');
407
+ const express = require('express');
408
+
409
+ const app = express();
410
+ app.use(express.json());
411
+
412
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
413
+
414
+ app.post('/tasks', (req, res) => {
415
+ console.log('Created task:', req.body.title);
416
+ res.status(201).json({ id: '1', title: req.body.title });
417
+ });
418
+
419
+ app.listen(3000, () => console.log('Express running on port 3000'));
420
+ ```
421
+
422
+ ```bash
423
+ node app.js
424
+ ```
425
+
426
+ #### With PM2
427
+
428
+ ```javascript
429
+ // ecosystem.config.cjs
430
+ module.exports = {
431
+ apps: [{
432
+ name: 'my-app',
433
+ script: './app.js',
434
+ node_args: '-r securenow/register',
435
+ env: {
436
+ SECURENOW_APPID: 'your-app-key',
437
+ SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
438
+ SECURENOW_LOGGING_ENABLED: '1',
439
+ SECURENOW_NO_UUID: '1',
440
+ SECURENOW_CAPTURE_BODY: '1',
441
+ }
442
+ }]
443
+ };
444
+ ```
445
+
446
+ ---
447
+
448
+ ### Fastify
449
+
450
+ ```bash
451
+ npm install securenow fastify
452
+ ```
453
+
454
+ ```javascript
455
+ // app.js
456
+ require('securenow/register');
457
+ const Fastify = require('fastify');
458
+ const fastify = Fastify({ logger: true });
459
+
460
+ fastify.get('/health', async () => ({ status: 'ok' }));
461
+
462
+ fastify.post('/tasks', {
463
+ schema: { body: { type: 'object', required: ['title'], properties: { title: { type: 'string' } } } }
464
+ }, async (request) => {
465
+ console.log('Created task:', request.body.title);
466
+ return { id: '1', title: request.body.title };
467
+ });
468
+
469
+ fastify.listen({ port: 3000 }, (err) => {
470
+ if (err) { fastify.log.error(err); process.exit(1); }
471
+ console.log('Fastify running on port 3000');
472
+ });
473
+ ```
474
+
475
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify — the body capture hook conflicts with Fastify's internal stream handling.
476
+
477
+ ---
478
+
479
+ ### Koa
480
+
481
+ ```bash
482
+ npm install securenow koa @koa/router koa-bodyparser
483
+ ```
484
+
485
+ ```javascript
486
+ // app.js
487
+ require('securenow/register');
488
+ const Koa = require('koa');
489
+ const Router = require('@koa/router');
490
+ const bodyParser = require('koa-bodyparser');
491
+
492
+ const app = new Koa();
493
+ const router = new Router();
494
+
495
+ router.get('/health', (ctx) => { ctx.body = { status: 'ok' }; });
496
+
497
+ router.post('/tasks', (ctx) => {
498
+ console.log('Created task:', ctx.request.body.title);
499
+ ctx.status = 201;
500
+ ctx.body = { id: '1', title: ctx.request.body.title };
501
+ });
502
+
503
+ app.use(bodyParser());
504
+ app.use(router.routes());
505
+ app.use(router.allowedMethods());
506
+
507
+ app.listen(3000, () => console.log('Koa running on port 3000'));
508
+ ```
509
+
510
+ ---
511
+
512
+ ### NestJS
513
+
514
+ ```bash
515
+ npm install securenow @nestjs/core @nestjs/common reflect-metadata ts-node typescript
516
+ ```
517
+
518
+ NestJS uses TypeScript — securenow is loaded via `-r` flags instead of in-code `require()`:
519
+
520
+ ```typescript
521
+ // app.ts
522
+ import 'reflect-metadata';
523
+ import { NestFactory } from '@nestjs/core';
524
+ import { Module, Controller, Get, Post, Body } from '@nestjs/common';
525
+
526
+ @Controller()
527
+ class AppController {
528
+ @Get('health')
529
+ health() { return { status: 'ok' }; }
530
+
531
+ @Post('tasks')
532
+ create(@Body() body: { title: string }) {
533
+ console.log('Created task:', body.title);
534
+ return { id: '1', title: body.title };
535
+ }
536
+ }
537
+
538
+ @Module({ controllers: [AppController] })
539
+ class AppModule {}
540
+
541
+ async function bootstrap() {
542
+ const app = await NestFactory.create(AppModule);
543
+ await app.listen(3000);
544
+ console.log('NestJS running on port 3000');
545
+ }
546
+ bootstrap();
547
+ ```
548
+
549
+ ```bash
550
+ node -r securenow/register -r ts-node/register app.ts
551
+ ```
552
+
553
+ PM2 config:
554
+
555
+ ```javascript
556
+ {
557
+ name: 'my-nestjs-app',
558
+ script: 'app.ts',
559
+ interpreter: 'node',
560
+ node_args: '-r securenow/register -r ts-node/register',
561
+ }
562
+ ```
563
+
564
+ ---
565
+
566
+ ### Hapi
567
+
568
+ ```bash
569
+ npm install securenow @hapi/hapi
570
+ ```
571
+
572
+ ```javascript
573
+ // app.js
574
+ require('securenow/register');
575
+ const Hapi = require('@hapi/hapi');
576
+
577
+ const init = async () => {
578
+ const server = Hapi.server({ port: 3000, host: '0.0.0.0' });
579
+
580
+ server.route({ method: 'GET', path: '/health', handler: () => ({ status: 'ok' }) });
581
+
582
+ server.route({
583
+ method: 'POST', path: '/tasks',
584
+ options: { payload: { parse: true, allow: 'application/json' } },
585
+ handler: (request, h) => {
586
+ console.log('Created task:', request.payload.title);
587
+ return h.response({ id: '1', title: request.payload.title }).code(201);
588
+ }
589
+ });
590
+
591
+ await server.start();
592
+ console.log('Hapi running on port 3000');
593
+ };
594
+
595
+ init().catch((err) => { console.error(err); process.exit(1); });
596
+ ```
597
+
598
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi — the body capture hook consumes the request stream before Hapi's payload parser.
599
+
600
+ ---
601
+
602
+ ### h3 (UnJS / Nitro)
603
+
604
+ ```bash
605
+ npm install securenow h3
606
+ ```
607
+
608
+ ```javascript
609
+ // app.js
610
+ require('securenow/register');
611
+ const { createApp, createRouter, defineEventHandler, readBody, setResponseStatus, toNodeListener } = require('h3');
612
+ const http = require('http');
613
+
614
+ const app = createApp();
615
+ const router = createRouter();
616
+
617
+ router.get('/health', defineEventHandler(() => ({ status: 'ok' })));
618
+
619
+ router.post('/tasks', defineEventHandler(async (event) => {
620
+ const body = await readBody(event);
621
+ console.log('Created task:', body.title);
622
+ setResponseStatus(event, 201);
623
+ return { id: '1', title: body.title };
624
+ }));
625
+
626
+ app.use(router);
627
+
628
+ http.createServer(toNodeListener(app)).listen(3000, () => {
629
+ console.log('h3 running on port 3000');
630
+ });
631
+ ```
632
+
633
+ ---
634
+
635
+ ### Polka
636
+
637
+ ```bash
638
+ npm install securenow polka
639
+ ```
640
+
641
+ Polka is minimalist no built-in body parser:
642
+
643
+ ```javascript
644
+ // app.js
645
+ require('securenow/register');
646
+ const polka = require('polka');
647
+
648
+ function jsonBody(req, res, next) {
649
+ if (req.method === 'GET' || req.method === 'DELETE') return next();
650
+ let data = '';
651
+ req.on('data', chunk => { data += chunk; });
652
+ req.on('end', () => { try { req.body = JSON.parse(data); } catch { req.body = {}; } next(); });
653
+ }
654
+
655
+ function sendJson(res, status, body) {
656
+ res.writeHead(status, { 'Content-Type': 'application/json' });
657
+ res.end(JSON.stringify(body));
658
+ }
659
+
660
+ polka()
661
+ .use(jsonBody)
662
+ .get('/health', (req, res) => sendJson(res, 200, { status: 'ok' }))
663
+ .post('/tasks', (req, res) => {
664
+ console.log('Created task:', req.body.title);
665
+ sendJson(res, 201, { id: '1', title: req.body.title });
666
+ })
667
+ .listen(3000, () => console.log('Polka running on port 3000'));
668
+ ```
669
+
670
+ ---
671
+
672
+ ### Micro / Raw HTTP
673
+
674
+ For apps using Node's bare `http` module:
675
+
676
+ ```bash
677
+ npm install securenow
678
+ ```
679
+
680
+ ```javascript
681
+ // app.js
682
+ require('securenow/register');
683
+ const http = require('http');
684
+
685
+ function sendJson(res, status, body) {
686
+ res.writeHead(status, { 'Content-Type': 'application/json' });
687
+ res.end(JSON.stringify(body));
688
+ }
689
+
690
+ function readBody(req) {
691
+ return new Promise((resolve) => {
692
+ let d = ''; req.on('data', c => { d += c; }); req.on('end', () => { try { resolve(JSON.parse(d)); } catch { resolve({}); } });
693
+ });
694
+ }
695
+
696
+ async function handler(req, res) {
697
+ const url = new URL(req.url, `http://${req.headers.host}`);
698
+ if (url.pathname === '/health') return sendJson(res, 200, { status: 'ok' });
699
+ if (url.pathname === '/tasks' && req.method === 'POST') {
700
+ const body = await readBody(req);
701
+ console.log('Created task:', body.title);
702
+ return sendJson(res, 201, { id: '1', title: body.title });
703
+ }
704
+ sendJson(res, 404, { error: 'Not found' });
705
+ }
706
+
707
+ http.createServer(handler).listen(3000, () => console.log('HTTP running on port 3000'));
708
+ ```
709
+
710
+ ---
711
+
712
+ ### Hono (ESM)
713
+
714
+ ```bash
715
+ npm install securenow hono @hono/node-server
716
+ ```
717
+
718
+ Hono uses ESM — preload via `-r` flag (the ESM hook is auto-registered on Node >=20.6):
719
+
720
+ ```javascript
721
+ // app.mjs
722
+ import { serve } from '@hono/node-server';
723
+ import { Hono } from 'hono';
724
+
725
+ const app = new Hono();
726
+
727
+ app.get('/health', (c) => c.json({ status: 'ok' }));
728
+
729
+ app.post('/tasks', async (c) => {
730
+ const body = await c.req.json();
731
+ console.log('Created task:', body.title);
732
+ return c.json({ id: '1', title: body.title }, 201);
733
+ });
734
+
735
+ serve({ fetch: app.fetch, port: 3000 }, () => console.log('Hono running on port 3000'));
736
+ ```
737
+
738
+ ```bash
739
+ node -r securenow/register app.mjs
740
+ ```
741
+
742
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hono. Do **not** add `require('securenow/register')` inside `.mjs` files.
743
+
744
+ ---
745
+
746
+ ### Feathers
747
+
748
+ ```bash
749
+ npm install securenow @feathersjs/feathers @feathersjs/express @feathersjs/errors
750
+ ```
751
+
752
+ Feathers uses Express transport — same setup as Express:
753
+
754
+ ```javascript
755
+ // app.js
756
+ require('securenow/register');
757
+ const feathers = require('@feathersjs/feathers');
758
+ const express = require('@feathersjs/express');
759
+ const errors = require('@feathersjs/errors');
760
+
761
+ class TaskService {
762
+ constructor() { this.tasks = []; this.nextId = 1; }
763
+ async find() { return this.tasks; }
764
+ async create(data) {
765
+ if (!data.title) throw new errors.BadRequest('title is required');
766
+ const task = { id: String(this.nextId++), title: data.title };
767
+ this.tasks.push(task);
768
+ console.log('Created task:', task.id);
769
+ return task;
770
+ }
771
+ }
772
+
773
+ const app = express(feathers());
774
+ app.use(express.json());
775
+ app.configure(express.rest());
776
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
777
+ app.use('/tasks', new TaskService());
778
+ app.use(express.errorHandler());
779
+
780
+ app.listen(3000, () => console.log('Feathers running on port 3000'));
781
+ ```
782
+
783
+ ---
784
+
785
+ ### Next.js
786
+
787
+ See [Next.js Complete Guide →](./docs/NEXTJS-SETUP-COMPLETE.md)
788
+
789
+ Create `instrumentation.ts` in your project root:
790
+
791
+ ```typescript
792
+ export async function register() {
793
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
794
+ await import('securenow/register');
795
+ }
796
+ }
797
+ ```
798
+
799
+ `.env.local`:
800
+
801
+ ```env
802
+ SECURENOW_APPID=my-nextjs-app
803
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
804
+ SECURENOW_LOGGING_ENABLED=1
805
+ SECURENOW_NO_UUID=1
806
+ ```
807
+
808
+ ---
809
+
810
+ ### Nuxt 3
811
+
812
+ ```bash
813
+ npm install securenow
814
+ ```
815
+
816
+ Add the module to `nuxt.config.ts`:
817
+
818
+ ```typescript
819
+ export default defineNuxtConfig({
820
+ modules: ['securenow/nuxt'],
821
+ });
822
+ ```
823
+
824
+ `.env`:
825
+
826
+ ```env
827
+ SECURENOW_APPID=my-nuxt-app
828
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
829
+ ```
830
+
831
+ That's it — the Nuxt module handles OTel SDK initialization, Nitro externalization, and request tracing automatically. Optional config:
832
+
833
+ ```typescript
834
+ export default defineNuxtConfig({
835
+ modules: ['securenow/nuxt'],
836
+ securenow: {
837
+ captureBody: true,
838
+ logging: true,
839
+ noUuid: true,
840
+ },
841
+ });
842
+ ```
843
+
844
+ ---
845
+
846
+ ### Compatibility Matrix
847
+
848
+ | Framework | Traces | Logs | Body Capture | Notes |
849
+ |-----------|--------|------|--------------|-------|
850
+ | Express | Yes | Yes | Yes | Fully compatible |
851
+ | Fastify | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
852
+ | Koa | Yes | Yes | Yes | Needs `koa-bodyparser` |
853
+ | NestJS | Yes | Yes | Yes | Use `-r ts-node/register` |
854
+ | Hapi | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
855
+ | h3 | Yes | Yes | Yes | Uses `toNodeListener()` |
856
+ | Polka | Yes | Yes | Yes | Needs manual body parser |
857
+ | Micro/HTTP | Yes | Yes | Yes | Full control |
858
+ | Hono | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
859
+ | Feathers | Yes | Yes | Yes | Uses Express transport |
860
+ | Next.js | Yes | Yes | Yes | Use `instrumentation.ts` |
861
+ | Nuxt 3 | Yes | Yes | Yes | Use `securenow/nuxt` module |
862
+
863
+ ---
864
+
865
+ ## Environment Variables Reference
866
+
867
+ ### Required Variables
868
+
869
+ | Variable | Description | Example |
870
+ |----------|-------------|---------|
871
+ | `SECURENOW_APPID` | Your application identifier. Used as the service name in traces. | `my-app` |
872
+ | `SECURENOW_INSTANCE` | Base URL of your OTLP collector endpoint. | `http://localhost:4318` |
873
+
874
+ ### Optional Configuration
875
+
876
+ #### Service Naming
877
+
878
+ | Variable | Description | Default |
879
+ |----------|-------------|---------|
880
+ | `OTEL_SERVICE_NAME` | Alternative to SECURENOW_APPID. Standard OpenTelemetry variable. | - |
881
+ | `SECURENOW_NO_UUID` | Set to `1` to disable UUID suffix on service name. Useful for clustered apps. | `0` |
882
+ | `SECURENOW_STRICT` | Set to `1` to exit process if SECURENOW_APPID is not set in cluster mode. | `0` |
883
+
884
+ #### Connection Settings
885
+
886
+ | Variable | Description | Default |
887
+ |----------|-------------|---------|
888
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Alternative to SECURENOW_INSTANCE. Standard OpenTelemetry variable. | - |
889
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically. | `{SECURENOW_INSTANCE}/v1/traces` |
890
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically. | `{SECURENOW_INSTANCE}/v1/logs` |
891
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Headers to send with OTLP exports. Format: `key1=value1,key2=value2` | - |
892
+
893
+ #### Logging
894
+
895
+ | Variable | Description | Default |
896
+ |----------|-------------|---------|
897
+ | `SECURENOW_LOGGING_ENABLED` | Enable automatic logging to OTLP backend. Set to `1` to enable, `0` to disable. | `1` |
898
+
899
+ #### Request Body Capture
900
+
901
+ | Variable | Description | Default |
902
+ |----------|-------------|---------|
903
+ | `SECURENOW_CAPTURE_BODY` | Enable request body capture in traces. Set to `1` to enable. | `0` |
904
+ | `SECURENOW_MAX_BODY_SIZE` | Maximum body size to capture in bytes. Bodies larger than this are truncated. | `10240` (10KB) |
905
+ | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated list of additional field names to redact. | - |
906
+
907
+ **Default sensitive fields (auto-redacted):** `password`, `passwd`, `pwd`, `secret`, `token`, `api_key`, `apikey`, `access_token`, `auth`, `credentials`, `mysql_pwd`, `stripeToken`, `card`, `cardnumber`, `ccv`, `cvc`, `cvv`, `ssn`, `pin`
908
+
909
+ #### Instrumentation Control
910
+
911
+ | Variable | Description | Default |
912
+ |----------|-------------|---------|
913
+ | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated list of instrumentation packages to disable. | - |
914
+
915
+ **Example:** `SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns` disables filesystem and DNS instrumentations.
916
+
917
+ #### Debugging
918
+
919
+ | Variable | Description | Default |
920
+ |----------|-------------|---------|
921
+ | `OTEL_LOG_LEVEL` | OpenTelemetry SDK log level. Options: `debug`, `info`, `warn`, `error` | `none` |
922
+ | `SECURENOW_TEST_SPAN` | Set to `1` to emit a test span on startup. | `0` |
923
+
924
+ #### Environment
925
+
926
+ | Variable | Description | Default |
927
+ |----------|-------------|---------|
928
+ | `NODE_ENV` | Deployment environment name. Sent as `deployment.environment` attribute. | `production` |
929
+
930
+ ---
931
+
932
+ ## Logging Setup
933
+
934
+ ### Automatic Console Logging
935
+
936
+ Since **v5.6.0**, when `SECURENOW_LOGGING_ENABLED=1`, all console calls are automatically forwarded as OTLP log records:
937
+
938
+ ```javascript
939
+ // At the top of your main file
940
+ require('securenow/register');
941
+
942
+ // With SECURENOW_LOGGING_ENABLED=1, all console logs are automatically sent
943
+ console.log('Application started');
944
+ console.info('User action', { userId: 123, action: 'login' });
945
+ console.warn('Deprecation warning');
946
+ console.error('Error occurred', { error: 'Something failed' });
947
+ console.debug('Debug info');
948
+ ```
949
+
950
+ **Severity mapping:**
951
+ - `console.log()` INFO
952
+ - `console.info()` → INFO
953
+ - `console.warn()` WARN
954
+ - `console.error()` → ERROR
955
+ - `console.debug()` DEBUG
956
+
957
+ **Environment variable:**
958
+ ```bash
959
+ SECURENOW_LOGGING_ENABLED=1
960
+ ```
961
+
962
+ ### Direct Logger API
963
+
964
+ For more control, use the OpenTelemetry logger API:
965
+
966
+ ```javascript
967
+ require('securenow/register');
968
+ const { getLogger } = require('securenow/tracing');
969
+
970
+ // Get a logger instance
971
+ const logger = getLogger('my-module', '1.0.0');
972
+
973
+ // Emit structured logs
974
+ logger.emit({
975
+ severityNumber: 9, // INFO
976
+ severityText: 'INFO',
977
+ body: 'User logged in',
978
+ attributes: {
979
+ userId: 123,
980
+ username: 'john',
981
+ sessionId: 'abc123',
982
+ },
983
+ });
984
+ ```
985
+
986
+ **Severity numbers:**
987
+ - `5` - DEBUG
988
+ - `9` - INFO
989
+ - `13` - WARN
990
+ - `17` - ERROR
991
+
992
+ ### Using with NODE_OPTIONS
993
+
994
+ ```bash
995
+ # Enable tracing + logging (console auto-forwarding is built-in since v5.6.0)
996
+ NODE_OPTIONS="-r securenow/register" \
997
+ SECURENOW_APPID=my-app \
998
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318 \
999
+ SECURENOW_LOGGING_ENABLED=1 \
1000
+ node app.js
1001
+ ```
1002
+
1003
+ ---
1004
+
1005
+ ## Request Body Capture
1006
+
1007
+ SecureNow can capture HTTP request bodies in traces for debugging purposes. This is disabled by default.
1008
+
1009
+ ### Enable Body Capture
1010
+
1011
+ ```bash
1012
+ export SECURENOW_CAPTURE_BODY=1
1013
+ export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
1014
+ ```
1015
+
1016
+ ### Supported Content Types
1017
+
1018
+ - `application/json`
1019
+ - `application/x-www-form-urlencoded`
1020
+ - `application/graphql`
1021
+
1022
+ **Note:** Multipart form data (file uploads) are NOT captured by design.
1023
+
1024
+ ### Sensitive Data Redaction
1025
+
1026
+ All request bodies are automatically scanned and sensitive fields are redacted:
1027
+
1028
+ **Automatically redacted fields:** `password`, `secret`, `token`, `api_key`, `card`, `cvv`, `ssn`, and more.
1029
+
1030
+ **Add custom fields to redact:**
1031
+
1032
+ ```bash
1033
+ export SECURENOW_SENSITIVE_FIELDS="custom_secret,internal_token"
1034
+ ```
1035
+
1036
+ ### Example
1037
+
1038
+ ```javascript
1039
+ // POST /api/users with body:
1040
+ {
1041
+ "email": "user@example.com",
1042
+ "password": "secret123",
1043
+ "name": "John Doe"
1044
+ }
1045
+
1046
+ // Captured in trace as:
1047
+ {
1048
+ "email": "user@example.com",
1049
+ "password": "[REDACTED]",
1050
+ "name": "John Doe"
1051
+ }
1052
+ ```
1053
+
1054
+ ---
1055
+
1056
+ ## Advanced Configuration
1057
+
1058
+ ### Complete Example with All Options
1059
+
1060
+ ```bash
1061
+ # Service identification
1062
+ export SECURENOW_APPID=my-production-app
1063
+ export SECURENOW_NO_UUID=1
1064
+ export SECURENOW_STRICT=1
1065
+
1066
+ # OTLP backend
1067
+ export SECURENOW_INSTANCE=http://collector.example.com:4318
1068
+ export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key"
1069
+
1070
+ # Logging
1071
+ export SECURENOW_LOGGING_ENABLED=1
1072
+
1073
+ # Request body capture
1074
+ export SECURENOW_CAPTURE_BODY=1
1075
+ export SECURENOW_MAX_BODY_SIZE=20480
1076
+ export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
1077
+
1078
+ # Environment
1079
+ export NODE_ENV=production
1080
+
1081
+ # Debugging
1082
+ export OTEL_LOG_LEVEL=info
1083
+
1084
+ # Disable specific instrumentations
1085
+ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
1086
+
1087
+ # Run application
1088
+ NODE_OPTIONS="-r securenow/register" node app.js
1089
+ ```
1090
+
1091
+ ### Using Multiple Logger Instances
1092
+
1093
+ ```javascript
1094
+ const { getLogger } = require('securenow/tracing');
1095
+
1096
+ const authLogger = getLogger('auth-service', '1.0.0');
1097
+ const dbLogger = getLogger('database', '1.0.0');
1098
+ const apiLogger = getLogger('api-handler', '1.0.0');
1099
+
1100
+ authLogger.emit({
1101
+ severityNumber: 9,
1102
+ severityText: 'INFO',
1103
+ body: 'User authenticated',
1104
+ attributes: { userId: 123 },
1105
+ });
1106
+
1107
+ dbLogger.emit({
1108
+ severityNumber: 13,
1109
+ severityText: 'WARN',
1110
+ body: 'Slow query detected',
1111
+ attributes: { queryTime: 5000 },
1112
+ });
1113
+ ```
1114
+
1115
+ ### Check if Logging is Enabled
1116
+
1117
+ ```javascript
1118
+ const { isLoggingEnabled } = require('securenow/tracing');
1119
+
1120
+ if (isLoggingEnabled()) {
1121
+ console.log('Logging is enabled');
1122
+ } else {
1123
+ console.log('Logging is disabled');
1124
+ }
1125
+ ```
1126
+
1127
+ ### Programmatic Configuration
1128
+
1129
+ While environment variables are recommended, you can also configure programmatically:
1130
+
1131
+ ```javascript
1132
+ // Set environment variables before requiring securenow
1133
+ process.env.SECURENOW_APPID = 'my-app';
1134
+ process.env.SECURENOW_INSTANCE = 'http://localhost:4318';
1135
+ process.env.SECURENOW_LOGGING_ENABLED = '1';
1136
+
1137
+ // Then initialize (console log forwarding is automatic since v5.6.0)
1138
+ require('securenow/register');
1139
+ ```
1140
+
1141
+ ---
1142
+
1143
+ ## TypeScript Support
1144
+
1145
+ SecureNow includes full TypeScript definitions.
1146
+
1147
+ ### Type Definitions
1148
+
1149
+ ```typescript
1150
+ import { getLogger, isLoggingEnabled, Logger, LogRecord } from 'securenow/tracing';
1151
+
1152
+ // Get a typed logger
1153
+ const logger: Logger | null = getLogger('my-service', '1.0.0');
1154
+
1155
+ // Emit a log with type checking
1156
+ if (logger) {
1157
+ const logRecord: LogRecord = {
1158
+ severityNumber: 9,
1159
+ severityText: 'INFO',
1160
+ body: 'User action',
1161
+ attributes: {
1162
+ userId: 123,
1163
+ action: 'login',
1164
+ },
1165
+ };
1166
+
1167
+ logger.emit(logRecord);
1168
+ }
1169
+
1170
+ // Check if enabled
1171
+ const enabled: boolean = isLoggingEnabled();
1172
+ ```
1173
+
1174
+ ### Next.js with TypeScript
1175
+
1176
+ ```typescript
1177
+ // instrumentation.ts
1178
+ export async function register() {
1179
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
1180
+ process.env.SECURENOW_LOGGING_ENABLED = '1';
1181
+
1182
+ await import('securenow/register');
1183
+ }
1184
+ }
1185
+ ```
1186
+
1187
+ ### NestJS with TypeScript
1188
+
1189
+ Use `-r securenow/register -r ts-node/register` flags instead of in-code require:
1190
+
1191
+ ```typescript
1192
+ // main.ts (run with: node -r securenow/register -r ts-node/register main.ts)
1193
+ import { NestFactory } from '@nestjs/core';
1194
+ import { AppModule } from './app.module';
1195
+
1196
+ async function bootstrap() {
1197
+ const app = await NestFactory.create(AppModule);
1198
+ await app.listen(3000);
1199
+ }
1200
+
1201
+ bootstrap();
1202
+ ```
1203
+
1204
+ ---
1205
+
1206
+ ## Troubleshooting
1207
+
1208
+ ### Traces Not Appearing
1209
+
1210
+ **Check 1: Verify environment variables**
1211
+
1212
+ ```bash
1213
+ echo $SECURENOW_APPID
1214
+ echo $SECURENOW_INSTANCE
1215
+ ```
1216
+
1217
+ Both should output values.
1218
+
1219
+ **Check 2: Verify OTLP collector is running**
1220
+
1221
+ ```bash
1222
+ curl http://localhost:4318/v1/traces
1223
+ # Should return 200 or 405 (method not allowed)
1224
+ ```
1225
+
1226
+ **Check 3: Enable debug logging**
1227
+
1228
+ ```bash
1229
+ export OTEL_LOG_LEVEL=debug
1230
+ node app.js
1231
+ ```
1232
+
1233
+ Look for lines like:
1234
+ ```
1235
+ [securenow] OTel SDK started http://localhost:4318/v1/traces
1236
+ ```
1237
+
1238
+ **Check 4: Verify initialization order**
1239
+
1240
+ SecureNow must be required BEFORE any other modules:
1241
+
1242
+ ```javascript
1243
+ // ✅ Correct
1244
+ require('securenow/register');
1245
+ const express = require('express');
1246
+
1247
+ // Wrong - too late!
1248
+ const express = require('express');
1249
+ require('securenow/register');
1250
+ ```
1251
+
1252
+ ### Logs Not Appearing
1253
+
1254
+ **Check 1: Is logging enabled?**
1255
+
1256
+ ```bash
1257
+ echo $SECURENOW_LOGGING_ENABLED
1258
+ # Should output: 1
1259
+ ```
1260
+
1261
+ **Check 2: Verify console instrumentation is loaded**
1262
+
1263
+ ```javascript
1264
+ require('securenow/register');
1265
+ ```
1266
+
1267
+ **Check 3: Check console output**
1268
+
1269
+ You should see:
1270
+ ```
1271
+ [securenow] 📋 Logging: ENABLED → http://localhost:4318/v1/logs
1272
+ ```
1273
+
1274
+ **Check 4: Verify OTLP logs endpoint**
1275
+
1276
+ ```bash
1277
+ curl http://localhost:4318/v1/logs
1278
+ # Should return 200 or 405
1279
+ ```
1280
+
1281
+ ### Request Body Not Captured
1282
+
1283
+ **Check 1: Is body capture enabled?**
1284
+
1285
+ ```bash
1286
+ export SECURENOW_CAPTURE_BODY=1
1287
+ ```
1288
+
1289
+ **Check 2: Verify content type**
1290
+
1291
+ Body capture only works for:
1292
+ - `application/json`
1293
+ - `application/x-www-form-urlencoded`
1294
+ - `application/graphql`
1295
+
1296
+ **Check 3: Check body size**
1297
+
1298
+ Bodies larger than `SECURENOW_MAX_BODY_SIZE` are truncated:
1299
+
1300
+ ```bash
1301
+ export SECURENOW_MAX_BODY_SIZE=20480 # Increase to 20KB
1302
+ ```
1303
+
1304
+ ### High Memory Usage
1305
+
1306
+ **Option 1: Disable body capture**
1307
+
1308
+ ```bash
1309
+ export SECURENOW_CAPTURE_BODY=0
1310
+ ```
1311
+
1312
+ **Option 2: Reduce body size limit**
1313
+
1314
+ ```bash
1315
+ export SECURENOW_MAX_BODY_SIZE=5120 # 5KB
1316
+ ```
1317
+
1318
+ **Option 3: Disable specific instrumentations**
1319
+
1320
+ ```bash
1321
+ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
1322
+ ```
1323
+
1324
+ ### Next.js Instrumentation Not Working
1325
+
1326
+ **Check 1: Verify instrumentation file location**
1327
+
1328
+ `instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
1329
+
1330
+ **Check 2: Enable instrumentation hook**
1331
+
1332
+ ```javascript
1333
+ // next.config.js
1334
+ module.exports = {
1335
+ experimental: {
1336
+ instrumentationHook: true,
1337
+ },
1338
+ };
1339
+ ```
1340
+
1341
+ **Check 3: Restart dev server**
1342
+
1343
+ ```bash
1344
+ # Kill the server and restart
1345
+ npm run dev
1346
+ ```
1347
+
1348
+ ### PM2 Cluster Issues
1349
+
1350
+ **Problem: Different service names for each worker**
1351
+
1352
+ **Solution: Use SECURENOW_NO_UUID**
1353
+
1354
+ ```bash
1355
+ export SECURENOW_NO_UUID=1
1356
+ ```
1357
+
1358
+ This uses the same service name for all workers.
1359
+
1360
+ **Problem: Workers not instrumented**
1361
+
1362
+ **Solution: Use node_args in PM2 config**
1363
+
1364
+ ```javascript
1365
+ // ecosystem.config.js
1366
+ module.exports = {
1367
+ apps: [{
1368
+ name: 'my-app',
1369
+ script: './app.js',
1370
+ instances: 4,
1371
+ node_args: '-r securenow/register',
1372
+ env: {
1373
+ SECURENOW_APPID: 'my-app',
1374
+ SECURENOW_INSTANCE: 'http://localhost:4318',
1375
+ }
1376
+ }]
1377
+ };
1378
+ ```
1379
+
1380
+ ---
1381
+
1382
+ ## Best Practices
1383
+
1384
+ ### 1. Use Environment Variables
1385
+
1386
+ Don't hardcode configuration. Use environment variables:
1387
+
1388
+ ```javascript
1389
+ // ❌ Bad
1390
+ process.env.SECURENOW_APPID = 'hardcoded-value';
1391
+
1392
+ // ✅ Good - use .env file or export
1393
+ // .env
1394
+ SECURENOW_APPID=my-app
1395
+ SECURENOW_INSTANCE=http://localhost:4318
1396
+ ```
1397
+
1398
+ ### 2. Use Structured Logging
1399
+
1400
+ Pass objects to console methods for better filtering:
1401
+
1402
+ ```javascript
1403
+ // ❌ Less useful
1404
+ console.log('User 123 logged in');
1405
+
1406
+ // ✅ Better - structured attributes
1407
+ console.log('User logged in', {
1408
+ userId: 123,
1409
+ email: 'user@example.com',
1410
+ timestamp: new Date().toISOString(),
1411
+ });
1412
+ ```
1413
+
1414
+ ### 3. Choose Appropriate Severity Levels
1415
+
1416
+ ```javascript
1417
+ // Normal operations
1418
+ console.log('Request processed');
1419
+ console.info('User created', { userId: 123 });
1420
+
1421
+ // Warnings
1422
+ console.warn('API rate limit approaching', { remaining: 10 });
1423
+
1424
+ // Errors
1425
+ console.error('Database connection failed', { error: err.message });
1426
+
1427
+ // Debug (only in development)
1428
+ console.debug('Cache hit', { key: 'user:123' });
1429
+ ```
1430
+
1431
+ ### 4. Don't Log Sensitive Data
1432
+
1433
+ Even though SecureNow automatically redacts common sensitive fields, avoid logging:
1434
+
1435
+ ```javascript
1436
+ // ❌ Bad
1437
+ console.log('Login attempt', {
1438
+ email: 'user@example.com',
1439
+ password: 'secret123', // Will be redacted, but don't log it!
1440
+ });
1441
+
1442
+ // Good
1443
+ console.log('Login attempt', {
1444
+ email: 'user@example.com',
1445
+ timestamp: Date.now(),
1446
+ });
1447
+ ```
1448
+
1449
+ ### 5. Use Different Logger Instances for Different Modules
1450
+
1451
+ ```javascript
1452
+ // auth-service.js
1453
+ const authLogger = getLogger('auth-service', '1.0.0');
1454
+
1455
+ // database.js
1456
+ const dbLogger = getLogger('database', '1.0.0');
1457
+
1458
+ // api.js
1459
+ const apiLogger = getLogger('api', '1.0.0');
1460
+ ```
1461
+
1462
+ ### 6. Enable Body Capture Only in Development
1463
+
1464
+ ```bash
1465
+ # .env.development
1466
+ SECURENOW_CAPTURE_BODY=1
1467
+
1468
+ # .env.production
1469
+ SECURENOW_CAPTURE_BODY=0
1470
+ ```
1471
+
1472
+ ---
1473
+
1474
+ ## Supported Runtimes
1475
+
1476
+ - **Node.js:** 18+
1477
+ - **Frameworks:** Express, Next.js, Nuxt 3, Fastify, NestJS, Koa, Hapi, and more
1478
+ - **Databases:** PostgreSQL, MySQL, MongoDB, Redis
1479
+ - **HTTP Clients:** axios, fetch, node-fetch, got, request
1480
+ - **GraphQL:** Apollo Server, GraphQL.js
1481
+ - **Message Queues:** Redis, BullMQ
1482
+ - **And many more via OpenTelemetry auto-instrumentation**
1483
+
1484
+ ---
1485
+
1486
+ ## Automatic Instrumentations
1487
+
1488
+ SecureNow automatically instruments:
1489
+
1490
+ - HTTP/HTTPS (incoming and outgoing)
1491
+ - Express.js
1492
+ - Fastify
1493
+ - Koa
1494
+ - Hapi
1495
+ - Next.js
1496
+ - PostgreSQL
1497
+ - MySQL/MySQL2
1498
+ - MongoDB
1499
+ - Redis
1500
+ - GraphQL
1501
+ - gRPC
1502
+ - DNS
1503
+ - File System
1504
+ - And 50+ more libraries
1505
+
1506
+ No code changes needed!
1507
+
1508
+ ---
1509
+
1510
+ ## Architecture
1511
+
1512
+ ```
1513
+ ┌─────────────────────────────────┐
1514
+ │ Your Application │
1515
+ │ (Express/Next.js/etc) │
1516
+ └───────────────┬─────────────────┘
1517
+
1518
+
1519
+ ┌─────────────────────────────────┐
1520
+ │ SecureNow Library │
1521
+ │ - Auto-instrumentation │
1522
+ │ - Console wrapper (optional) │
1523
+ │ - Body capture (optional) │
1524
+ └───────────────┬─────────────────┘
1525
+
1526
+
1527
+ ┌─────────────────────────────────┐
1528
+ │ OpenTelemetry SDK │
1529
+ - Trace/Log processors
1530
+ - OTLP exporters
1531
+ └───────────────┬─────────────────┘
1532
+
1533
+
1534
+ ┌─────────────────────────────────┐
1535
+ OTLP Collector/Backend
1536
+ (Your observability platform)
1537
+ └─────────────────────────────────┘
1538
+ ```
1539
+
1540
+ ---
1541
+
1542
+ ## Performance
1543
+
1544
+ - **Minimal overhead:** < 1% CPU and memory impact
1545
+ - **Batch export:** Traces and logs are batched before sending
1546
+ - **Async processing:** No blocking of application threads
1547
+ - **Configurable:** Disable instrumentations you don't need
1548
+
1549
+ ---
1550
+
1551
+ ## Security
1552
+
1553
+ - **Automatic redaction** of sensitive fields (passwords, tokens, keys)
1554
+ - **Configurable** sensitive field patterns
1555
+ - **No data stored** locally - everything sent to your OTLP backend
1556
+ - **Open source** - audit the code yourself
1557
+
1558
+ ---
1559
+
1560
+ ## License
1561
+
1562
+ ISC
1563
+
1564
+ ---
1565
+
1566
+ ## Support
1567
+
1568
+ - **Documentation:** [GitHub Docs](https://github.com/your-repo/securenow-npm/tree/main/docs)
1569
+ - **Issues:** [GitHub Issues](https://github.com/your-repo/securenow-npm/issues)
1570
+ - **Examples:** [GitHub Examples](https://github.com/your-repo/securenow-npm/tree/main/examples)
1571
+
1572
+ ---
1573
+
1574
+ ## Changelog
1575
+
1576
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
1577
+
1578
+ ---
1579
+
1580
+ ## Contributing
1581
+
1582
+ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
1583
+
1584
+ ---
1585
+
1586
+ ## Related Packages
1587
+
1588
+ - [@opentelemetry/sdk-node](https://www.npmjs.com/package/@opentelemetry/sdk-node) - Core OpenTelemetry SDK
1589
+ - [@opentelemetry/auto-instrumentations-node](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) - Auto-instrumentation
1590
+ - [@opentelemetry/exporter-trace-otlp-http](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http) - OTLP exporter
1591
+
1592
+ ---
1593
+
1594
+ **Made with ❤️ for the Node.js community**