@qlibs/apm 0.3.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -10
- package/dist/apm.config.d.ts +2 -1
- package/dist/apm.config.js +1 -0
- package/dist/http/apm-logging.interceptor.js +1 -1
- package/dist/logger/apm-logger.service.d.ts +1 -0
- package/dist/logger/apm-logger.service.js +33 -0
- package/dist/logger/winston.instance.js +11 -5
- package/dist/tracing.js +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@ What gets traced automatically (no business-logic changes required):
|
|
|
19
19
|
|
|
20
20
|
Metrics (RED dashboards — latency, error rate, throughput) are intentionally
|
|
21
21
|
**not** exported separately: SigNoz and Elastic APM both derive these from
|
|
22
|
-
trace data automatically.
|
|
22
|
+
trace data automatically. The OTel SDK therefore ships traces only
|
|
23
|
+
(`OTEL_METRICS_EXPORTER` and `OTEL_LOGS_EXPORTER` default to `none`). If you need custom business metrics later, add an
|
|
23
24
|
`@opentelemetry/sdk-metrics` + OTLP metrics exporter next to `tracing.ts` —
|
|
24
25
|
the config/resource plumbing here already gives you everything needed to
|
|
25
26
|
wire that in.
|
|
@@ -78,12 +79,82 @@ dependency of this package.
|
|
|
78
79
|
| `OTEL_EXPORTER_OTLP_HEADERS` | _(empty)_ | Comma-separated `key=value` pairs, e.g. ingestion keys / auth tokens. |
|
|
79
80
|
| `LOG_LEVEL` | `info` (`debug` when env is `local`) | Winston log level (`error`, `warn`, `info`, `http`, `verbose`, `debug`). At `info`, Nest `verbose`/`debug` logs are dropped — set `verbose` or `debug` to see them. HTTP access logs and Nest `fatal` (logged as `error` with `fatal: true`) are always visible at `info`. On the console, `error`/`warn` go to stderr and everything else to stdout. |
|
|
80
81
|
| `APM_LOG_FORMAT` | `pretty` for `local`/`development`, `json` otherwise | `pretty` = colorized console; `json` = structured stdout. |
|
|
81
|
-
| `APM_LOG_TRANSPORT` | `stdout` | Comma list of `stdout`, `elasticsearch`, `otlp`. Multiple can be active at once. |
|
|
82
|
+
| `APM_LOG_TRANSPORT` | `stdout` | Comma list of `stdout`, `elasticsearch`, `otlp`. Multiple can be active at once. `none` = the APM writes no log lines of its own (no access log, no extra error line); `ApmLoggerService` then just forwards to Nest's default console logger, so console output appears once, in Nest's format. Traces are unaffected. |
|
|
82
83
|
| `ELASTICSEARCH_NODE` / `_USERNAME` / `_PASSWORD` / `_INDEX` | _(empty)_ | Only used when `APM_LOG_TRANSPORT` includes `elasticsearch`. While ES is unreachable at most 1000 log lines are buffered (the rest are dropped) and each is retried 5 times. Shipping via stdout + Filebeat/Fluent Bit is still preferred in production. |
|
|
83
84
|
| `APM_HTTP_IGNORE_PATHS` | `/health,/favicon.ico` | Comma list of path prefixes excluded from the HTTP access log and from tracing. |
|
|
84
85
|
| `OTEL_NODE_ENABLED_INSTRUMENTATIONS` | `http,undici,express,nestjs-core,pg,ioredis,redis,amqplib` | Which auto-instrumentations to load (names without the `@opentelemetry/instrumentation-` prefix). Add e.g. `mongodb`, `kafkajs` if your app needs them. |
|
|
85
86
|
| `OTEL_TRACES_SAMPLER` / `OTEL_TRACES_SAMPLER_ARG` | `parentbased_always_on` | Standard OTel sampling. For high-traffic services use `parentbased_traceidratio` with e.g. `0.1` (10%). |
|
|
86
87
|
|
|
88
|
+
## Recommended setup
|
|
89
|
+
|
|
90
|
+
### Production
|
|
91
|
+
|
|
92
|
+
```env
|
|
93
|
+
NODE_ENV=production
|
|
94
|
+
APM_SERVICE_NAME=my-app-api
|
|
95
|
+
APM_SERVICE_VERSION=1.4.2
|
|
96
|
+
LOG_LEVEL=warn
|
|
97
|
+
APM_LOG_TRANSPORT=none
|
|
98
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
99
|
+
# Optional, for high-traffic services (> ~50 req/s):
|
|
100
|
+
# OTEL_TRACES_SAMPLER=parentbased_traceidratio
|
|
101
|
+
# OTEL_TRACES_SAMPLER_ARG=0.2
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Destination | What you get |
|
|
105
|
+
|---|---|
|
|
106
|
+
| **pm2 / docker logs** | Only `ERROR`, `WARN` and `FATAL`, in Nest's own format (`[Nest] 123 - ... ERROR [OrderService] ...`), each line **once**. Errors/fatal go to stderr (`pm2 logs --err`), warnings to stdout. No per-request access log, no `log`/`verbose`/`debug`. Plus one startup line: `[apm] tracing enabled -> ...`. |
|
|
107
|
+
| **SigNoz — Traces** | Every request (except `/health`, `/favicon.ico`) including its Postgres, Redis, RabbitMQ and outbound HTTP calls. Failed requests are marked as errors with message and stack trace. Latency / error-rate / throughput dashboards are derived from these traces. |
|
|
108
|
+
| **SigNoz — Logs** | Nothing is sent. |
|
|
109
|
+
| **SigNoz — Metrics** | Nothing is sent. |
|
|
110
|
+
| **Deploy / restart** | Pending traces are flushed (max 5s), then Nest's graceful shutdown runs normally. |
|
|
111
|
+
|
|
112
|
+
In short: the terminal is for warnings and errors only; per-request detail
|
|
113
|
+
lives in SigNoz.
|
|
114
|
+
|
|
115
|
+
Requirements in the app:
|
|
116
|
+
- `import '@qlibs/apm/tracing'` as the first line of `main.ts`.
|
|
117
|
+
- `recordException()` or `ApmExceptionFilter` in place, so errors are marked
|
|
118
|
+
on the trace.
|
|
119
|
+
- If `main.ts` does **not** call `app.useLogger(app.get(ApmLoggerService))`,
|
|
120
|
+
`LOG_LEVEL` does not filter Nest's output — use
|
|
121
|
+
`NestFactory.create(AppModule, { logger: ['fatal', 'error', 'warn'] })`
|
|
122
|
+
instead.
|
|
123
|
+
|
|
124
|
+
On the server, enable log rotation as a safety net (`pm2 install
|
|
125
|
+
pm2-logrotate`, or `max-size` / `max-file` for Docker's `json-file` driver).
|
|
126
|
+
|
|
127
|
+
### Development (shared dev / staging server)
|
|
128
|
+
|
|
129
|
+
```env
|
|
130
|
+
NODE_ENV=development
|
|
131
|
+
APM_SERVICE_NAME=my-app-api
|
|
132
|
+
LOG_LEVEL=debug
|
|
133
|
+
APM_LOG_TRANSPORT=stdout
|
|
134
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| Destination | What you get |
|
|
138
|
+
|---|---|
|
|
139
|
+
| **pm2 / docker logs** | **All levels** (error … debug), colorized and human-readable, written by the APM — e.g. `10:21:05 info [HTTP] GET /api/orders 200 (trace=4bf92f...)`. Includes a **per-request access log** with duration and `trace_id`, so any log line can be looked up as a trace in SigNoz. Nest's own logs go through the same logger, so nothing is printed twice. |
|
|
140
|
+
| **SigNoz — Traces** | Every request, kept apart from production by `deployment.environment=development` (filter by environment in SigNoz). |
|
|
141
|
+
| **SigNoz — Logs / Metrics** | Nothing is sent. |
|
|
142
|
+
|
|
143
|
+
**Developer laptop:** use `NODE_ENV=local` and drop `LOG_LEVEL` (defaults to
|
|
144
|
+
`debug`) and `OTEL_EXPORTER_OTLP_ENDPOINT`. Logs stay colorized in the
|
|
145
|
+
terminal, tracing is off, nothing is sent anywhere.
|
|
146
|
+
|
|
147
|
+
### At a glance
|
|
148
|
+
|
|
149
|
+
| | Production | Development |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Who prints to the terminal | Nest (APM is silent) | APM |
|
|
152
|
+
| Levels shown | warn, error, fatal | all |
|
|
153
|
+
| Per-request access log | ❌ (use SigNoz) | ✅ |
|
|
154
|
+
| `trace_id` on log lines | ❌ | ✅ |
|
|
155
|
+
| Traces to SigNoz | ✅ | ✅ |
|
|
156
|
+
| Logs / metrics to SigNoz | ❌ | ❌ |
|
|
157
|
+
|
|
87
158
|
## Example configurations
|
|
88
159
|
|
|
89
160
|
`LOG_LEVEL` is a threshold: it keeps that level and everything more severe
|
|
@@ -104,7 +175,22 @@ Errors are still marked on the trace span by `recordException()` regardless of
|
|
|
104
175
|
`LOG_LEVEL`. After changing env vars, restart the app (pm2:
|
|
105
176
|
`pm2 restart <app> --update-env`).
|
|
106
177
|
|
|
107
|
-
**1.
|
|
178
|
+
**1. Traces only — Nest's own console logs, no duplicate APM log lines**
|
|
179
|
+
```env
|
|
180
|
+
NODE_ENV=production
|
|
181
|
+
APM_SERVICE_NAME=my-app-api
|
|
182
|
+
LOG_LEVEL=warn
|
|
183
|
+
APM_LOG_TRANSPORT=none
|
|
184
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
185
|
+
```
|
|
186
|
+
pm2/docker show only Nest's normal `[Nest] ... ERROR [Context] ...` lines, each
|
|
187
|
+
once. Errors still appear on the trace in SigNoz (status ERROR + exception
|
|
188
|
+
event) via `recordException()`. `LOG_LEVEL` keeps working if `main.ts` calls
|
|
189
|
+
`app.useLogger(app.get(ApmLoggerService))`; if it doesn't, filter Nest's output
|
|
190
|
+
with `NestFactory.create(AppModule, { logger: ['fatal', 'error', 'warn'] })`
|
|
191
|
+
instead. Trade-off: console lines carry no `trace_id`.
|
|
192
|
+
|
|
193
|
+
**2. Production, minimal — only warn + error in pm2/docker, traces to SigNoz**
|
|
108
194
|
```env
|
|
109
195
|
NODE_ENV=production
|
|
110
196
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -115,7 +201,7 @@ OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
|
115
201
|
Note: at `warn` the HTTP access log (`GET /api/... 200`, level `info`) is
|
|
116
202
|
dropped too.
|
|
117
203
|
|
|
118
|
-
**
|
|
204
|
+
**3. Production, standard — info + access log in pm2/docker, logs and traces to SigNoz**
|
|
119
205
|
```env
|
|
120
206
|
NODE_ENV=production
|
|
121
207
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -124,7 +210,7 @@ APM_LOG_TRANSPORT=stdout,otlp
|
|
|
124
210
|
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
125
211
|
```
|
|
126
212
|
|
|
127
|
-
**
|
|
213
|
+
**4. Production, high traffic — trace only 10% of requests**
|
|
128
214
|
```env
|
|
129
215
|
NODE_ENV=production
|
|
130
216
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -135,7 +221,7 @@ OTEL_TRACES_SAMPLER=parentbased_traceidratio
|
|
|
135
221
|
OTEL_TRACES_SAMPLER_ARG=0.1
|
|
136
222
|
```
|
|
137
223
|
|
|
138
|
-
**
|
|
224
|
+
**5. Staging, investigating a bug — everything**
|
|
139
225
|
```env
|
|
140
226
|
NODE_ENV=staging
|
|
141
227
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -144,7 +230,7 @@ APM_LOG_TRANSPORT=stdout,otlp
|
|
|
144
230
|
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4318
|
|
145
231
|
```
|
|
146
232
|
|
|
147
|
-
**
|
|
233
|
+
**6. Local development, no SigNoz**
|
|
148
234
|
```env
|
|
149
235
|
NODE_ENV=local
|
|
150
236
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -152,7 +238,7 @@ APM_SERVICE_NAME=my-app-api
|
|
|
152
238
|
# OTEL_EXPORTER_OTLP_ENDPOINT left empty -> tracing off
|
|
153
239
|
```
|
|
154
240
|
|
|
155
|
-
**
|
|
241
|
+
**7. Logs to pm2/docker only, no tracing at all**
|
|
156
242
|
```env
|
|
157
243
|
NODE_ENV=production
|
|
158
244
|
APM_SERVICE_NAME=my-app-api
|
|
@@ -161,13 +247,13 @@ APM_LOG_TRANSPORT=stdout
|
|
|
161
247
|
# OTEL_EXPORTER_OTLP_ENDPOINT not set -> nothing is sent to SigNoz
|
|
162
248
|
```
|
|
163
249
|
|
|
164
|
-
**
|
|
250
|
+
**8. Collector listening on gRPC (port 4317)**
|
|
165
251
|
```env
|
|
166
252
|
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4317
|
|
167
253
|
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
|
168
254
|
```
|
|
169
255
|
|
|
170
|
-
**
|
|
256
|
+
**9. Logs to Elasticsearch / Kibana**
|
|
171
257
|
```env
|
|
172
258
|
NODE_ENV=production
|
|
173
259
|
APM_SERVICE_NAME=my-app-api
|
package/dist/apm.config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type LogFormat = 'pretty' | 'json';
|
|
2
|
-
export type LogTransportKind = 'stdout' | 'elasticsearch' | 'otlp';
|
|
2
|
+
export type LogTransportKind = 'stdout' | 'elasticsearch' | 'otlp' | 'none';
|
|
3
3
|
export type OtlpProtocol = 'http/protobuf' | 'grpc';
|
|
4
4
|
export interface ApmConfig {
|
|
5
5
|
enabled: boolean;
|
|
@@ -13,6 +13,7 @@ export interface ApmConfig {
|
|
|
13
13
|
headers: Record<string, string>;
|
|
14
14
|
};
|
|
15
15
|
logging: {
|
|
16
|
+
enabled: boolean;
|
|
16
17
|
level: string;
|
|
17
18
|
format: LogFormat;
|
|
18
19
|
transports: LogTransportKind[];
|
package/dist/apm.config.js
CHANGED
|
@@ -45,6 +45,7 @@ function getApmConfig() {
|
|
|
45
45
|
headers: parseHeaders(env.OTEL_EXPORTER_OTLP_HEADERS),
|
|
46
46
|
},
|
|
47
47
|
logging: {
|
|
48
|
+
enabled: !transports.includes('none'),
|
|
48
49
|
level: env.LOG_LEVEL || (nodeEnv === 'local' ? 'debug' : 'info'),
|
|
49
50
|
format: env.APM_LOG_FORMAT || (isLocal ? 'pretty' : 'json'),
|
|
50
51
|
transports: transports.length ? transports : ['stdout'],
|
|
@@ -14,7 +14,7 @@ const apm_config_1 = require("../apm.config");
|
|
|
14
14
|
const winston_instance_1 = require("../logger/winston.instance");
|
|
15
15
|
let ApmLoggingInterceptor = class ApmLoggingInterceptor {
|
|
16
16
|
intercept(context, next) {
|
|
17
|
-
if (context.getType() !== 'http') {
|
|
17
|
+
if (context.getType() !== 'http' || !(0, apm_config_1.getApmConfig)().logging.enabled) {
|
|
18
18
|
return next.handle();
|
|
19
19
|
}
|
|
20
20
|
const request = context.switchToHttp().getRequest();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LoggerService } from '@nestjs/common';
|
|
2
2
|
export declare class ApmLoggerService implements LoggerService {
|
|
3
|
+
private readonly fallback;
|
|
3
4
|
log(message: any, context?: string): void;
|
|
4
5
|
error(message: any, trace?: string, context?: string): void;
|
|
5
6
|
warn(message: any, context?: string): void;
|
|
@@ -8,24 +8,57 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.ApmLoggerService = void 0;
|
|
10
10
|
const common_1 = require("@nestjs/common");
|
|
11
|
+
const apm_config_1 = require("../apm.config");
|
|
11
12
|
const winston_instance_1 = require("./winston.instance");
|
|
13
|
+
const NEST_LEVELS = {
|
|
14
|
+
error: ['fatal', 'error'],
|
|
15
|
+
warn: ['fatal', 'error', 'warn'],
|
|
16
|
+
info: ['fatal', 'error', 'warn', 'log'],
|
|
17
|
+
http: ['fatal', 'error', 'warn', 'log'],
|
|
18
|
+
verbose: ['fatal', 'error', 'warn', 'log', 'verbose'],
|
|
19
|
+
debug: ['fatal', 'error', 'warn', 'log', 'verbose', 'debug'],
|
|
20
|
+
silly: ['fatal', 'error', 'warn', 'log', 'verbose', 'debug'],
|
|
21
|
+
};
|
|
22
|
+
function buildFallbackLogger() {
|
|
23
|
+
const { logging } = (0, apm_config_1.getApmConfig)();
|
|
24
|
+
if (logging.enabled)
|
|
25
|
+
return undefined;
|
|
26
|
+
return new common_1.ConsoleLogger(undefined, {
|
|
27
|
+
logLevels: NEST_LEVELS[logging.level] || NEST_LEVELS.info,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
12
30
|
let ApmLoggerService = class ApmLoggerService {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.fallback = buildFallbackLogger();
|
|
33
|
+
}
|
|
13
34
|
log(message, context) {
|
|
35
|
+
if (this.fallback)
|
|
36
|
+
return this.fallback.log(message, context);
|
|
14
37
|
winston_instance_1.winstonLogger.info(this.stringify(message), { context });
|
|
15
38
|
}
|
|
16
39
|
error(message, trace, context) {
|
|
40
|
+
if (this.fallback)
|
|
41
|
+
return this.fallback.error(message, trace, context);
|
|
17
42
|
winston_instance_1.winstonLogger.error(this.stringify(message), { trace, context });
|
|
18
43
|
}
|
|
19
44
|
warn(message, context) {
|
|
45
|
+
if (this.fallback)
|
|
46
|
+
return this.fallback.warn(message, context);
|
|
20
47
|
winston_instance_1.winstonLogger.warn(this.stringify(message), { context });
|
|
21
48
|
}
|
|
22
49
|
debug(message, context) {
|
|
50
|
+
if (this.fallback)
|
|
51
|
+
return this.fallback.debug(message, context);
|
|
23
52
|
winston_instance_1.winstonLogger.debug(this.stringify(message), { context });
|
|
24
53
|
}
|
|
25
54
|
fatal(message, context) {
|
|
55
|
+
if (this.fallback)
|
|
56
|
+
return this.fallback.fatal(message, context);
|
|
26
57
|
winston_instance_1.winstonLogger.error(this.stringify(message), { context, fatal: true });
|
|
27
58
|
}
|
|
28
59
|
verbose(message, context) {
|
|
60
|
+
if (this.fallback)
|
|
61
|
+
return this.fallback.verbose(message, context);
|
|
29
62
|
winston_instance_1.winstonLogger.verbose(this.stringify(message), { context });
|
|
30
63
|
}
|
|
31
64
|
stringify(message) {
|
|
@@ -122,11 +122,17 @@ function buildTransports() {
|
|
|
122
122
|
return transports;
|
|
123
123
|
}
|
|
124
124
|
const config = (0, apm_config_1.getApmConfig)();
|
|
125
|
-
exports.winstonLogger =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
exports.winstonLogger = config.logging.enabled
|
|
126
|
+
? winston.createLogger({
|
|
127
|
+
level: config.logging.level,
|
|
128
|
+
defaultMeta: {
|
|
129
|
+
service: config.serviceName,
|
|
130
|
+
environment: config.environment,
|
|
131
|
+
},
|
|
132
|
+
transports: buildTransports(),
|
|
133
|
+
})
|
|
134
|
+
:
|
|
135
|
+
winston.createLogger({ silent: true });
|
|
130
136
|
exports.winstonLogger.on('error', (err) => {
|
|
131
137
|
console.error('[apm] log transport error:', err instanceof Error ? err.message : err);
|
|
132
138
|
});
|
package/dist/tracing.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var _a, _b;
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
const apm_config_1 = require("./apm.config");
|
|
4
5
|
const config = (0, apm_config_1.getApmConfig)();
|
|
@@ -7,6 +8,8 @@ if (config.enabled && config.tracing.enabled && config.tracing.otlpEndpoint) {
|
|
|
7
8
|
process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS =
|
|
8
9
|
'http,undici,express,nestjs-core,pg,ioredis,redis,amqplib';
|
|
9
10
|
}
|
|
11
|
+
(_a = process.env).OTEL_METRICS_EXPORTER || (_a.OTEL_METRICS_EXPORTER = 'none');
|
|
12
|
+
(_b = process.env).OTEL_LOGS_EXPORTER || (_b.OTEL_LOGS_EXPORTER = 'none');
|
|
10
13
|
const { NodeSDK } = require('@opentelemetry/sdk-node');
|
|
11
14
|
const { getNodeAutoInstrumentations, } = require('@opentelemetry/auto-instrumentations-node');
|
|
12
15
|
const { resourceFromAttributes } = require('@opentelemetry/resources');
|
|
@@ -32,12 +35,16 @@ if (config.enabled && config.tracing.enabled && config.tracing.otlpEndpoint) {
|
|
|
32
35
|
sdk.start();
|
|
33
36
|
const SHUTDOWN_TIMEOUT_MS = 5000;
|
|
34
37
|
const onSignal = (signal) => {
|
|
38
|
+
let timer;
|
|
35
39
|
Promise.race([
|
|
36
40
|
sdk.shutdown(),
|
|
37
|
-
new Promise((resolve) =>
|
|
41
|
+
new Promise((resolve) => {
|
|
42
|
+
timer = setTimeout(resolve, SHUTDOWN_TIMEOUT_MS);
|
|
43
|
+
}),
|
|
38
44
|
])
|
|
39
45
|
.catch((err) => console.error('[apm] error shutting down OTel SDK', err))
|
|
40
46
|
.finally(() => {
|
|
47
|
+
clearTimeout(timer);
|
|
41
48
|
if (process.listenerCount(signal) === 0) {
|
|
42
49
|
process.kill(process.pid, signal);
|
|
43
50
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qlibs/apm",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Vendor-neutral APM for NestJS: OpenTelemetry tracing (OTLP) + structured logging + error monitoring. Works with SigNoz, Elastic/Kibana, Jaeger, or any OTel collector.",
|
|
5
5
|
"author": "QBIT Developer",
|
|
6
6
|
"license": "MIT",
|