securenow 5.6.0 → 5.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NPM_README.md CHANGED
@@ -1,1609 +1,1544 @@
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 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
+ > **v5.6.0+:** When `SECURENOW_LOGGING_ENABLED=1`, all `console.log`/`warn`/`error`/`info`/`debug` calls
383
+ > are **automatically** forwarded as OTLP log records. The separate `require('securenow/console-instrumentation')` is no longer needed (but still available for backward compat).
384
+
385
+ ### Express.js
386
+
387
+ ```bash
388
+ npm install securenow express
389
+ ```
390
+
391
+ ```javascript
392
+ // app.js
393
+ require('securenow/register');
394
+ const express = require('express');
395
+
396
+ const app = express();
397
+ app.use(express.json());
398
+
399
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
400
+
401
+ app.post('/tasks', (req, res) => {
402
+ console.log('Created task:', req.body.title);
403
+ res.status(201).json({ id: '1', title: req.body.title });
404
+ });
405
+
406
+ app.listen(3000, () => console.log('Express running on port 3000'));
407
+ ```
408
+
409
+ ```bash
410
+ node app.js
411
+ ```
412
+
413
+ #### With PM2
414
+
415
+ ```javascript
416
+ // ecosystem.config.cjs
417
+ module.exports = {
418
+ apps: [{
419
+ name: 'my-app',
420
+ script: './app.js',
421
+ node_args: '-r securenow/register',
422
+ env: {
423
+ SECURENOW_APPID: 'your-app-key',
424
+ SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
425
+ SECURENOW_LOGGING_ENABLED: '1',
426
+ SECURENOW_NO_UUID: '1',
427
+ SECURENOW_CAPTURE_BODY: '1',
428
+ }
429
+ }]
430
+ };
431
+ ```
432
+
433
+ ---
434
+
435
+ ### Fastify
436
+
437
+ ```bash
438
+ npm install securenow fastify
439
+ ```
440
+
441
+ ```javascript
442
+ // app.js
443
+ require('securenow/register');
444
+ const Fastify = require('fastify');
445
+ const fastify = Fastify({ logger: true });
446
+
447
+ fastify.get('/health', async () => ({ status: 'ok' }));
448
+
449
+ fastify.post('/tasks', {
450
+ schema: { body: { type: 'object', required: ['title'], properties: { title: { type: 'string' } } } }
451
+ }, async (request) => {
452
+ console.log('Created task:', request.body.title);
453
+ return { id: '1', title: request.body.title };
454
+ });
455
+
456
+ fastify.listen({ port: 3000 }, (err) => {
457
+ if (err) { fastify.log.error(err); process.exit(1); }
458
+ console.log('Fastify running on port 3000');
459
+ });
460
+ ```
461
+
462
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify — the body capture hook conflicts with Fastify's internal stream handling.
463
+
464
+ ---
465
+
466
+ ### Koa
467
+
468
+ ```bash
469
+ npm install securenow koa @koa/router koa-bodyparser
470
+ ```
471
+
472
+ ```javascript
473
+ // app.js
474
+ require('securenow/register');
475
+ const Koa = require('koa');
476
+ const Router = require('@koa/router');
477
+ const bodyParser = require('koa-bodyparser');
478
+
479
+ const app = new Koa();
480
+ const router = new Router();
481
+
482
+ router.get('/health', (ctx) => { ctx.body = { status: 'ok' }; });
483
+
484
+ router.post('/tasks', (ctx) => {
485
+ console.log('Created task:', ctx.request.body.title);
486
+ ctx.status = 201;
487
+ ctx.body = { id: '1', title: ctx.request.body.title };
488
+ });
489
+
490
+ app.use(bodyParser());
491
+ app.use(router.routes());
492
+ app.use(router.allowedMethods());
493
+
494
+ app.listen(3000, () => console.log('Koa running on port 3000'));
495
+ ```
496
+
497
+ ---
498
+
499
+ ### NestJS
500
+
501
+ ```bash
502
+ npm install securenow @nestjs/core @nestjs/common reflect-metadata ts-node typescript
503
+ ```
504
+
505
+ NestJS uses TypeScript — securenow is loaded via `-r` flags instead of in-code `require()`:
506
+
507
+ ```typescript
508
+ // app.ts
509
+ import 'reflect-metadata';
510
+ import { NestFactory } from '@nestjs/core';
511
+ import { Module, Controller, Get, Post, Body } from '@nestjs/common';
512
+
513
+ @Controller()
514
+ class AppController {
515
+ @Get('health')
516
+ health() { return { status: 'ok' }; }
517
+
518
+ @Post('tasks')
519
+ create(@Body() body: { title: string }) {
520
+ console.log('Created task:', body.title);
521
+ return { id: '1', title: body.title };
522
+ }
523
+ }
524
+
525
+ @Module({ controllers: [AppController] })
526
+ class AppModule {}
527
+
528
+ async function bootstrap() {
529
+ const app = await NestFactory.create(AppModule);
530
+ await app.listen(3000);
531
+ console.log('NestJS running on port 3000');
532
+ }
533
+ bootstrap();
534
+ ```
535
+
536
+ ```bash
537
+ node -r securenow/register -r ts-node/register app.ts
538
+ ```
539
+
540
+ PM2 config:
541
+
542
+ ```javascript
543
+ {
544
+ name: 'my-nestjs-app',
545
+ script: 'app.ts',
546
+ interpreter: 'node',
547
+ node_args: '-r securenow/register -r ts-node/register',
548
+ }
549
+ ```
550
+
551
+ ---
552
+
553
+ ### Hapi
554
+
555
+ ```bash
556
+ npm install securenow @hapi/hapi
557
+ ```
558
+
559
+ ```javascript
560
+ // app.js
561
+ require('securenow/register');
562
+ const Hapi = require('@hapi/hapi');
563
+
564
+ const init = async () => {
565
+ const server = Hapi.server({ port: 3000, host: '0.0.0.0' });
566
+
567
+ server.route({ method: 'GET', path: '/health', handler: () => ({ status: 'ok' }) });
568
+
569
+ server.route({
570
+ method: 'POST', path: '/tasks',
571
+ options: { payload: { parse: true, allow: 'application/json' } },
572
+ handler: (request, h) => {
573
+ console.log('Created task:', request.payload.title);
574
+ return h.response({ id: '1', title: request.payload.title }).code(201);
575
+ }
576
+ });
577
+
578
+ await server.start();
579
+ console.log('Hapi running on port 3000');
580
+ };
581
+
582
+ init().catch((err) => { console.error(err); process.exit(1); });
583
+ ```
584
+
585
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi — the body capture hook consumes the request stream before Hapi's payload parser.
586
+
587
+ ---
588
+
589
+ ### h3 (UnJS / Nitro)
590
+
591
+ ```bash
592
+ npm install securenow h3
593
+ ```
594
+
595
+ ```javascript
596
+ // app.js
597
+ require('securenow/register');
598
+ const { createApp, createRouter, defineEventHandler, readBody, setResponseStatus, toNodeListener } = require('h3');
599
+ const http = require('http');
600
+
601
+ const app = createApp();
602
+ const router = createRouter();
603
+
604
+ router.get('/health', defineEventHandler(() => ({ status: 'ok' })));
605
+
606
+ router.post('/tasks', defineEventHandler(async (event) => {
607
+ const body = await readBody(event);
608
+ console.log('Created task:', body.title);
609
+ setResponseStatus(event, 201);
610
+ return { id: '1', title: body.title };
611
+ }));
612
+
613
+ app.use(router);
614
+
615
+ http.createServer(toNodeListener(app)).listen(3000, () => {
616
+ console.log('h3 running on port 3000');
617
+ });
618
+ ```
619
+
620
+ ---
621
+
622
+ ### Polka
623
+
624
+ ```bash
625
+ npm install securenow polka
626
+ ```
627
+
628
+ Polka is minimalist — no built-in body parser:
629
+
630
+ ```javascript
631
+ // app.js
632
+ require('securenow/register');
633
+ const polka = require('polka');
634
+
635
+ function jsonBody(req, res, next) {
636
+ if (req.method === 'GET' || req.method === 'DELETE') return next();
637
+ let data = '';
638
+ req.on('data', chunk => { data += chunk; });
639
+ req.on('end', () => { try { req.body = JSON.parse(data); } catch { req.body = {}; } next(); });
640
+ }
641
+
642
+ function sendJson(res, status, body) {
643
+ res.writeHead(status, { 'Content-Type': 'application/json' });
644
+ res.end(JSON.stringify(body));
645
+ }
646
+
647
+ polka()
648
+ .use(jsonBody)
649
+ .get('/health', (req, res) => sendJson(res, 200, { status: 'ok' }))
650
+ .post('/tasks', (req, res) => {
651
+ console.log('Created task:', req.body.title);
652
+ sendJson(res, 201, { id: '1', title: req.body.title });
653
+ })
654
+ .listen(3000, () => console.log('Polka running on port 3000'));
655
+ ```
656
+
657
+ ---
658
+
659
+ ### Micro / Raw HTTP
660
+
661
+ For apps using Node's bare `http` module:
662
+
663
+ ```bash
664
+ npm install securenow
665
+ ```
666
+
667
+ ```javascript
668
+ // app.js
669
+ require('securenow/register');
670
+ const http = require('http');
671
+
672
+ function sendJson(res, status, body) {
673
+ res.writeHead(status, { 'Content-Type': 'application/json' });
674
+ res.end(JSON.stringify(body));
675
+ }
676
+
677
+ function readBody(req) {
678
+ return new Promise((resolve) => {
679
+ let d = ''; req.on('data', c => { d += c; }); req.on('end', () => { try { resolve(JSON.parse(d)); } catch { resolve({}); } });
680
+ });
681
+ }
682
+
683
+ async function handler(req, res) {
684
+ const url = new URL(req.url, `http://${req.headers.host}`);
685
+ if (url.pathname === '/health') return sendJson(res, 200, { status: 'ok' });
686
+ if (url.pathname === '/tasks' && req.method === 'POST') {
687
+ const body = await readBody(req);
688
+ console.log('Created task:', body.title);
689
+ return sendJson(res, 201, { id: '1', title: body.title });
690
+ }
691
+ sendJson(res, 404, { error: 'Not found' });
692
+ }
693
+
694
+ http.createServer(handler).listen(3000, () => console.log('HTTP running on port 3000'));
695
+ ```
696
+
697
+ ---
698
+
699
+ ### Hono (ESM)
700
+
701
+ ```bash
702
+ npm install securenow hono @hono/node-server
703
+ ```
704
+
705
+ Hono uses ESM securenow must be preloaded via `-r` flag:
706
+
707
+ ```javascript
708
+ // app.mjs
709
+ import { serve } from '@hono/node-server';
710
+ import { Hono } from 'hono';
711
+
712
+ const app = new Hono();
713
+
714
+ app.get('/health', (c) => c.json({ status: 'ok' }));
715
+
716
+ app.post('/tasks', async (c) => {
717
+ const body = await c.req.json();
718
+ console.log('Created task:', body.title);
719
+ return c.json({ id: '1', title: body.title }, 201);
720
+ });
721
+
722
+ serve({ fetch: app.fetch, port: 3000 }, () => console.log('Hono running on port 3000'));
723
+ ```
724
+
725
+ ```bash
726
+ node -r securenow/register app.mjs
727
+ ```
728
+
729
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hono. Do **not** add `require('securenow/register')` inside `.mjs` files.
730
+
731
+ ---
732
+
733
+ ### Feathers
734
+
735
+ ```bash
736
+ npm install securenow @feathersjs/feathers @feathersjs/express @feathersjs/errors
737
+ ```
738
+
739
+ Feathers uses Express transport — same setup as Express:
740
+
741
+ ```javascript
742
+ // app.js
743
+ require('securenow/register');
744
+ const feathers = require('@feathersjs/feathers');
745
+ const express = require('@feathersjs/express');
746
+ const errors = require('@feathersjs/errors');
747
+
748
+ class TaskService {
749
+ constructor() { this.tasks = []; this.nextId = 1; }
750
+ async find() { return this.tasks; }
751
+ async create(data) {
752
+ if (!data.title) throw new errors.BadRequest('title is required');
753
+ const task = { id: String(this.nextId++), title: data.title };
754
+ this.tasks.push(task);
755
+ console.log('Created task:', task.id);
756
+ return task;
757
+ }
758
+ }
759
+
760
+ const app = express(feathers());
761
+ app.use(express.json());
762
+ app.configure(express.rest());
763
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
764
+ app.use('/tasks', new TaskService());
765
+ app.use(express.errorHandler());
766
+
767
+ app.listen(3000, () => console.log('Feathers running on port 3000'));
768
+ ```
769
+
770
+ ---
771
+
772
+ ### Next.js
773
+
774
+ See [Next.js Complete Guide →](./docs/NEXTJS-SETUP-COMPLETE.md)
775
+
776
+ Create `instrumentation.ts` in your project root:
777
+
778
+ ```typescript
779
+ export async function register() {
780
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
781
+ await import('securenow/register');
782
+ }
783
+ }
784
+ ```
785
+
786
+ `.env.local`:
787
+
788
+ ```env
789
+ SECURENOW_APPID=my-nextjs-app
790
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
791
+ SECURENOW_LOGGING_ENABLED=1
792
+ SECURENOW_NO_UUID=1
793
+ ```
794
+
795
+ ---
796
+
797
+ ### Compatibility Matrix
798
+
799
+ | Framework | Traces | Logs | Body Capture | Notes |
800
+ |-----------|--------|------|--------------|-------|
801
+ | Express | Yes | Yes | Yes | Fully compatible |
802
+ | Fastify | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
803
+ | Koa | Yes | Yes | Yes | Needs `koa-bodyparser` |
804
+ | NestJS | Yes | Yes | Yes | Use `-r ts-node/register` |
805
+ | Hapi | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
806
+ | h3 | Yes | Yes | Yes | Uses `toNodeListener()` |
807
+ | Polka | Yes | Yes | Yes | Needs manual body parser |
808
+ | Micro/HTTP | Yes | Yes | Yes | Full control |
809
+ | Hono | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
810
+ | Feathers | Yes | Yes | Yes | Uses Express transport |
811
+ | Next.js | Yes | Yes | Yes | Use `instrumentation.ts` |
812
+
813
+ ---
814
+
815
+ ## Environment Variables Reference
816
+
817
+ ### Required Variables
818
+
819
+ | Variable | Description | Example |
820
+ |----------|-------------|---------|
821
+ | `SECURENOW_APPID` | Your application identifier. Used as the service name in traces. | `my-app` |
822
+ | `SECURENOW_INSTANCE` | Base URL of your OTLP collector endpoint. | `http://localhost:4318` |
823
+
824
+ ### Optional Configuration
825
+
826
+ #### Service Naming
827
+
828
+ | Variable | Description | Default |
829
+ |----------|-------------|---------|
830
+ | `OTEL_SERVICE_NAME` | Alternative to SECURENOW_APPID. Standard OpenTelemetry variable. | - |
831
+ | `SECURENOW_NO_UUID` | Set to `1` to disable UUID suffix on service name. Useful for clustered apps. | `0` |
832
+ | `SECURENOW_STRICT` | Set to `1` to exit process if SECURENOW_APPID is not set in cluster mode. | `0` |
833
+
834
+ #### Connection Settings
835
+
836
+ | Variable | Description | Default |
837
+ |----------|-------------|---------|
838
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Alternative to SECURENOW_INSTANCE. Standard OpenTelemetry variable. | - |
839
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically. | `{SECURENOW_INSTANCE}/v1/traces` |
840
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically. | `{SECURENOW_INSTANCE}/v1/logs` |
841
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Headers to send with OTLP exports. Format: `key1=value1,key2=value2` | - |
842
+
843
+ #### Logging
844
+
845
+ | Variable | Description | Default |
846
+ |----------|-------------|---------|
847
+ | `SECURENOW_LOGGING_ENABLED` | Enable automatic logging to OTLP backend. Set to `1` to enable, `0` to disable. | `1` |
848
+
849
+ #### Request Body Capture
850
+
851
+ | Variable | Description | Default |
852
+ |----------|-------------|---------|
853
+ | `SECURENOW_CAPTURE_BODY` | Enable request body capture in traces. Set to `1` to enable. | `0` |
854
+ | `SECURENOW_MAX_BODY_SIZE` | Maximum body size to capture in bytes. Bodies larger than this are truncated. | `10240` (10KB) |
855
+ | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated list of additional field names to redact. | - |
856
+
857
+ **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`
858
+
859
+ #### Instrumentation Control
860
+
861
+ | Variable | Description | Default |
862
+ |----------|-------------|---------|
863
+ | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated list of instrumentation packages to disable. | - |
864
+
865
+ **Example:** `SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns` disables filesystem and DNS instrumentations.
866
+
867
+ #### Debugging
868
+
869
+ | Variable | Description | Default |
870
+ |----------|-------------|---------|
871
+ | `OTEL_LOG_LEVEL` | OpenTelemetry SDK log level. Options: `debug`, `info`, `warn`, `error` | `none` |
872
+ | `SECURENOW_TEST_SPAN` | Set to `1` to emit a test span on startup. | `0` |
873
+
874
+ #### Environment
875
+
876
+ | Variable | Description | Default |
877
+ |----------|-------------|---------|
878
+ | `NODE_ENV` | Deployment environment name. Sent as `deployment.environment` attribute. | `production` |
879
+
880
+ ---
881
+
882
+ ## Logging Setup
883
+
884
+ ### Automatic Console Logging
885
+
886
+ Since **v5.6.0**, when `SECURENOW_LOGGING_ENABLED=1`, all console calls are automatically forwarded as OTLP log records:
887
+
888
+ ```javascript
889
+ // At the top of your main file
890
+ require('securenow/register');
891
+
892
+ // With SECURENOW_LOGGING_ENABLED=1, all console logs are automatically sent
893
+ console.log('Application started');
894
+ console.info('User action', { userId: 123, action: 'login' });
895
+ console.warn('Deprecation warning');
896
+ console.error('Error occurred', { error: 'Something failed' });
897
+ console.debug('Debug info');
898
+ ```
899
+
900
+ **Severity mapping:**
901
+ - `console.log()` → INFO
902
+ - `console.info()` → INFO
903
+ - `console.warn()` WARN
904
+ - `console.error()` → ERROR
905
+ - `console.debug()` DEBUG
906
+
907
+ **Environment variable:**
908
+ ```bash
909
+ SECURENOW_LOGGING_ENABLED=1
910
+ ```
911
+
912
+ ### Direct Logger API
913
+
914
+ For more control, use the OpenTelemetry logger API:
915
+
916
+ ```javascript
917
+ require('securenow/register');
918
+ const { getLogger } = require('securenow/tracing');
919
+
920
+ // Get a logger instance
921
+ const logger = getLogger('my-module', '1.0.0');
922
+
923
+ // Emit structured logs
924
+ logger.emit({
925
+ severityNumber: 9, // INFO
926
+ severityText: 'INFO',
927
+ body: 'User logged in',
928
+ attributes: {
929
+ userId: 123,
930
+ username: 'john',
931
+ sessionId: 'abc123',
932
+ },
933
+ });
934
+ ```
935
+
936
+ **Severity numbers:**
937
+ - `5` - DEBUG
938
+ - `9` - INFO
939
+ - `13` - WARN
940
+ - `17` - ERROR
941
+
942
+ ### Using with NODE_OPTIONS
943
+
944
+ ```bash
945
+ # Enable tracing + logging (console auto-forwarding is built-in since v5.6.0)
946
+ NODE_OPTIONS="-r securenow/register" \
947
+ SECURENOW_APPID=my-app \
948
+ SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318 \
949
+ SECURENOW_LOGGING_ENABLED=1 \
950
+ node app.js
951
+ ```
952
+
953
+ ---
954
+
955
+ ## Request Body Capture
956
+
957
+ SecureNow can capture HTTP request bodies in traces for debugging purposes. This is disabled by default.
958
+
959
+ ### Enable Body Capture
960
+
961
+ ```bash
962
+ export SECURENOW_CAPTURE_BODY=1
963
+ export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
964
+ ```
965
+
966
+ ### Supported Content Types
967
+
968
+ - `application/json`
969
+ - `application/x-www-form-urlencoded`
970
+ - `application/graphql`
971
+
972
+ **Note:** Multipart form data (file uploads) are NOT captured by design.
973
+
974
+ ### Sensitive Data Redaction
975
+
976
+ All request bodies are automatically scanned and sensitive fields are redacted:
977
+
978
+ **Automatically redacted fields:** `password`, `secret`, `token`, `api_key`, `card`, `cvv`, `ssn`, and more.
979
+
980
+ **Add custom fields to redact:**
981
+
982
+ ```bash
983
+ export SECURENOW_SENSITIVE_FIELDS="custom_secret,internal_token"
984
+ ```
985
+
986
+ ### Example
987
+
988
+ ```javascript
989
+ // POST /api/users with body:
990
+ {
991
+ "email": "user@example.com",
992
+ "password": "secret123",
993
+ "name": "John Doe"
994
+ }
995
+
996
+ // Captured in trace as:
997
+ {
998
+ "email": "user@example.com",
999
+ "password": "[REDACTED]",
1000
+ "name": "John Doe"
1001
+ }
1002
+ ```
1003
+
1004
+ ---
1005
+
1006
+ ## Advanced Configuration
1007
+
1008
+ ### Complete Example with All Options
1009
+
1010
+ ```bash
1011
+ # Service identification
1012
+ export SECURENOW_APPID=my-production-app
1013
+ export SECURENOW_NO_UUID=1
1014
+ export SECURENOW_STRICT=1
1015
+
1016
+ # OTLP backend
1017
+ export SECURENOW_INSTANCE=http://collector.example.com:4318
1018
+ export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key"
1019
+
1020
+ # Logging
1021
+ export SECURENOW_LOGGING_ENABLED=1
1022
+
1023
+ # Request body capture
1024
+ export SECURENOW_CAPTURE_BODY=1
1025
+ export SECURENOW_MAX_BODY_SIZE=20480
1026
+ export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
1027
+
1028
+ # Environment
1029
+ export NODE_ENV=production
1030
+
1031
+ # Debugging
1032
+ export OTEL_LOG_LEVEL=info
1033
+
1034
+ # Disable specific instrumentations
1035
+ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
1036
+
1037
+ # Run application
1038
+ NODE_OPTIONS="-r securenow/register" node app.js
1039
+ ```
1040
+
1041
+ ### Using Multiple Logger Instances
1042
+
1043
+ ```javascript
1044
+ const { getLogger } = require('securenow/tracing');
1045
+
1046
+ const authLogger = getLogger('auth-service', '1.0.0');
1047
+ const dbLogger = getLogger('database', '1.0.0');
1048
+ const apiLogger = getLogger('api-handler', '1.0.0');
1049
+
1050
+ authLogger.emit({
1051
+ severityNumber: 9,
1052
+ severityText: 'INFO',
1053
+ body: 'User authenticated',
1054
+ attributes: { userId: 123 },
1055
+ });
1056
+
1057
+ dbLogger.emit({
1058
+ severityNumber: 13,
1059
+ severityText: 'WARN',
1060
+ body: 'Slow query detected',
1061
+ attributes: { queryTime: 5000 },
1062
+ });
1063
+ ```
1064
+
1065
+ ### Check if Logging is Enabled
1066
+
1067
+ ```javascript
1068
+ const { isLoggingEnabled } = require('securenow/tracing');
1069
+
1070
+ if (isLoggingEnabled()) {
1071
+ console.log('Logging is enabled');
1072
+ } else {
1073
+ console.log('Logging is disabled');
1074
+ }
1075
+ ```
1076
+
1077
+ ### Programmatic Configuration
1078
+
1079
+ While environment variables are recommended, you can also configure programmatically:
1080
+
1081
+ ```javascript
1082
+ // Set environment variables before requiring securenow
1083
+ process.env.SECURENOW_APPID = 'my-app';
1084
+ process.env.SECURENOW_INSTANCE = 'http://localhost:4318';
1085
+ process.env.SECURENOW_LOGGING_ENABLED = '1';
1086
+
1087
+ // Then initialize (console log forwarding is automatic since v5.6.0)
1088
+ require('securenow/register');
1089
+ ```
1090
+
1091
+ ---
1092
+
1093
+ ## TypeScript Support
1094
+
1095
+ SecureNow includes full TypeScript definitions.
1096
+
1097
+ ### Type Definitions
1098
+
1099
+ ```typescript
1100
+ import { getLogger, isLoggingEnabled, Logger, LogRecord } from 'securenow/tracing';
1101
+
1102
+ // Get a typed logger
1103
+ const logger: Logger | null = getLogger('my-service', '1.0.0');
1104
+
1105
+ // Emit a log with type checking
1106
+ if (logger) {
1107
+ const logRecord: LogRecord = {
1108
+ severityNumber: 9,
1109
+ severityText: 'INFO',
1110
+ body: 'User action',
1111
+ attributes: {
1112
+ userId: 123,
1113
+ action: 'login',
1114
+ },
1115
+ };
1116
+
1117
+ logger.emit(logRecord);
1118
+ }
1119
+
1120
+ // Check if enabled
1121
+ const enabled: boolean = isLoggingEnabled();
1122
+ ```
1123
+
1124
+ ### Next.js with TypeScript
1125
+
1126
+ ```typescript
1127
+ // instrumentation.ts
1128
+ export async function register() {
1129
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
1130
+ process.env.SECURENOW_LOGGING_ENABLED = '1';
1131
+
1132
+ await import('securenow/register');
1133
+ }
1134
+ }
1135
+ ```
1136
+
1137
+ ### NestJS with TypeScript
1138
+
1139
+ Use `-r securenow/register -r ts-node/register` flags instead of in-code require:
1140
+
1141
+ ```typescript
1142
+ // main.ts (run with: node -r securenow/register -r ts-node/register main.ts)
1143
+ import { NestFactory } from '@nestjs/core';
1144
+ import { AppModule } from './app.module';
1145
+
1146
+ async function bootstrap() {
1147
+ const app = await NestFactory.create(AppModule);
1148
+ await app.listen(3000);
1149
+ }
1150
+
1151
+ bootstrap();
1152
+ ```
1153
+
1154
+ ---
1155
+
1156
+ ## Troubleshooting
1157
+
1158
+ ### Traces Not Appearing
1159
+
1160
+ **Check 1: Verify environment variables**
1161
+
1162
+ ```bash
1163
+ echo $SECURENOW_APPID
1164
+ echo $SECURENOW_INSTANCE
1165
+ ```
1166
+
1167
+ Both should output values.
1168
+
1169
+ **Check 2: Verify OTLP collector is running**
1170
+
1171
+ ```bash
1172
+ curl http://localhost:4318/v1/traces
1173
+ # Should return 200 or 405 (method not allowed)
1174
+ ```
1175
+
1176
+ **Check 3: Enable debug logging**
1177
+
1178
+ ```bash
1179
+ export OTEL_LOG_LEVEL=debug
1180
+ node app.js
1181
+ ```
1182
+
1183
+ Look for lines like:
1184
+ ```
1185
+ [securenow] OTel SDK started → http://localhost:4318/v1/traces
1186
+ ```
1187
+
1188
+ **Check 4: Verify initialization order**
1189
+
1190
+ SecureNow must be required BEFORE any other modules:
1191
+
1192
+ ```javascript
1193
+ // ✅ Correct
1194
+ require('securenow/register');
1195
+ const express = require('express');
1196
+
1197
+ // ❌ Wrong - too late!
1198
+ const express = require('express');
1199
+ require('securenow/register');
1200
+ ```
1201
+
1202
+ ### Logs Not Appearing
1203
+
1204
+ **Check 1: Is logging enabled?**
1205
+
1206
+ ```bash
1207
+ echo $SECURENOW_LOGGING_ENABLED
1208
+ # Should output: 1
1209
+ ```
1210
+
1211
+ **Check 2: Verify console instrumentation is loaded**
1212
+
1213
+ ```javascript
1214
+ require('securenow/register');
1215
+ ```
1216
+
1217
+ **Check 3: Check console output**
1218
+
1219
+ You should see:
1220
+ ```
1221
+ [securenow] 📋 Logging: ENABLED → http://localhost:4318/v1/logs
1222
+ ```
1223
+
1224
+ **Check 4: Verify OTLP logs endpoint**
1225
+
1226
+ ```bash
1227
+ curl http://localhost:4318/v1/logs
1228
+ # Should return 200 or 405
1229
+ ```
1230
+
1231
+ ### Request Body Not Captured
1232
+
1233
+ **Check 1: Is body capture enabled?**
1234
+
1235
+ ```bash
1236
+ export SECURENOW_CAPTURE_BODY=1
1237
+ ```
1238
+
1239
+ **Check 2: Verify content type**
1240
+
1241
+ Body capture only works for:
1242
+ - `application/json`
1243
+ - `application/x-www-form-urlencoded`
1244
+ - `application/graphql`
1245
+
1246
+ **Check 3: Check body size**
1247
+
1248
+ Bodies larger than `SECURENOW_MAX_BODY_SIZE` are truncated:
1249
+
1250
+ ```bash
1251
+ export SECURENOW_MAX_BODY_SIZE=20480 # Increase to 20KB
1252
+ ```
1253
+
1254
+ ### High Memory Usage
1255
+
1256
+ **Option 1: Disable body capture**
1257
+
1258
+ ```bash
1259
+ export SECURENOW_CAPTURE_BODY=0
1260
+ ```
1261
+
1262
+ **Option 2: Reduce body size limit**
1263
+
1264
+ ```bash
1265
+ export SECURENOW_MAX_BODY_SIZE=5120 # 5KB
1266
+ ```
1267
+
1268
+ **Option 3: Disable specific instrumentations**
1269
+
1270
+ ```bash
1271
+ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
1272
+ ```
1273
+
1274
+ ### Next.js Instrumentation Not Working
1275
+
1276
+ **Check 1: Verify instrumentation file location**
1277
+
1278
+ `instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
1279
+
1280
+ **Check 2: Enable instrumentation hook**
1281
+
1282
+ ```javascript
1283
+ // next.config.js
1284
+ module.exports = {
1285
+ experimental: {
1286
+ instrumentationHook: true,
1287
+ },
1288
+ };
1289
+ ```
1290
+
1291
+ **Check 3: Restart dev server**
1292
+
1293
+ ```bash
1294
+ # Kill the server and restart
1295
+ npm run dev
1296
+ ```
1297
+
1298
+ ### PM2 Cluster Issues
1299
+
1300
+ **Problem: Different service names for each worker**
1301
+
1302
+ **Solution: Use SECURENOW_NO_UUID**
1303
+
1304
+ ```bash
1305
+ export SECURENOW_NO_UUID=1
1306
+ ```
1307
+
1308
+ This uses the same service name for all workers.
1309
+
1310
+ **Problem: Workers not instrumented**
1311
+
1312
+ **Solution: Use node_args in PM2 config**
1313
+
1314
+ ```javascript
1315
+ // ecosystem.config.js
1316
+ module.exports = {
1317
+ apps: [{
1318
+ name: 'my-app',
1319
+ script: './app.js',
1320
+ instances: 4,
1321
+ node_args: '-r securenow/register',
1322
+ env: {
1323
+ SECURENOW_APPID: 'my-app',
1324
+ SECURENOW_INSTANCE: 'http://localhost:4318',
1325
+ }
1326
+ }]
1327
+ };
1328
+ ```
1329
+
1330
+ ---
1331
+
1332
+ ## Best Practices
1333
+
1334
+ ### 1. Use Environment Variables
1335
+
1336
+ Don't hardcode configuration. Use environment variables:
1337
+
1338
+ ```javascript
1339
+ // Bad
1340
+ process.env.SECURENOW_APPID = 'hardcoded-value';
1341
+
1342
+ // ✅ Good - use .env file or export
1343
+ // .env
1344
+ SECURENOW_APPID=my-app
1345
+ SECURENOW_INSTANCE=http://localhost:4318
1346
+ ```
1347
+
1348
+ ### 2. Use Structured Logging
1349
+
1350
+ Pass objects to console methods for better filtering:
1351
+
1352
+ ```javascript
1353
+ // ❌ Less useful
1354
+ console.log('User 123 logged in');
1355
+
1356
+ // Better - structured attributes
1357
+ console.log('User logged in', {
1358
+ userId: 123,
1359
+ email: 'user@example.com',
1360
+ timestamp: new Date().toISOString(),
1361
+ });
1362
+ ```
1363
+
1364
+ ### 3. Choose Appropriate Severity Levels
1365
+
1366
+ ```javascript
1367
+ // Normal operations
1368
+ console.log('Request processed');
1369
+ console.info('User created', { userId: 123 });
1370
+
1371
+ // Warnings
1372
+ console.warn('API rate limit approaching', { remaining: 10 });
1373
+
1374
+ // Errors
1375
+ console.error('Database connection failed', { error: err.message });
1376
+
1377
+ // Debug (only in development)
1378
+ console.debug('Cache hit', { key: 'user:123' });
1379
+ ```
1380
+
1381
+ ### 4. Don't Log Sensitive Data
1382
+
1383
+ Even though SecureNow automatically redacts common sensitive fields, avoid logging:
1384
+
1385
+ ```javascript
1386
+ // Bad
1387
+ console.log('Login attempt', {
1388
+ email: 'user@example.com',
1389
+ password: 'secret123', // Will be redacted, but don't log it!
1390
+ });
1391
+
1392
+ // ✅ Good
1393
+ console.log('Login attempt', {
1394
+ email: 'user@example.com',
1395
+ timestamp: Date.now(),
1396
+ });
1397
+ ```
1398
+
1399
+ ### 5. Use Different Logger Instances for Different Modules
1400
+
1401
+ ```javascript
1402
+ // auth-service.js
1403
+ const authLogger = getLogger('auth-service', '1.0.0');
1404
+
1405
+ // database.js
1406
+ const dbLogger = getLogger('database', '1.0.0');
1407
+
1408
+ // api.js
1409
+ const apiLogger = getLogger('api', '1.0.0');
1410
+ ```
1411
+
1412
+ ### 6. Enable Body Capture Only in Development
1413
+
1414
+ ```bash
1415
+ # .env.development
1416
+ SECURENOW_CAPTURE_BODY=1
1417
+
1418
+ # .env.production
1419
+ SECURENOW_CAPTURE_BODY=0
1420
+ ```
1421
+
1422
+ ---
1423
+
1424
+ ## Supported Runtimes
1425
+
1426
+ - **Node.js:** 18+
1427
+ - **Frameworks:** Express, Next.js, Fastify, NestJS, Koa, Hapi, and more
1428
+ - **Databases:** PostgreSQL, MySQL, MongoDB, Redis
1429
+ - **HTTP Clients:** axios, fetch, node-fetch, got, request
1430
+ - **GraphQL:** Apollo Server, GraphQL.js
1431
+ - **Message Queues:** Redis, BullMQ
1432
+ - **And many more via OpenTelemetry auto-instrumentation**
1433
+
1434
+ ---
1435
+
1436
+ ## Automatic Instrumentations
1437
+
1438
+ SecureNow automatically instruments:
1439
+
1440
+ - HTTP/HTTPS (incoming and outgoing)
1441
+ - Express.js
1442
+ - Fastify
1443
+ - Koa
1444
+ - Hapi
1445
+ - Next.js
1446
+ - PostgreSQL
1447
+ - MySQL/MySQL2
1448
+ - MongoDB
1449
+ - Redis
1450
+ - GraphQL
1451
+ - gRPC
1452
+ - DNS
1453
+ - File System
1454
+ - And 50+ more libraries
1455
+
1456
+ No code changes needed!
1457
+
1458
+ ---
1459
+
1460
+ ## Architecture
1461
+
1462
+ ```
1463
+ ┌─────────────────────────────────┐
1464
+ │ Your Application │
1465
+ │ (Express/Next.js/etc) │
1466
+ └───────────────┬─────────────────┘
1467
+
1468
+
1469
+ ┌─────────────────────────────────┐
1470
+ │ SecureNow Library │
1471
+ │ - Auto-instrumentation │
1472
+ │ - Console wrapper (optional) │
1473
+ │ - Body capture (optional) │
1474
+ └───────────────┬─────────────────┘
1475
+
1476
+
1477
+ ┌─────────────────────────────────┐
1478
+ │ OpenTelemetry SDK │
1479
+ │ - Trace/Log processors │
1480
+ │ - OTLP exporters │
1481
+ └───────────────┬─────────────────┘
1482
+
1483
+
1484
+ ┌─────────────────────────────────┐
1485
+ │ OTLP Collector/Backend │
1486
+ │ (Your observability platform) │
1487
+ └─────────────────────────────────┘
1488
+ ```
1489
+
1490
+ ---
1491
+
1492
+ ## Performance
1493
+
1494
+ - **Minimal overhead:** < 1% CPU and memory impact
1495
+ - **Batch export:** Traces and logs are batched before sending
1496
+ - **Async processing:** No blocking of application threads
1497
+ - **Configurable:** Disable instrumentations you don't need
1498
+
1499
+ ---
1500
+
1501
+ ## Security
1502
+
1503
+ - **Automatic redaction** of sensitive fields (passwords, tokens, keys)
1504
+ - **Configurable** sensitive field patterns
1505
+ - **No data stored** locally - everything sent to your OTLP backend
1506
+ - **Open source** - audit the code yourself
1507
+
1508
+ ---
1509
+
1510
+ ## License
1511
+
1512
+ ISC
1513
+
1514
+ ---
1515
+
1516
+ ## Support
1517
+
1518
+ - **Documentation:** [GitHub Docs](https://github.com/your-repo/securenow-npm/tree/main/docs)
1519
+ - **Issues:** [GitHub Issues](https://github.com/your-repo/securenow-npm/issues)
1520
+ - **Examples:** [GitHub Examples](https://github.com/your-repo/securenow-npm/tree/main/examples)
1521
+
1522
+ ---
1523
+
1524
+ ## Changelog
1525
+
1526
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
1527
+
1528
+ ---
1529
+
1530
+ ## Contributing
1531
+
1532
+ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
1533
+
1534
+ ---
1535
+
1536
+ ## Related Packages
1537
+
1538
+ - [@opentelemetry/sdk-node](https://www.npmjs.com/package/@opentelemetry/sdk-node) - Core OpenTelemetry SDK
1539
+ - [@opentelemetry/auto-instrumentations-node](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) - Auto-instrumentation
1540
+ - [@opentelemetry/exporter-trace-otlp-http](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http) - OTLP exporter
1541
+
1542
+ ---
1543
+
1544
+ **Made with ❤️ for the Node.js community**