@grupodiariodaregiao/bunstone 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +298 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +53329 -42958
- package/dist/lib/app-startup.d.ts +5 -0
- package/dist/lib/database/sql-module.d.ts +3 -0
- package/dist/lib/rabbitmq/rabbitmq.service.d.ts +0 -26
- package/dist/lib/telemetry/index.d.ts +3 -0
- package/dist/lib/telemetry/interfaces/telemetry-options.interface.d.ts +68 -0
- package/dist/lib/telemetry/telemetry-module.d.ts +37 -0
- package/dist/lib/telemetry/telemetry.sdk.d.ts +25 -0
- package/docs/telemetry.md +292 -0
- package/lib/app-startup.ts +337 -20
- package/lib/cqrs/command-bus.ts +46 -1
- package/lib/cqrs/event-bus.ts +37 -10
- package/lib/cqrs/query-bus.ts +46 -1
- package/lib/database/sql-module.ts +149 -6
- package/lib/rabbitmq/rabbitmq.service.ts +149 -80
- package/lib/telemetry/index.ts +6 -0
- package/lib/telemetry/interfaces/telemetry-options.interface.ts +72 -0
- package/lib/telemetry/telemetry-module.ts +60 -0
- package/lib/telemetry/telemetry.sdk.ts +159 -0
- package/package.json +9 -1
package/AGENTS.md
CHANGED
|
@@ -193,6 +193,7 @@ This file is published with the `@grupodiariodaregiao/bunstone` package so codin
|
|
|
193
193
|
- `docs/pt-BR/routing-params.md`
|
|
194
194
|
- `docs/pt-BR/scheduling.md`
|
|
195
195
|
- `docs/pt-BR/testing.md`
|
|
196
|
+
- `docs/telemetry.md`
|
|
196
197
|
|
|
197
198
|
## Bundled Examples
|
|
198
199
|
|
|
@@ -5559,6 +5560,303 @@ it("deve mockar um command handler", async () => {
|
|
|
5559
5560
|
O utilitário `Test.createTestingModule()` limpa automaticamente o `GlobalRegistry` e o estado interno antes da compilação, garantindo que os testes permaneçam isolados entre si.
|
|
5560
5561
|
````
|
|
5561
5562
|
|
|
5563
|
+
## Source: `docs/telemetry.md`
|
|
5564
|
+
|
|
5565
|
+
````md
|
|
5566
|
+
# OpenTelemetry (Observability)
|
|
5567
|
+
|
|
5568
|
+
Bunstone has built-in OpenTelemetry instrumentation that automatically captures **traces** and **metrics** from all major application layers — no manual instrumentation required.
|
|
5569
|
+
|
|
5570
|
+
## What gets instrumented automatically
|
|
5571
|
+
|
|
5572
|
+
| Layer | Traces | Metrics |
|
|
5573
|
+
|---|---|---|
|
|
5574
|
+
| **HTTP** (Elysia routes) | ✅ Per-request spans with route, method, status | ✅ `http.server.request.duration`, `http.server.request.count` |
|
|
5575
|
+
| **SQL** | ✅ Per-query spans with operation and sanitized SQL | ✅ `db.query.duration` |
|
|
5576
|
+
| **CQRS — Commands** | ✅ Per-command spans | ✅ `cqrs.command.duration` |
|
|
5577
|
+
| **CQRS — Queries** | ✅ Per-query spans | ✅ `cqrs.query.duration` |
|
|
5578
|
+
| **CQRS — Events** | ✅ Per-publish spans | ✅ `cqrs.event.publish.count` |
|
|
5579
|
+
| **RabbitMQ — publish** | ✅ Producer spans + W3C context injection | ✅ `messaging.rabbitmq.publish.duration` |
|
|
5580
|
+
| **RabbitMQ — consume** | ✅ Consumer spans + W3C context extraction | ✅ `messaging.rabbitmq.consume.duration` |
|
|
5581
|
+
| **BullMQ — process** | ✅ Per-job spans | ✅ `messaging.bullmq.process.duration` |
|
|
5582
|
+
|
|
5583
|
+
> **Context propagation is automatic.** Because every HTTP request runs inside an OTel `AsyncLocalStorage` context, SQL queries, CQRS commands, and message publishes that happen during a request are automatically nested as child spans of the HTTP span — no manual context passing needed.
|
|
5584
|
+
|
|
5585
|
+
## Quick start
|
|
5586
|
+
|
|
5587
|
+
### 1. Install (already included in Bunstone)
|
|
5588
|
+
|
|
5589
|
+
```bash
|
|
5590
|
+
# OTel packages are bundled — nothing extra to install
|
|
5591
|
+
```
|
|
5592
|
+
|
|
5593
|
+
### 2. Register `TelemetryModule`
|
|
5594
|
+
|
|
5595
|
+
Add it as the **first** import in your root module so the SDK is ready before any routes start handling requests.
|
|
5596
|
+
|
|
5597
|
+
```typescript
|
|
5598
|
+
import { Module, TelemetryModule } from "@grupodiariodaregiao/bunstone";
|
|
5599
|
+
|
|
5600
|
+
@Module({
|
|
5601
|
+
imports: [
|
|
5602
|
+
TelemetryModule.register({
|
|
5603
|
+
serviceName: "orders-api",
|
|
5604
|
+
serviceVersion: "1.2.0",
|
|
5605
|
+
environment: process.env.NODE_ENV ?? "production",
|
|
5606
|
+
traces: {
|
|
5607
|
+
otlp: { endpoint: "http://otel-collector:4318" },
|
|
5608
|
+
},
|
|
5609
|
+
metrics: {
|
|
5610
|
+
otlp: { endpoint: "http://otel-collector:4318" },
|
|
5611
|
+
exportIntervalMillis: 30_000,
|
|
5612
|
+
},
|
|
5613
|
+
}),
|
|
5614
|
+
// ... other modules
|
|
5615
|
+
],
|
|
5616
|
+
})
|
|
5617
|
+
export class AppModule {}
|
|
5618
|
+
```
|
|
5619
|
+
|
|
5620
|
+
### 3. Start your app normally
|
|
5621
|
+
|
|
5622
|
+
```typescript
|
|
5623
|
+
import "reflect-metadata";
|
|
5624
|
+
import { AppStartup } from "@grupodiariodaregiao/bunstone";
|
|
5625
|
+
import { AppModule } from "./app.module";
|
|
5626
|
+
|
|
5627
|
+
const app = await AppStartup.create(AppModule);
|
|
5628
|
+
app.listen(3000);
|
|
5629
|
+
```
|
|
5630
|
+
|
|
5631
|
+
That's it. All instrumented layers will immediately start producing telemetry.
|
|
5632
|
+
|
|
5633
|
+
---
|
|
5634
|
+
|
|
5635
|
+
## Configuration reference
|
|
5636
|
+
|
|
5637
|
+
### `TelemetryOptions`
|
|
5638
|
+
|
|
5639
|
+
```typescript
|
|
5640
|
+
interface TelemetryOptions {
|
|
5641
|
+
/** Service name included in all traces and metrics — required */
|
|
5642
|
+
serviceName: string;
|
|
5643
|
+
|
|
5644
|
+
/** Semantic version string (default: "unknown") */
|
|
5645
|
+
serviceVersion?: string;
|
|
5646
|
+
|
|
5647
|
+
/** Deployment environment, e.g. "production" (default: "production") */
|
|
5648
|
+
environment?: string;
|
|
5649
|
+
|
|
5650
|
+
traces?: {
|
|
5651
|
+
/** Enable tracing. Default: true */
|
|
5652
|
+
enabled?: boolean;
|
|
5653
|
+
|
|
5654
|
+
/** OTLP HTTP exporter options */
|
|
5655
|
+
otlp?: {
|
|
5656
|
+
/**
|
|
5657
|
+
* Base endpoint URL.
|
|
5658
|
+
* Traces are sent to {endpoint}/v1/traces.
|
|
5659
|
+
* Falls back to OTEL_EXPORTER_OTLP_ENDPOINT env var, then
|
|
5660
|
+
* "http://localhost:4318".
|
|
5661
|
+
*/
|
|
5662
|
+
endpoint?: string;
|
|
5663
|
+
/** Extra HTTP headers for every OTLP request */
|
|
5664
|
+
headers?: Record<string, string>;
|
|
5665
|
+
};
|
|
5666
|
+
|
|
5667
|
+
/**
|
|
5668
|
+
* Sampling ratio 0.0–1.0.
|
|
5669
|
+
* 1.0 = record every span (default).
|
|
5670
|
+
* 0.1 = record 10 % of root spans.
|
|
5671
|
+
*/
|
|
5672
|
+
sampleRatio?: number;
|
|
5673
|
+
};
|
|
5674
|
+
|
|
5675
|
+
metrics?: {
|
|
5676
|
+
/** Enable metrics. Default: true */
|
|
5677
|
+
enabled?: boolean;
|
|
5678
|
+
|
|
5679
|
+
otlp?: {
|
|
5680
|
+
endpoint?: string;
|
|
5681
|
+
headers?: Record<string, string>;
|
|
5682
|
+
};
|
|
5683
|
+
|
|
5684
|
+
/**
|
|
5685
|
+
* How often metrics are pushed to the exporter in milliseconds.
|
|
5686
|
+
* Default: 60_000 (1 minute).
|
|
5687
|
+
*/
|
|
5688
|
+
exportIntervalMillis?: number;
|
|
5689
|
+
};
|
|
5690
|
+
|
|
5691
|
+
/**
|
|
5692
|
+
* Also print spans and metrics to stdout.
|
|
5693
|
+
* Useful in local development. Default: false.
|
|
5694
|
+
*/
|
|
5695
|
+
consoleExport?: boolean;
|
|
5696
|
+
}
|
|
5697
|
+
```
|
|
5698
|
+
|
|
5699
|
+
---
|
|
5700
|
+
|
|
5701
|
+
## Local development with console output
|
|
5702
|
+
|
|
5703
|
+
```typescript
|
|
5704
|
+
TelemetryModule.register({
|
|
5705
|
+
serviceName: "my-api",
|
|
5706
|
+
consoleExport: true, // prints spans to stdout
|
|
5707
|
+
traces: { enabled: true },
|
|
5708
|
+
metrics: { enabled: true, exportIntervalMillis: 10_000 },
|
|
5709
|
+
})
|
|
5710
|
+
```
|
|
5711
|
+
|
|
5712
|
+
---
|
|
5713
|
+
|
|
5714
|
+
## Connecting to a collector
|
|
5715
|
+
|
|
5716
|
+
Any OpenTelemetry-compatible collector works.
|
|
5717
|
+
|
|
5718
|
+
### Jaeger (all-in-one)
|
|
5719
|
+
|
|
5720
|
+
```bash
|
|
5721
|
+
docker run -d \
|
|
5722
|
+
-p 4318:4318 \ # OTLP HTTP
|
|
5723
|
+
-p 16686:16686 \ # Jaeger UI
|
|
5724
|
+
jaegertracing/all-in-one:latest
|
|
5725
|
+
```
|
|
5726
|
+
|
|
5727
|
+
```typescript
|
|
5728
|
+
TelemetryModule.register({
|
|
5729
|
+
serviceName: "my-api",
|
|
5730
|
+
traces: { otlp: { endpoint: "http://localhost:4318" } },
|
|
5731
|
+
})
|
|
5732
|
+
```
|
|
5733
|
+
|
|
5734
|
+
Open <http://localhost:16686> to view traces.
|
|
5735
|
+
|
|
5736
|
+
### Grafana + Tempo + Prometheus
|
|
5737
|
+
|
|
5738
|
+
```typescript
|
|
5739
|
+
TelemetryModule.register({
|
|
5740
|
+
serviceName: "my-api",
|
|
5741
|
+
traces: {
|
|
5742
|
+
otlp: { endpoint: "http://tempo:4318" },
|
|
5743
|
+
},
|
|
5744
|
+
metrics: {
|
|
5745
|
+
otlp: { endpoint: "http://otel-collector:4318" },
|
|
5746
|
+
exportIntervalMillis: 15_000,
|
|
5747
|
+
},
|
|
5748
|
+
})
|
|
5749
|
+
```
|
|
5750
|
+
|
|
5751
|
+
### Using environment variables
|
|
5752
|
+
|
|
5753
|
+
Instead of hardcoding the endpoint you can set:
|
|
5754
|
+
|
|
5755
|
+
```bash
|
|
5756
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
|
|
5757
|
+
```
|
|
5758
|
+
|
|
5759
|
+
and omit `otlp.endpoint` from the config object.
|
|
5760
|
+
|
|
5761
|
+
---
|
|
5762
|
+
|
|
5763
|
+
## Distributed tracing across services
|
|
5764
|
+
|
|
5765
|
+
Bunstone follows the **W3C Trace Context** standard ([RFC](https://www.w3.org/TR/trace-context/)).
|
|
5766
|
+
|
|
5767
|
+
- **Incoming requests**: The `traceparent` / `tracestate` headers are automatically extracted and used as the parent context for all spans generated during that request.
|
|
5768
|
+
- **Outgoing RabbitMQ messages**: The current trace context is automatically injected into message headers so consumers in other services can continue the same trace.
|
|
5769
|
+
|
|
5770
|
+
This means a single distributed trace can span your Bunstone service **and** any downstream service that understands W3C Trace Context.
|
|
5771
|
+
|
|
5772
|
+
---
|
|
5773
|
+
|
|
5774
|
+
## Span and metric names reference
|
|
5775
|
+
|
|
5776
|
+
### HTTP spans
|
|
5777
|
+
|
|
5778
|
+
| Attribute | Value |
|
|
5779
|
+
|---|---|
|
|
5780
|
+
| Span name | `{METHOD} {route}` — e.g. `GET /users/:id` |
|
|
5781
|
+
| `http.request.method` | `GET`, `POST`, etc. |
|
|
5782
|
+
| `http.route` | Parametrized route, e.g. `/users/:id` |
|
|
5783
|
+
| `url.path` | Actual path, e.g. `/users/123` |
|
|
5784
|
+
| `url.full` | Full URL |
|
|
5785
|
+
| `http.response.status_code` | HTTP status code |
|
|
5786
|
+
| Span status | `OK` for < 500, `ERROR` for ≥ 500 |
|
|
5787
|
+
|
|
5788
|
+
### SQL spans
|
|
5789
|
+
|
|
5790
|
+
| Attribute | Value |
|
|
5791
|
+
|---|---|
|
|
5792
|
+
| Span name | `db.{OPERATION}` — e.g. `db.SELECT` |
|
|
5793
|
+
| `db.system` | `postgresql`, `mysql`, or `sqlite` |
|
|
5794
|
+
| `db.operation.name` | SQL operation keyword |
|
|
5795
|
+
| `db.query.text` | Sanitized SQL (parameter values replaced with `?`) |
|
|
5796
|
+
|
|
5797
|
+
### CQRS spans
|
|
5798
|
+
|
|
5799
|
+
| Attribute | Value |
|
|
5800
|
+
|---|---|
|
|
5801
|
+
| Span name | `command.execute {CommandName}` / `query.execute {QueryName}` / `event.publish {EventName}` |
|
|
5802
|
+
| `cqrs.type` | `command`, `query`, or `event` |
|
|
5803
|
+
| `cqrs.command.name` / `cqrs.query.name` / `cqrs.event.name` | Class name of the command/query/event |
|
|
5804
|
+
|
|
5805
|
+
### RabbitMQ spans
|
|
5806
|
+
|
|
5807
|
+
| Attribute | Value |
|
|
5808
|
+
|---|---|
|
|
5809
|
+
| Span name | `rabbitmq.publish {exchange}` or `rabbitmq.consume {queue}` |
|
|
5810
|
+
| `messaging.system` | `rabbitmq` |
|
|
5811
|
+
| `messaging.operation.type` | `publish` or `deliver` |
|
|
5812
|
+
| `messaging.destination.name` | Exchange or queue name |
|
|
5813
|
+
| `messaging.rabbitmq.destination.routing_key` | Routing key |
|
|
5814
|
+
|
|
5815
|
+
### BullMQ spans
|
|
5816
|
+
|
|
5817
|
+
| Attribute | Value |
|
|
5818
|
+
|---|---|
|
|
5819
|
+
| Span name | `bullmq.process {queue}/{jobName}` |
|
|
5820
|
+
| `messaging.system` | `bullmq` |
|
|
5821
|
+
| `messaging.operation.type` | `process` |
|
|
5822
|
+
| `messaging.destination.name` | Queue name |
|
|
5823
|
+
| `messaging.bullmq.job.name` | Job name |
|
|
5824
|
+
| `messaging.bullmq.job.id` | Job ID |
|
|
5825
|
+
| `messaging.bullmq.job.attempts` | Number of processing attempts |
|
|
5826
|
+
|
|
5827
|
+
---
|
|
5828
|
+
|
|
5829
|
+
## Advanced: bring your own SDK
|
|
5830
|
+
|
|
5831
|
+
`TelemetryModule` is optional. If you already have a custom `TracerProvider` and `MeterProvider` set up via `@opentelemetry/api`, Bunstone's instrumentation will automatically use them — because all instrumentation only calls the OTel API, which delegates to whatever provider is globally registered.
|
|
5832
|
+
|
|
5833
|
+
```typescript
|
|
5834
|
+
import { trace, metrics } from "@opentelemetry/api";
|
|
5835
|
+
|
|
5836
|
+
// Set up your own providers before AppStartup.create()
|
|
5837
|
+
trace.setGlobalTracerProvider(myTracerProvider);
|
|
5838
|
+
metrics.setGlobalMeterProvider(myMeterProvider);
|
|
5839
|
+
|
|
5840
|
+
// Then start the app — no TelemetryModule needed
|
|
5841
|
+
const app = await AppStartup.create(AppModule);
|
|
5842
|
+
```
|
|
5843
|
+
|
|
5844
|
+
---
|
|
5845
|
+
|
|
5846
|
+
## Graceful shutdown
|
|
5847
|
+
|
|
5848
|
+
`TelemetryModule` registers an `onModuleDestroy` lifecycle hook that flushes all pending spans and metrics before the process exits. If you're not using `TelemetryModule`, call `TelemetrySdk.shutdown()` manually:
|
|
5849
|
+
|
|
5850
|
+
```typescript
|
|
5851
|
+
import { TelemetrySdk } from "@grupodiariodaregiao/bunstone";
|
|
5852
|
+
|
|
5853
|
+
process.on("SIGTERM", async () => {
|
|
5854
|
+
await TelemetrySdk.shutdown();
|
|
5855
|
+
process.exit(0);
|
|
5856
|
+
});
|
|
5857
|
+
```
|
|
5858
|
+
````
|
|
5859
|
+
|
|
5562
5860
|
## Full Examples
|
|
5563
5861
|
|
|
5564
5862
|
## Source: `examples/01-basic-app/index.ts`
|
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,9 @@ export * from "./lib/types/options";
|
|
|
63
63
|
export * from "./lib/types/module-config";
|
|
64
64
|
export * from "./lib/schedule/cron/cron";
|
|
65
65
|
export * from "./lib/schedule/timeout/timeout";
|
|
66
|
+
export { TelemetryModule } from "./lib/telemetry/telemetry-module";
|
|
67
|
+
export { TelemetrySdk } from "./lib/telemetry/telemetry.sdk";
|
|
68
|
+
export type { TelemetryOptions, OtlpExporterOptions } from "./lib/telemetry/interfaces/telemetry-options.interface";
|
|
66
69
|
export * from "./lib/testing/test";
|
|
67
70
|
export * from "./lib/testing/testing-module";
|
|
68
71
|
export * from "./lib/testing/test-app";
|