securenow 4.0.12 → 5.0.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/CONSUMING-APPS-GUIDE.md +415 -0
- package/NPM_README.md +1328 -0
- package/README.md +42 -2
- package/console-instrumentation.js +136 -0
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +455 -0
- package/docs/ENVIRONMENT-VARIABLES.md +652 -0
- package/docs/EXPRESS-SETUP-GUIDE.md +720 -0
- package/docs/INDEX.md +206 -129
- package/docs/LOGGING-GUIDE.md +708 -0
- package/docs/LOGGING-QUICKSTART.md +239 -0
- package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
- package/examples/express-with-logging.js +137 -0
- package/examples/nextjs-with-logging-example.md +301 -0
- package/package.json +14 -3
- package/tracing.d.ts +182 -89
- package/tracing.js +61 -10
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express.js Example with SecureNow Tracing and Logging
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates:
|
|
5
|
+
* - Automatic tracing of HTTP requests
|
|
6
|
+
* - Automatic logging via console instrumentation
|
|
7
|
+
* - Structured logging with context
|
|
8
|
+
*
|
|
9
|
+
* Setup:
|
|
10
|
+
* 1. npm install securenow express
|
|
11
|
+
* 2. export SECURENOW_LOGGING_ENABLED=1
|
|
12
|
+
* 3. export SECURENOW_APPID=express-demo
|
|
13
|
+
* 4. export SECURENOW_INSTANCE=http://localhost:4318
|
|
14
|
+
* 5. node examples/express-with-logging.js
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Initialize SecureNow (must be first!)
|
|
18
|
+
require('securenow/register');
|
|
19
|
+
require('securenow/console-instrumentation');
|
|
20
|
+
|
|
21
|
+
const express = require('express');
|
|
22
|
+
const app = express();
|
|
23
|
+
|
|
24
|
+
app.use(express.json());
|
|
25
|
+
|
|
26
|
+
// Logging middleware
|
|
27
|
+
app.use((req, res, next) => {
|
|
28
|
+
console.info('Incoming request', {
|
|
29
|
+
method: req.method,
|
|
30
|
+
path: req.path,
|
|
31
|
+
query: req.query,
|
|
32
|
+
ip: req.ip,
|
|
33
|
+
userAgent: req.get('user-agent'),
|
|
34
|
+
});
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Routes
|
|
39
|
+
app.get('/', (req, res) => {
|
|
40
|
+
console.log('Home page accessed');
|
|
41
|
+
res.json({
|
|
42
|
+
message: 'Express with SecureNow Logging',
|
|
43
|
+
timestamp: new Date().toISOString(),
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
app.get('/users', (req, res) => {
|
|
48
|
+
console.log('Fetching users list');
|
|
49
|
+
|
|
50
|
+
// Simulate user data
|
|
51
|
+
const users = [
|
|
52
|
+
{ id: 1, name: 'John Doe' },
|
|
53
|
+
{ id: 2, name: 'Jane Smith' },
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
console.info('Users fetched successfully', {
|
|
57
|
+
count: users.length,
|
|
58
|
+
requestId: req.get('x-request-id'),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
res.json(users);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
app.post('/users', (req, res) => {
|
|
65
|
+
console.info('Creating new user', {
|
|
66
|
+
userData: req.body,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Simulate validation
|
|
71
|
+
if (!req.body.name || !req.body.email) {
|
|
72
|
+
console.warn('User creation validation failed', {
|
|
73
|
+
body: req.body,
|
|
74
|
+
missing: !req.body.name ? 'name' : 'email',
|
|
75
|
+
});
|
|
76
|
+
return res.status(400).json({ error: 'Name and email required' });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Simulate user creation
|
|
80
|
+
const newUser = {
|
|
81
|
+
id: Math.floor(Math.random() * 1000),
|
|
82
|
+
...req.body,
|
|
83
|
+
createdAt: new Date().toISOString(),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
console.log('User created successfully', {
|
|
87
|
+
userId: newUser.id,
|
|
88
|
+
email: newUser.email,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
res.status(201).json(newUser);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('Failed to create user', {
|
|
94
|
+
error: error.message,
|
|
95
|
+
stack: error.stack,
|
|
96
|
+
body: req.body,
|
|
97
|
+
});
|
|
98
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
app.get('/error', (req, res) => {
|
|
103
|
+
console.warn('Error endpoint accessed - will throw error');
|
|
104
|
+
throw new Error('Intentional error for testing');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Error handler
|
|
108
|
+
app.use((err, req, res, next) => {
|
|
109
|
+
console.error('Express error handler', {
|
|
110
|
+
error: err.message,
|
|
111
|
+
stack: err.stack,
|
|
112
|
+
path: req.path,
|
|
113
|
+
method: req.method,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
res.status(500).json({
|
|
117
|
+
error: 'Internal server error',
|
|
118
|
+
message: err.message,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Start server
|
|
123
|
+
const PORT = process.env.PORT || 3000;
|
|
124
|
+
app.listen(PORT, () => {
|
|
125
|
+
console.log('Express server started', {
|
|
126
|
+
port: PORT,
|
|
127
|
+
nodeVersion: process.version,
|
|
128
|
+
env: process.env.NODE_ENV || 'development',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
console.info('Available endpoints:', {
|
|
132
|
+
home: `http://localhost:${PORT}/`,
|
|
133
|
+
users: `http://localhost:${PORT}/users`,
|
|
134
|
+
createUser: `POST http://localhost:${PORT}/users`,
|
|
135
|
+
error: `http://localhost:${PORT}/error`,
|
|
136
|
+
});
|
|
137
|
+
});
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Next.js with Logging Example
|
|
2
|
+
|
|
3
|
+
This example shows how to set up logging in a Next.js application.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Install SecureNow
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install securenow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### 2. Create `instrumentation.ts`
|
|
14
|
+
|
|
15
|
+
Create `instrumentation.ts` in your project root (same level as `app/` or `pages/`):
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// instrumentation.ts
|
|
19
|
+
export async function register() {
|
|
20
|
+
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
21
|
+
// Enable logging
|
|
22
|
+
process.env.SECURENOW_LOGGING_ENABLED = '1';
|
|
23
|
+
|
|
24
|
+
// Initialize tracing and logging
|
|
25
|
+
await import('securenow/register');
|
|
26
|
+
await import('securenow/console-instrumentation');
|
|
27
|
+
|
|
28
|
+
console.log('SecureNow initialized with logging enabled');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Configure Environment Variables
|
|
34
|
+
|
|
35
|
+
Create `.env.local`:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
SECURENOW_LOGGING_ENABLED=1
|
|
39
|
+
SECURENOW_APPID=my-nextjs-app
|
|
40
|
+
SECURENOW_INSTANCE=http://localhost:4318
|
|
41
|
+
|
|
42
|
+
# For SigNoz Cloud:
|
|
43
|
+
# SECURENOW_INSTANCE=https://ingest.<region>.signoz.cloud:443
|
|
44
|
+
# OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-key>"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 4. Enable Instrumentation in `next.config.js`
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
// next.config.js
|
|
51
|
+
/** @type {import('next').NextConfig} */
|
|
52
|
+
const nextConfig = {
|
|
53
|
+
experimental: {
|
|
54
|
+
instrumentationHook: true,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = nextConfig;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage Examples
|
|
62
|
+
|
|
63
|
+
### API Route with Logging
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// app/api/users/route.ts
|
|
67
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
68
|
+
|
|
69
|
+
export async function GET(request: NextRequest) {
|
|
70
|
+
console.log('GET /api/users called', {
|
|
71
|
+
searchParams: Object.fromEntries(request.nextUrl.searchParams),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
// Fetch users from database
|
|
76
|
+
const users = await fetchUsers();
|
|
77
|
+
|
|
78
|
+
console.info('Users fetched successfully', {
|
|
79
|
+
count: users.length,
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return NextResponse.json(users);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Failed to fetch users', {
|
|
86
|
+
error: error.message,
|
|
87
|
+
stack: error.stack,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return NextResponse.json(
|
|
91
|
+
{ error: 'Failed to fetch users' },
|
|
92
|
+
{ status: 500 }
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function POST(request: NextRequest) {
|
|
98
|
+
const body = await request.json();
|
|
99
|
+
|
|
100
|
+
console.info('Creating new user', {
|
|
101
|
+
email: body.email,
|
|
102
|
+
name: body.name,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const user = await createUser(body);
|
|
107
|
+
|
|
108
|
+
console.log('User created successfully', {
|
|
109
|
+
userId: user.id,
|
|
110
|
+
email: user.email,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return NextResponse.json(user, { status: 201 });
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('Failed to create user', {
|
|
116
|
+
error: error.message,
|
|
117
|
+
body,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return NextResponse.json(
|
|
121
|
+
{ error: 'Failed to create user' },
|
|
122
|
+
{ status: 500 }
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Server Component with Logging
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// app/dashboard/page.tsx
|
|
132
|
+
export default async function DashboardPage() {
|
|
133
|
+
console.log('Dashboard page rendering started');
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const data = await fetchDashboardData();
|
|
137
|
+
|
|
138
|
+
console.info('Dashboard data loaded', {
|
|
139
|
+
itemCount: data.items.length,
|
|
140
|
+
loadTime: Date.now(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div>
|
|
145
|
+
<h1>Dashboard</h1>
|
|
146
|
+
{/* Render your dashboard */}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('Dashboard data fetch failed', {
|
|
151
|
+
error: error.message,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return <div>Error loading dashboard</div>;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Server Action with Logging
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// app/actions.ts
|
|
163
|
+
'use server';
|
|
164
|
+
|
|
165
|
+
export async function submitForm(formData: FormData) {
|
|
166
|
+
const name = formData.get('name');
|
|
167
|
+
const email = formData.get('email');
|
|
168
|
+
|
|
169
|
+
console.info('Form submission received', {
|
|
170
|
+
name,
|
|
171
|
+
email,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
const result = await saveToDatabase({ name, email });
|
|
176
|
+
|
|
177
|
+
console.log('Form saved successfully', {
|
|
178
|
+
resultId: result.id,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
return { success: true, id: result.id };
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error('Form submission failed', {
|
|
184
|
+
error: error.message,
|
|
185
|
+
formData: { name, email },
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return { success: false, error: error.message };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Middleware with Logging
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// middleware.ts
|
|
197
|
+
import { NextResponse } from 'next/server';
|
|
198
|
+
import type { NextRequest } from 'next/server';
|
|
199
|
+
|
|
200
|
+
export function middleware(request: NextRequest) {
|
|
201
|
+
console.log('Middleware executed', {
|
|
202
|
+
path: request.nextUrl.pathname,
|
|
203
|
+
method: request.method,
|
|
204
|
+
userAgent: request.headers.get('user-agent'),
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Authentication check example
|
|
208
|
+
const token = request.cookies.get('auth-token');
|
|
209
|
+
|
|
210
|
+
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
|
|
211
|
+
console.warn('Unauthorized access attempt', {
|
|
212
|
+
path: request.nextUrl.pathname,
|
|
213
|
+
ip: request.ip,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
return NextResponse.redirect(new URL('/login', request.url));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return NextResponse.next();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const config = {
|
|
223
|
+
matcher: ['/dashboard/:path*', '/api/:path*'],
|
|
224
|
+
};
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Run the Application
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npm run dev
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
You should see in the console:
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
[securenow] OTel SDK started → http://localhost:4318/v1/traces
|
|
237
|
+
[securenow] 📋 Logging: ENABLED → http://localhost:4318/v1/logs
|
|
238
|
+
[securenow] Console instrumentation installed
|
|
239
|
+
SecureNow initialized with logging enabled
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## View Logs in SigNoz
|
|
243
|
+
|
|
244
|
+
1. Open your SigNoz dashboard
|
|
245
|
+
2. Navigate to **Logs** section
|
|
246
|
+
3. Filter by `service.name = my-nextjs-app`
|
|
247
|
+
4. See all your application logs with:
|
|
248
|
+
- Automatic severity levels
|
|
249
|
+
- Structured attributes
|
|
250
|
+
- Trace correlation (when logs happen during traced requests)
|
|
251
|
+
|
|
252
|
+
## Advanced: Direct Logger API
|
|
253
|
+
|
|
254
|
+
For more control, use the logger API directly:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// app/api/advanced/route.ts
|
|
258
|
+
import { getLogger } from 'securenow/tracing';
|
|
259
|
+
|
|
260
|
+
const logger = getLogger('api-handler', '1.0.0');
|
|
261
|
+
|
|
262
|
+
export async function GET() {
|
|
263
|
+
logger?.emit({
|
|
264
|
+
severityNumber: 9,
|
|
265
|
+
severityText: 'INFO',
|
|
266
|
+
body: 'Advanced API called',
|
|
267
|
+
attributes: {
|
|
268
|
+
endpoint: '/api/advanced',
|
|
269
|
+
customField: 'value',
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return Response.json({ message: 'Success' });
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Troubleshooting
|
|
278
|
+
|
|
279
|
+
### Logs not appearing?
|
|
280
|
+
|
|
281
|
+
1. Check `SECURENOW_LOGGING_ENABLED=1` in `.env.local`
|
|
282
|
+
2. Verify `instrumentationHook: true` in `next.config.js`
|
|
283
|
+
3. Ensure `instrumentation.ts` is in the root (not in `app/`)
|
|
284
|
+
4. Enable debug: `OTEL_LOG_LEVEL=debug` in `.env.local`
|
|
285
|
+
5. Restart the dev server: `npm run dev`
|
|
286
|
+
|
|
287
|
+
### Console instrumentation not working?
|
|
288
|
+
|
|
289
|
+
Make sure the import order in `instrumentation.ts`:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// ✅ Correct order
|
|
293
|
+
await import('securenow/register'); // First
|
|
294
|
+
await import('securenow/console-instrumentation'); // Second
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Next Steps
|
|
298
|
+
|
|
299
|
+
- [Complete Logging Guide](../docs/LOGGING-GUIDE.md)
|
|
300
|
+
- [Next.js Complete Guide](../docs/NEXTJS-GUIDE.md)
|
|
301
|
+
- [View Logs in SigNoz](https://signoz.io/docs/logs-management/overview/)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securenow",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces to SigNoz or any OTLP backend",
|
|
3
|
+
"version": "5.0.1",
|
|
4
|
+
"description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces and logs to SigNoz or any OTLP backend",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "register.js",
|
|
7
7
|
"types": "register.d.ts",
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"opentelemetry",
|
|
16
16
|
"otel",
|
|
17
17
|
"tracing",
|
|
18
|
+
"logging",
|
|
19
|
+
"logs",
|
|
18
20
|
"observability",
|
|
19
21
|
"apm",
|
|
20
22
|
"monitoring",
|
|
@@ -42,6 +44,9 @@
|
|
|
42
44
|
"types": "./tracing.d.ts",
|
|
43
45
|
"default": "./tracing.js"
|
|
44
46
|
},
|
|
47
|
+
"./console-instrumentation": {
|
|
48
|
+
"default": "./console-instrumentation.js"
|
|
49
|
+
},
|
|
45
50
|
"./nextjs": {
|
|
46
51
|
"types": "./nextjs.d.ts",
|
|
47
52
|
"default": "./nextjs.js"
|
|
@@ -70,6 +75,7 @@
|
|
|
70
75
|
"register.d.ts",
|
|
71
76
|
"tracing.js",
|
|
72
77
|
"tracing.d.ts",
|
|
78
|
+
"console-instrumentation.js",
|
|
73
79
|
"nextjs.js",
|
|
74
80
|
"nextjs.d.ts",
|
|
75
81
|
"nextjs-auto-capture.js",
|
|
@@ -84,11 +90,15 @@
|
|
|
84
90
|
"web-vite.mjs",
|
|
85
91
|
"examples/",
|
|
86
92
|
"docs/",
|
|
87
|
-
"README.md"
|
|
93
|
+
"README.md",
|
|
94
|
+
"NPM_README.md",
|
|
95
|
+
"CONSUMING-APPS-GUIDE.md"
|
|
88
96
|
],
|
|
89
97
|
"dependencies": {
|
|
90
98
|
"@opentelemetry/api": "1.7.0",
|
|
99
|
+
"@opentelemetry/api-logs": "^0.47.0",
|
|
91
100
|
"@opentelemetry/auto-instrumentations-node": "0.47.0",
|
|
101
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.47.0",
|
|
92
102
|
"@opentelemetry/exporter-trace-otlp-http": "0.47.0",
|
|
93
103
|
"@opentelemetry/instrumentation": "0.47.0",
|
|
94
104
|
"@opentelemetry/instrumentation-document-load": "0.47.0",
|
|
@@ -97,6 +107,7 @@
|
|
|
97
107
|
"@opentelemetry/instrumentation-user-interaction": "0.47.0",
|
|
98
108
|
"@opentelemetry/instrumentation-xml-http-request": "0.47.0",
|
|
99
109
|
"@opentelemetry/resources": "1.20.0",
|
|
110
|
+
"@opentelemetry/sdk-logs": "^0.47.0",
|
|
100
111
|
"@opentelemetry/sdk-node": "0.47.0",
|
|
101
112
|
"@opentelemetry/sdk-trace-web": "1.20.0",
|
|
102
113
|
"@opentelemetry/semantic-conventions": "1.20.0",
|