@vtvlive/interactive-apm 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -123
- package/dist/factories/tracing-provider.factory.d.ts +3 -0
- package/dist/factories/tracing-provider.factory.d.ts.map +1 -1
- package/dist/factories/tracing-provider.factory.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/init/elastic-apm-init.d.ts.map +1 -1
- package/dist/init/elastic-apm-init.js +24 -7
- package/dist/init/opentelemetry-init.d.ts +3 -0
- package/dist/init/opentelemetry-init.d.ts.map +1 -1
- package/dist/init/opentelemetry-init.js +122 -25
- package/dist/providers/elastic-apm.tracing-provider.d.ts.map +1 -1
- package/dist/providers/elastic-apm.tracing-provider.js +45 -10
- package/dist/providers/opentelemetry.tracing-provider.d.ts +7 -0
- package/dist/providers/opentelemetry.tracing-provider.d.ts.map +1 -1
- package/dist/providers/opentelemetry.tracing-provider.js +195 -27
- package/dist/types/otlp-transport.type.d.ts +14 -0
- package/dist/types/otlp-transport.type.d.ts.map +1 -0
- package/dist/types/otlp-transport.type.js +17 -0
- package/dist/utils/debug-exporter-wrapper.d.ts +25 -0
- package/dist/utils/debug-exporter-wrapper.d.ts.map +1 -0
- package/dist/utils/debug-exporter-wrapper.js +207 -0
- package/dist/utils/debug-logger.d.ts +56 -0
- package/dist/utils/debug-logger.d.ts.map +1 -0
- package/dist/utils/debug-logger.js +227 -0
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
- **NestJS Integration**: Ready-to-use module with dependency injection
|
|
9
9
|
- **Standalone Usage**: Works without NestJS for vanilla TypeScript/JavaScript projects
|
|
10
10
|
- **Flexible Configuration**: Configure via environment variables or programmatic options
|
|
11
|
+
- **Debug Mode**: Comprehensive logging for troubleshooting connection issues
|
|
12
|
+
- **OTLP Transport Options**: Support for HTTP, gRPC, and PROTO (protobuf over HTTP) transports
|
|
11
13
|
- **TypeScript Support**: Fully typed with TypeScript
|
|
14
|
+
- **Auto Transaction Naming**: HTTP requests automatically named as "METHOD /route/path"
|
|
12
15
|
|
|
13
16
|
## Installation
|
|
14
17
|
|
|
@@ -18,6 +21,11 @@
|
|
|
18
21
|
npm install @vtvlive/interactive-apm @opentelemetry/api @opentelemetry/exporter-trace-otlp-http @opentelemetry/instrumentation-http @opentelemetry/sdk-node @opentelemetry/resources
|
|
19
22
|
```
|
|
20
23
|
|
|
24
|
+
For gRPC or PROTO transport support:
|
|
25
|
+
```bash
|
|
26
|
+
npm install @opentelemetry/exporter-trace-otlp-grpc @opentelemetry/exporter-trace-otlp-proto
|
|
27
|
+
```
|
|
28
|
+
|
|
21
29
|
### For Elastic APM
|
|
22
30
|
|
|
23
31
|
```bash
|
|
@@ -34,37 +42,91 @@ npm install @nestjs/common @nestjs/config
|
|
|
34
42
|
|
|
35
43
|
## Environment Variables
|
|
36
44
|
|
|
37
|
-
| Variable
|
|
38
|
-
|
|
39
|
-
| `APM_PROVIDER`
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
45
|
+
| Variable | Description | Default |
|
|
46
|
+
| -------------------------------------- | --------------------------------------------------------------------------- | --------------------------------- |
|
|
47
|
+
| `APM_PROVIDER` | Provider selection: `elastic-apm` or `opentelemetry` | `opentelemetry` |
|
|
48
|
+
| `APM_DEBUG` | Enable debug mode with detailed logging (default: `false`) | `false` |
|
|
49
|
+
| `ELASTIC_APM_SERVICE_NAME` | Service name for APM | Required |
|
|
50
|
+
| `ELASTIC_APM_SERVER_URL` | Elastic APM server URL | `http://localhost:8200` |
|
|
51
|
+
| `ELASTIC_APM_SECRET_TOKEN` | Secret token for authentication | Optional |
|
|
52
|
+
| `ELASTIC_APM_ENVIRONMENT` | Deployment environment | `development` |
|
|
53
|
+
| `ELASTIC_OTLP_ENDPOINT` | OTLP endpoint (OpenTelemetry only) | `http://localhost:8200/v1/traces` |
|
|
54
|
+
| `ELASTIC_OTLP_TRANSPORT` | OTLP transport: `http`, `grpc`, or `proto` | `http` |
|
|
55
|
+
| `ELASTIC_OTLP_AUTH_TOKEN` | OTLP-specific auth token (takes precedence over `ELASTIC_APM_SECRET_TOKEN`) | Optional |
|
|
56
|
+
| `ELASTIC_OTLP_HEADERS` | Additional OTLP headers as JSON string | Optional |
|
|
57
|
+
| `ELASTIC_OTLP_ENABLE_CONSOLE_EXPORTER` | Enable console exporter for debugging | `false` |
|
|
58
|
+
|
|
59
|
+
## Debug Mode
|
|
60
|
+
|
|
61
|
+
Enable debug mode to see detailed logs about APM initialization, span creation, and export status:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Enable debug mode
|
|
65
|
+
APM_DEBUG=true
|
|
66
|
+
|
|
67
|
+
# Or in .env file
|
|
68
|
+
APM_DEBUG=true
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Debug mode provides:
|
|
72
|
+
- Initialization details (service name, endpoint, transport type)
|
|
73
|
+
- Span creation and lifecycle events
|
|
74
|
+
- Export success/failure status
|
|
75
|
+
- HTTP request/response details for troubleshooting
|
|
47
76
|
|
|
48
77
|
## Usage
|
|
49
78
|
|
|
50
79
|
### NestJS Integration
|
|
51
80
|
|
|
52
|
-
####
|
|
81
|
+
#### Complete Example with ConfigService
|
|
53
82
|
|
|
54
83
|
```typescript
|
|
55
84
|
// app.module.ts
|
|
85
|
+
import { Module } from '@nestjs/common';
|
|
86
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
56
87
|
import { TracingModule } from '@vtvlive/interactive-apm';
|
|
57
88
|
|
|
58
89
|
@Module({
|
|
59
90
|
imports: [
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
ConfigModule.forRoot({
|
|
92
|
+
isGlobal: true,
|
|
93
|
+
envFilePath: ['.env.local', '.env'],
|
|
94
|
+
}),
|
|
95
|
+
|
|
96
|
+
TracingModule.registerAsync({
|
|
97
|
+
imports: [ConfigModule],
|
|
98
|
+
useFactory: async (configService: ConfigService) => {
|
|
99
|
+
return {
|
|
100
|
+
// Provider selection
|
|
101
|
+
provider: configService.get<string>('APM_PROVIDER', 'opentelemetry'),
|
|
102
|
+
|
|
103
|
+
// Common configuration
|
|
104
|
+
serviceName: configService.get<string>('ELASTIC_APM_SERVICE_NAME', 'my-service'),
|
|
105
|
+
environment: configService.get<string>('ELASTIC_APM_ENVIRONMENT', 'development'),
|
|
106
|
+
|
|
107
|
+
// OpenTelemetry configuration
|
|
108
|
+
otlpEndpoint: configService.get<string>('ELASTIC_OTLP_ENDPOINT', 'http://localhost:8200/v1/traces'),
|
|
109
|
+
otlpTransport: configService.get<string>('ELASTIC_OTLP_TRANSPORT', 'http'), // 'http' | 'grpc' | 'proto'
|
|
110
|
+
otlpAuthToken: configService.get<string>('ELASTIC_OTLP_AUTH_TOKEN'),
|
|
111
|
+
otlpHeaders: configService.get('ELASTIC_OTLP_HEADERS'),
|
|
112
|
+
enableConsoleExporter: configService.get<string>('ELASTIC_OTLP_ENABLE_CONSOLE_EXPORTER', 'false') === 'true',
|
|
113
|
+
|
|
114
|
+
// Elastic APM configuration
|
|
115
|
+
serverUrl: configService.get<string>('ELASTIC_APM_SERVER_URL', 'http://localhost:8200'),
|
|
116
|
+
secretToken: configService.get<string>('ELASTIC_APM_SECRET_TOKEN'),
|
|
117
|
+
|
|
118
|
+
// Debug mode - parse boolean from string env var
|
|
119
|
+
debug: ['1', 'true', 'yes'].includes(configService.get<string>('APM_DEBUG', 'false').toLowerCase()),
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
inject: [ConfigService],
|
|
123
|
+
}),
|
|
62
124
|
],
|
|
63
125
|
})
|
|
64
126
|
export class AppModule {}
|
|
65
127
|
```
|
|
66
128
|
|
|
67
|
-
####
|
|
129
|
+
#### Basic Usage (reads from environment)
|
|
68
130
|
|
|
69
131
|
```typescript
|
|
70
132
|
// app.module.ts
|
|
@@ -72,44 +134,38 @@ import { TracingModule } from '@vtvlive/interactive-apm';
|
|
|
72
134
|
|
|
73
135
|
@Module({
|
|
74
136
|
imports: [
|
|
75
|
-
TracingModule.
|
|
76
|
-
provider: 'opentelemetry',
|
|
77
|
-
serviceName: 'my-service',
|
|
78
|
-
otlpEndpoint: 'http://localhost:8200/v1/traces',
|
|
79
|
-
environment: 'production',
|
|
80
|
-
autoInit: true,
|
|
81
|
-
}),
|
|
137
|
+
TracingModule.registerAsync(),
|
|
82
138
|
// ... other modules
|
|
83
139
|
],
|
|
84
140
|
})
|
|
85
141
|
export class AppModule {}
|
|
86
142
|
```
|
|
87
143
|
|
|
88
|
-
####
|
|
144
|
+
#### In Controllers
|
|
89
145
|
|
|
90
146
|
```typescript
|
|
91
|
-
|
|
92
|
-
import {
|
|
93
|
-
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
147
|
+
import { Controller, Get } from '@nestjs/common';
|
|
148
|
+
import { TracingService } from '@vtvlive/interactive-apm';
|
|
94
149
|
|
|
95
|
-
@
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
150
|
+
@Controller('healthcheck')
|
|
151
|
+
export class HealthController {
|
|
152
|
+
constructor(private readonly tracingService: TracingService) {}
|
|
153
|
+
|
|
154
|
+
@Get('ping')
|
|
155
|
+
ping() {
|
|
156
|
+
return this.tracingService.startSpanWithParent(
|
|
157
|
+
'healthcheck.ping',
|
|
158
|
+
async (span) => {
|
|
159
|
+
span.setAttribute('healthcheck.type', 'liveness');
|
|
160
|
+
return { message: 'pong' };
|
|
161
|
+
},
|
|
162
|
+
{ 'http.method': 'GET', 'http.route': '/healthcheck/ping' }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
110
166
|
```
|
|
111
167
|
|
|
112
|
-
#### In
|
|
168
|
+
#### In Services
|
|
113
169
|
|
|
114
170
|
```typescript
|
|
115
171
|
import { Injectable } from '@nestjs/common';
|
|
@@ -117,20 +173,27 @@ import { TracingService } from '@vtvlive/interactive-apm';
|
|
|
117
173
|
|
|
118
174
|
@Injectable()
|
|
119
175
|
export class UserService {
|
|
120
|
-
constructor(
|
|
176
|
+
constructor(
|
|
177
|
+
private readonly tracingService: TracingService,
|
|
178
|
+
private readonly userRepository: UserRepository
|
|
179
|
+
) {}
|
|
121
180
|
|
|
122
181
|
async findById(id: string) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
182
|
+
return this.tracingService.startSpanWithParent(
|
|
183
|
+
'user.findById',
|
|
184
|
+
async (span) => {
|
|
185
|
+
span.setAttribute('userId', id);
|
|
186
|
+
|
|
187
|
+
const user = await this.userRepository.findById(id);
|
|
188
|
+
if (!user) {
|
|
189
|
+
throw new NotFoundException(`User ${id} not found`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
span.setAttribute('user.exists', 'true');
|
|
193
|
+
return user;
|
|
194
|
+
},
|
|
195
|
+
{ 'operation.type': 'read' }
|
|
196
|
+
);
|
|
134
197
|
}
|
|
135
198
|
|
|
136
199
|
async create(data: CreateUserDto) {
|
|
@@ -138,10 +201,23 @@ export class UserService {
|
|
|
138
201
|
'user.create',
|
|
139
202
|
async (span) => {
|
|
140
203
|
span.setAttribute('user.email', data.email);
|
|
141
|
-
|
|
204
|
+
|
|
205
|
+
// This nested call creates a child span
|
|
206
|
+
const hashedPassword = await this.tracingService.startSpanWithParent(
|
|
207
|
+
'user.hashPassword',
|
|
208
|
+
async () => await bcrypt.hash(data.password, 10),
|
|
209
|
+
{ 'operation.type': 'crypto' }
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const user = await this.userRepository.create({
|
|
213
|
+
...data,
|
|
214
|
+
password: hashedPassword,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
span.setAttribute('user.created', 'true');
|
|
142
218
|
return user;
|
|
143
219
|
},
|
|
144
|
-
{
|
|
220
|
+
{ 'operation.type': 'write' }
|
|
145
221
|
);
|
|
146
222
|
}
|
|
147
223
|
}
|
|
@@ -152,54 +228,36 @@ export class UserService {
|
|
|
152
228
|
#### OpenTelemetry
|
|
153
229
|
|
|
154
230
|
```typescript
|
|
155
|
-
import { initOpenTelemetry
|
|
156
|
-
import { SpanKind } from '@opentelemetry/api';
|
|
231
|
+
import { initOpenTelemetry } from '@vtvlive/interactive-apm';
|
|
157
232
|
|
|
158
|
-
// Initialize at the top of your application
|
|
233
|
+
// Initialize at the top of your application (before any imports)
|
|
159
234
|
await initOpenTelemetry({
|
|
160
235
|
serviceName: 'my-service',
|
|
161
236
|
otlpEndpoint: 'http://localhost:8200/v1/traces',
|
|
162
237
|
environment: 'production',
|
|
238
|
+
otlpTransport: 'proto', // 'http' | 'grpc' | 'proto'
|
|
239
|
+
enableConsoleExporter: false,
|
|
163
240
|
});
|
|
164
241
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Your code here
|
|
169
|
-
TracingHelper.setAttribute('result', 'success');
|
|
170
|
-
} catch (error) {
|
|
171
|
-
TracingHelper.captureError(error);
|
|
172
|
-
throw error;
|
|
173
|
-
} finally {
|
|
174
|
-
TracingHelper.endSpan(span);
|
|
175
|
-
}
|
|
242
|
+
// Your application code
|
|
243
|
+
import express from 'express';
|
|
244
|
+
const app = express();
|
|
176
245
|
```
|
|
177
246
|
|
|
178
247
|
#### Elastic APM
|
|
179
248
|
|
|
180
249
|
```typescript
|
|
181
|
-
import { initElasticApm
|
|
250
|
+
import { initElasticApm } from '@vtvlive/interactive-apm';
|
|
182
251
|
|
|
183
252
|
// Initialize at the top of your application
|
|
184
253
|
initElasticApm({
|
|
185
254
|
serviceName: 'my-service',
|
|
186
255
|
serverUrl: 'http://localhost:8200',
|
|
187
256
|
environment: 'production',
|
|
257
|
+
secretToken: 'your-secret-token',
|
|
188
258
|
});
|
|
189
259
|
|
|
190
|
-
//
|
|
191
|
-
const provider = createTracingProvider({ provider: 'elastic-apm' });
|
|
192
|
-
const tracingService = new TracingService(provider);
|
|
193
|
-
|
|
194
|
-
const span = tracingService.startSpan('operation', { key: 'value' });
|
|
195
|
-
try {
|
|
196
|
-
// Your code here
|
|
197
|
-
} catch (error) {
|
|
198
|
-
tracingService.captureError(error);
|
|
199
|
-
throw error;
|
|
200
|
-
} finally {
|
|
201
|
-
span.end();
|
|
202
|
-
}
|
|
260
|
+
// Your application code
|
|
203
261
|
```
|
|
204
262
|
|
|
205
263
|
## API Reference
|
|
@@ -208,41 +266,27 @@ try {
|
|
|
208
266
|
|
|
209
267
|
NestJS module for APM integration.
|
|
210
268
|
|
|
211
|
-
| Method
|
|
212
|
-
|
|
213
|
-
| `register(options)`
|
|
214
|
-
| `registerAsync(options)` | Register module with asynchronous options |
|
|
269
|
+
| Method | Description |
|
|
270
|
+
| ------------------------ | -------------------------------------------------------------- |
|
|
271
|
+
| `register(options)` | Register module with synchronous options |
|
|
272
|
+
| `registerAsync(options)` | Register module with asynchronous options (with ConfigService) |
|
|
215
273
|
|
|
216
274
|
### TracingService
|
|
217
275
|
|
|
218
276
|
Service for tracing operations.
|
|
219
277
|
|
|
220
|
-
| Method
|
|
221
|
-
|
|
222
|
-
| `startSpan(name, attributes?, spanKind?)`
|
|
223
|
-
| `startSpanWithParent(name, fn, attributes?)` | Execute function with tracing
|
|
224
|
-
| `captureError(error)`
|
|
225
|
-
| `setAttribute(key, value)`
|
|
226
|
-
| `endSpan(span?)`
|
|
227
|
-
| `shutdown()`
|
|
228
|
-
|
|
229
|
-
### TracingHelper
|
|
230
|
-
|
|
231
|
-
Static utility class for OpenTelemetry.
|
|
232
|
-
|
|
233
|
-
| Method | Description |
|
|
234
|
-
|--------|-------------|
|
|
235
|
-
| `startSpan(name, attributes?, spanKind?)` | Start a new span |
|
|
236
|
-
| `startSpanWithParent(name, fn, attributes?)` | Execute function with tracing context |
|
|
237
|
-
| `captureError(error)` | Capture error to active span |
|
|
238
|
-
| `setAttribute(key, value)` | Set attribute on active span |
|
|
239
|
-
| `endSpan(span?)` | End a span |
|
|
240
|
-
| `getActiveSpan()` | Get the active span |
|
|
241
|
-
| `getTraceId()` | Get the current trace ID |
|
|
278
|
+
| Method | Description |
|
|
279
|
+
| -------------------------------------------- | ----------------------------------------------------- |
|
|
280
|
+
| `startSpan(name, attributes?, spanKind?)` | Start a new span (must call `span.end()` manually) |
|
|
281
|
+
| `startSpanWithParent(name, fn, attributes?)` | Execute function with automatic tracing (recommended) |
|
|
282
|
+
| `captureError(error)` | Capture error to active span |
|
|
283
|
+
| `setAttribute(key, value)` | Set attribute on active span |
|
|
284
|
+
| `endSpan(span?)` | End a span manually |
|
|
285
|
+
| `shutdown()` | Flush and shutdown provider |
|
|
242
286
|
|
|
243
287
|
### SpanKind
|
|
244
288
|
|
|
245
|
-
Types of spans:
|
|
289
|
+
Types of spans (used with `startSpan`):
|
|
246
290
|
|
|
247
291
|
- `INTERNAL`: Internal operation
|
|
248
292
|
- `SERVER`: Server-side request handler (API endpoints)
|
|
@@ -250,24 +294,58 @@ Types of spans:
|
|
|
250
294
|
- `PRODUCER`: Message producer
|
|
251
295
|
- `CONSUMER`: Message consumer
|
|
252
296
|
|
|
253
|
-
|
|
297
|
+
### OtlpTransport
|
|
254
298
|
|
|
255
|
-
|
|
299
|
+
Transport options for OpenTelemetry OTLP exporter:
|
|
256
300
|
|
|
257
|
-
|
|
301
|
+
- `HTTP`: JSON over HTTP (default)
|
|
302
|
+
- `GRPC`: gRPC with protobuf
|
|
303
|
+
- `PROTO`: Protobuf over HTTP (most efficient)
|
|
258
304
|
|
|
259
|
-
|
|
305
|
+
## Transaction Naming
|
|
260
306
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
307
|
+
HTTP transactions are automatically named in the format `METHOD /route/path`:
|
|
308
|
+
|
|
309
|
+
- Request to `GET /api/healthcheck/ping` → Transaction: `GET /api/healthcheck/ping`
|
|
310
|
+
- Request to `POST /api/users` → Transaction: `POST /api/users`
|
|
311
|
+
|
|
312
|
+
This applies to both OpenTelemetry and Elastic APM providers.
|
|
313
|
+
|
|
314
|
+
## Provider Comparison
|
|
264
315
|
|
|
265
|
-
|
|
316
|
+
| Feature | OpenTelemetry | Elastic APM |
|
|
317
|
+
| -------------------- | ---------------------------- | ---------------- |
|
|
318
|
+
| Transport Options | HTTP, gRPC, PROTO | HTTP/HTTPS |
|
|
319
|
+
| Auto Instrumentation | HTTP, Express (configurable) | Built-in |
|
|
320
|
+
| Debug Logging | Comprehensive | Comprehensive |
|
|
321
|
+
| Transaction Naming | Auto + Custom | Auto + Custom |
|
|
322
|
+
| Standard | W3C Trace Context | Elastic APM spec |
|
|
266
323
|
|
|
267
|
-
|
|
324
|
+
## Troubleshooting
|
|
325
|
+
|
|
326
|
+
### No traces appearing in APM
|
|
327
|
+
|
|
328
|
+
1. Check if `APM_DEBUG=true` is set to see detailed logs
|
|
329
|
+
2. Verify endpoint URL is correct
|
|
330
|
+
3. Check network connectivity to APM server
|
|
331
|
+
4. Verify authentication token
|
|
332
|
+
|
|
333
|
+
### Using npm link for local development
|
|
268
334
|
|
|
269
335
|
```bash
|
|
270
|
-
|
|
336
|
+
# In the package directory
|
|
337
|
+
cd /path/to/interactive-apm
|
|
338
|
+
npm link
|
|
339
|
+
|
|
340
|
+
# In your project directory
|
|
341
|
+
cd /path/to/your-project
|
|
342
|
+
npm link @vtvlive/interactive-apm
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Note: After making changes to the package, rebuild it:
|
|
346
|
+
```bash
|
|
347
|
+
cd /path/to/interactive-apm
|
|
348
|
+
npm run build
|
|
271
349
|
```
|
|
272
350
|
|
|
273
351
|
## Testing
|
|
@@ -305,8 +383,6 @@ npm test
|
|
|
305
383
|
npm run clean
|
|
306
384
|
```
|
|
307
385
|
|
|
308
|
-
**For detailed deployment instructions (build, publish, install from private registry), see [DEPLOYMENT.md](DEPLOYMENT.md)**
|
|
309
|
-
|
|
310
386
|
## License
|
|
311
387
|
|
|
312
388
|
MIT
|
|
@@ -317,4 +393,6 @@ VTVLive
|
|
|
317
393
|
|
|
318
394
|
---
|
|
319
395
|
|
|
320
|
-
For more information
|
|
396
|
+
For more information:
|
|
397
|
+
- [Elastic APM documentation](https://www.elastic.co/guide/en/apm/get-started/current/index.html)
|
|
398
|
+
- [OpenTelemetry documentation](https://opentelemetry.io/docs/instrumentation/js/)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ITracingProvider } from '../interfaces/tracing-provider.interface';
|
|
2
2
|
import { ApmProvider } from '../types/apm-provider.type';
|
|
3
|
+
import { OtlpTransport } from '../types/otlp-transport.type';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration options for creating a tracing provider
|
|
5
6
|
*/
|
|
@@ -20,6 +21,8 @@ export interface TracingProviderConfig {
|
|
|
20
21
|
otlpAuthToken?: string;
|
|
21
22
|
/** OTLP headers as a record (key-value pairs). If provided, merges with Authorization header when token is set. */
|
|
22
23
|
otlpHeaders?: Record<string, string>;
|
|
24
|
+
/** OTLP transport type: 'http' or 'grpc' (default: 'http') */
|
|
25
|
+
otlpTransport?: OtlpTransport | string;
|
|
23
26
|
/** Enable console exporter for debugging (default: false) */
|
|
24
27
|
enableConsoleExporter?: boolean;
|
|
25
28
|
/** Service version */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing-provider.factory.d.ts","sourceRoot":"","sources":["../../src/factories/tracing-provider.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"tracing-provider.factory.d.ts","sourceRoot":"","sources":["../../src/factories/tracing-provider.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mHAAmH;IACnH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IACvC,6DAA6D;IAC7D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,GAAE,qBAA0B,GAAG,gBAAgB,CAQ1F;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB;;iCAEJ,GAAG;;CAiCjC,CAAC"}
|
|
@@ -86,6 +86,7 @@ exports.TracingProviderFactory = {
|
|
|
86
86
|
otlpEndpoint: get('ELASTIC_OTLP_ENDPOINT', 'http://localhost:8200/v1/traces'),
|
|
87
87
|
otlpAuthToken,
|
|
88
88
|
otlpHeaders: Object.keys(headers).length > 0 ? headers : undefined,
|
|
89
|
+
otlpTransport: get('ELASTIC_OTLP_TRANSPORT', 'http'),
|
|
89
90
|
enableConsoleExporter: get('ELASTIC_OTLP_ENABLE_CONSOLE_EXPORTER', 'false') === 'true',
|
|
90
91
|
});
|
|
91
92
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { TracingService } from './services/tracing.service';
|
|
|
3
3
|
export { TracingHelper } from './utils/tracing.helper';
|
|
4
4
|
export { ITracingProvider } from './interfaces/tracing-provider.interface';
|
|
5
5
|
export { ApmProvider, SpanKind } from './types/apm-provider.type';
|
|
6
|
+
export { OtlpTransport } from './types/otlp-transport.type';
|
|
6
7
|
export { ElasticApmTracingProvider } from './providers/elastic-apm.tracing-provider';
|
|
7
8
|
export { OpenTelemetryTracingProvider } from './providers/opentelemetry.tracing-provider';
|
|
8
9
|
export { createTracingProvider, TracingProviderFactory, TRACING_PROVIDER_TOKEN, TracingProviderConfig } from './factories/tracing-provider.factory';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAG1G,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAG1G,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,4CAA4C,CAAC;AAG1F,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAGpJ,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.shouldUseOpenTelemetry = exports.initOpenTelemetry = exports.shouldUseElasticApm = exports.getElasticApmAgent = exports.isElasticApmStarted = exports.initElasticApm = exports.TRACING_PROVIDER_TOKEN = exports.TracingProviderFactory = exports.createTracingProvider = exports.OpenTelemetryTracingProvider = exports.ElasticApmTracingProvider = exports.SpanKind = exports.ApmProvider = exports.TracingHelper = exports.TracingService = exports.TracingModule = void 0;
|
|
3
|
+
exports.shouldUseOpenTelemetry = exports.initOpenTelemetry = exports.shouldUseElasticApm = exports.getElasticApmAgent = exports.isElasticApmStarted = exports.initElasticApm = exports.TRACING_PROVIDER_TOKEN = exports.TracingProviderFactory = exports.createTracingProvider = exports.OpenTelemetryTracingProvider = exports.ElasticApmTracingProvider = exports.OtlpTransport = exports.SpanKind = exports.ApmProvider = exports.TracingHelper = exports.TracingService = exports.TracingModule = void 0;
|
|
4
4
|
// Core exports - NestJS integration
|
|
5
5
|
var tracing_module_1 = require("./modules/tracing.module");
|
|
6
6
|
Object.defineProperty(exports, "TracingModule", { enumerable: true, get: function () { return tracing_module_1.TracingModule; } });
|
|
@@ -14,6 +14,8 @@ Object.defineProperty(exports, "TracingHelper", { enumerable: true, get: functio
|
|
|
14
14
|
var apm_provider_type_1 = require("./types/apm-provider.type");
|
|
15
15
|
Object.defineProperty(exports, "ApmProvider", { enumerable: true, get: function () { return apm_provider_type_1.ApmProvider; } });
|
|
16
16
|
Object.defineProperty(exports, "SpanKind", { enumerable: true, get: function () { return apm_provider_type_1.SpanKind; } });
|
|
17
|
+
var otlp_transport_type_1 = require("./types/otlp-transport.type");
|
|
18
|
+
Object.defineProperty(exports, "OtlpTransport", { enumerable: true, get: function () { return otlp_transport_type_1.OtlpTransport; } });
|
|
17
19
|
// Providers - for direct usage
|
|
18
20
|
var elastic_apm_tracing_provider_1 = require("./providers/elastic-apm.tracing-provider");
|
|
19
21
|
Object.defineProperty(exports, "ElasticApmTracingProvider", { enumerable: true, get: function () { return elastic_apm_tracing_provider_1.ElasticApmTracingProvider; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elastic-apm-init.d.ts","sourceRoot":"","sources":["../../src/init/elastic-apm-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"elastic-apm-init.d.ts","sourceRoot":"","sources":["../../src/init/elastic-apm-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,WAAW,qBAAqB;IACpC,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;CAClE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAG7C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,GAAG,CAyCvE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAQ7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,GAAG,CAWxC"}
|
|
@@ -21,6 +21,7 @@ exports.initElasticApm = initElasticApm;
|
|
|
21
21
|
exports.isElasticApmStarted = isElasticApmStarted;
|
|
22
22
|
exports.getElasticApmAgent = getElasticApmAgent;
|
|
23
23
|
const apm_provider_type_1 = require("../types/apm-provider.type");
|
|
24
|
+
const debug_logger_1 = require("../utils/debug-logger");
|
|
24
25
|
/**
|
|
25
26
|
* Check if APM should use Elastic APM provider based on configuration
|
|
26
27
|
* @returns true if Elastic APM should be used
|
|
@@ -42,17 +43,33 @@ function initElasticApm(options = {}) {
|
|
|
42
43
|
if (apm.isStarted()) {
|
|
43
44
|
return apm;
|
|
44
45
|
}
|
|
46
|
+
const serviceName = options.serviceName || process.env.ELASTIC_APM_SERVICE_NAME || 'interactive-backend';
|
|
47
|
+
const serverUrl = options.serverUrl || process.env.ELASTIC_APM_SERVER_URL || 'http://localhost:8200';
|
|
48
|
+
const secretToken = options.secretToken || process.env.ELASTIC_APM_SECRET_TOKEN;
|
|
49
|
+
const serviceVersion = options.serviceVersion || process.env.npm_package_version || '1.0.0';
|
|
50
|
+
const environment = options.environment || process.env.ELASTIC_APM_ENVIRONMENT || 'development';
|
|
51
|
+
// Log initialization details when debug mode is on
|
|
52
|
+
(0, debug_logger_1.logInitialization)('ElasticAPM', {
|
|
53
|
+
serviceName,
|
|
54
|
+
serverUrl,
|
|
55
|
+
hasSecretToken: !!secretToken,
|
|
56
|
+
serviceVersion,
|
|
57
|
+
environment,
|
|
58
|
+
logLevel: options.logLevel || 'error',
|
|
59
|
+
});
|
|
45
60
|
// Start the agent
|
|
46
61
|
const agent = apm.start({
|
|
47
|
-
serviceName
|
|
48
|
-
serverUrl
|
|
49
|
-
secretToken
|
|
50
|
-
serviceVersion
|
|
51
|
-
environment
|
|
62
|
+
serviceName,
|
|
63
|
+
serverUrl,
|
|
64
|
+
secretToken,
|
|
65
|
+
serviceVersion,
|
|
66
|
+
environment,
|
|
52
67
|
logLevel: options.logLevel || 'error',
|
|
53
68
|
});
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
if ((0, debug_logger_1.isDebugEnabled)()) {
|
|
70
|
+
(0, debug_logger_1.infoLog)(`[ElasticAPM] Service: ${agent.getServiceName()}, Environment: ${agent.conf.environment}`);
|
|
71
|
+
(0, debug_logger_1.infoLog)('[ElasticAPM] Initialized');
|
|
72
|
+
}
|
|
56
73
|
return agent;
|
|
57
74
|
}
|
|
58
75
|
/**
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* environment: 'production',
|
|
15
15
|
* });
|
|
16
16
|
*/
|
|
17
|
+
import { OtlpTransport } from '../types/otlp-transport.type';
|
|
17
18
|
export interface OpenTelemetryInitOptions {
|
|
18
19
|
/** Service name for APM */
|
|
19
20
|
serviceName?: string;
|
|
@@ -35,6 +36,8 @@ export interface OpenTelemetryInitOptions {
|
|
|
35
36
|
enableHttpInstrumentation?: boolean;
|
|
36
37
|
/** Enable Express instrumentation */
|
|
37
38
|
enableExpressInstrumentation?: boolean;
|
|
39
|
+
/** OTLP transport type: 'http' or 'grpc' (default: 'http') */
|
|
40
|
+
otlpTransport?: OtlpTransport | string;
|
|
38
41
|
}
|
|
39
42
|
/**
|
|
40
43
|
* Check if APM should use OpenTelemetry provider based on configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opentelemetry-init.d.ts","sourceRoot":"","sources":["../../src/init/opentelemetry-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"opentelemetry-init.d.ts","sourceRoot":"","sources":["../../src/init/opentelemetry-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AA0C7D,MAAM,WAAW,wBAAwB;IACvC,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mHAAmH;IACnH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kCAAkC;IAClC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,qCAAqC;IACrC,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD;AAwCD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,GAAG,CAAC,CA2I5F"}
|