@bsb/observable-zipkin 1.0.0 → 1.1.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/README.md CHANGED
@@ -1,15 +1,13 @@
1
- # BSB Observable Zipkin
1
+ # @bsb/observable-zipkin
2
2
 
3
- Zipkin tracing integration for the Better Service Base (BSB) framework.
3
+ Zipkin tracing integration for BSB. Exports distributed traces to Zipkin and provides optional console logging.
4
4
 
5
- ## Features
5
+ ## Key Features
6
6
 
7
- - Direct Zipkin v2 API integration
8
- - Distributed tracing with OpenTelemetry instrumentation
9
- - Configurable sampling rates
10
- - Batch span export with configurable flush intervals
11
- - Console logging fallback for non-trace observability
12
- - Full TypeScript support
7
+ - Zipkin v2 API export
8
+ - OpenTelemetry-based tracing
9
+ - Configurable sampling and batching
10
+ - Optional console logging for non-trace output
13
11
 
14
12
  ## Installation
15
13
 
@@ -19,137 +17,77 @@ npm install @bsb/observable-zipkin
19
17
 
20
18
  ## Configuration
21
19
 
22
- Add to your BSB configuration file:
20
+ Add the plugin to your BSB configuration file:
23
21
 
24
22
  ```yaml
25
23
  plugins:
26
- observable:
27
- - observable-zipkin
28
-
29
- observable-zipkin:
30
- serviceName: my-service
31
- serviceVersion: 1.0.0
32
-
33
- zipkin:
34
- url: http://localhost:9411/api/v2/spans
35
- # Optional custom headers for authentication
36
- # headers:
37
- # Authorization: Bearer token123
38
-
39
- export:
40
- maxBatchSize: 100
41
- maxQueueSize: 2048
42
- scheduledDelayMillis: 5000
43
-
44
- samplingRate: 1.0 # 1.0 = 100%, 0.5 = 50%
45
-
46
- # Console logging (Zipkin doesn't handle logs/metrics)
47
- console:
48
- enabled: true
49
- logLevel: info # debug | info | warn | error
50
-
51
- # Optional resource attributes
52
- resourceAttributes:
53
- environment: production
54
- region: us-east-1
24
+ observables:
25
+ - plugin: "@bsb/observable-zipkin"
26
+ enabled: true
27
+ config:
28
+ serviceName: "my-service"
29
+ serviceVersion: "1.0.0"
30
+ zipkin:
31
+ url: "http://localhost:9411/api/v2/spans"
32
+ # headers:
33
+ # Authorization: "Bearer token123"
34
+ export:
35
+ maxBatchSize: 100
36
+ maxQueueSize: 2048
37
+ scheduledDelayMillis: 5000
38
+ samplingRate: 1.0
39
+ console:
40
+ enabled: true
41
+ logLevel: "info"
42
+ resourceAttributes:
43
+ environment: "production"
44
+ region: "us-east-1"
55
45
  ```
56
46
 
57
- ## What Gets Exported
58
-
59
- ### Traces (to Zipkin)
60
- - All span lifecycle events (start, end, error)
61
- - Span attributes and context
62
- - Distributed trace propagation
63
- - Exception tracking
64
-
65
- ### Logs (to Console)
66
- - Debug, info, warn, error levels
67
- - Structured logging with trace context
68
- - Configurable log level filtering
69
-
70
- ### Metrics (No-op)
71
- - Zipkin is trace-only, no metrics support
72
- - Use `observable-opentelemetry` or `observable-prometheus` for metrics
47
+ ### Configuration Options
48
+
49
+ | Option | Description | Default |
50
+ |--------|-------------|---------|
51
+ | `serviceName` | Service identifier | `"bsb-service"` |
52
+ | `serviceVersion` | Service version tag | - |
53
+ | `zipkin.url` | Zipkin API endpoint | `"http://localhost:9411/api/v2/spans"` |
54
+ | `zipkin.headers` | Custom HTTP headers | - |
55
+ | `export.maxBatchSize` | Max spans per batch | `100` |
56
+ | `export.maxQueueSize` | Max queued spans | `2048` |
57
+ | `export.scheduledDelayMillis` | Flush interval (ms) | `5000` |
58
+ | `samplingRate` | Sampling probability (0-1) | `1.0` |
59
+ | `console.enabled` | Enable console logs | `true` |
60
+ | `console.logLevel` | Minimum log level | `"info"` |
61
+ | `resourceAttributes` | Custom attributes | `{}` |
73
62
 
74
63
  ## Usage
75
64
 
76
- The plugin automatically integrates with BSB's Observable pattern:
65
+ Once configured, traces are exported automatically:
77
66
 
78
67
  ```typescript
79
- export class MyService extends BSBService<InstanceType<typeof Config>, typeof EventSchemas> {
80
- static Config = Config;
81
- static EventSchemas = EventSchemas;
82
-
83
- public async run(obs: Observable) {
84
- // Traces automatically sent to Zipkin
85
- obs.log.info("Service started"); // Console log
86
-
87
- // Create child span
88
- const workObs = obs.span("heavy-work");
89
- workObs.setAttribute("work.type", "batch");
90
-
91
- try {
92
- await this.doWork();
93
- workObs.end();
94
- } catch (error) {
95
- workObs.recordException(error);
96
- workObs.end();
97
- }
98
- }
99
- }
68
+ this.log.info("Service started");
69
+ const workObs = this.obs.span("heavy-work");
70
+ await this.doWork();
71
+ workObs.end();
100
72
  ```
101
73
 
102
74
  ## Zipkin Setup
103
75
 
104
- Run Zipkin locally with Docker:
76
+ Run Zipkin locally:
105
77
 
106
78
  ```bash
107
79
  docker run -d -p 9411:9411 openzipkin/zipkin
108
80
  ```
109
81
 
110
- Access UI at: http://localhost:9411
82
+ ## Documentation
111
83
 
112
- ## Architecture
84
+ Detailed documentation (used by the BSB Registry): `https://github.com/BetterCorp/better-service-base/blob/master/plugins/nodejs/observable-zipkin/docs/plugin.md`
113
85
 
114
- ```
115
- BSB Application
116
-
117
- Observable (DTrace)
118
-
119
- observable-zipkin
120
-
121
- OpenTelemetry SDK
122
-
123
- Zipkin Exporter
124
-
125
- Zipkin Server (HTTP)
126
- ```
86
+ ## Links
127
87
 
128
- ## Configuration Options
129
-
130
- | Option | Type | Default | Description |
131
- |--------|------|---------|-------------|
132
- | `serviceName` | string | `"bsb-service"` | Service identifier in Zipkin |
133
- | `serviceVersion` | string | - | Service version tag |
134
- | `zipkin.url` | string | `"http://localhost:9411/api/v2/spans"` | Zipkin API endpoint |
135
- | `zipkin.headers` | object | - | Custom HTTP headers |
136
- | `export.maxBatchSize` | number | `100` | Max spans per batch |
137
- | `export.maxQueueSize` | number | `2048` | Max queued spans |
138
- | `export.scheduledDelayMillis` | number | `5000` | Flush interval (ms) |
139
- | `samplingRate` | number | `1.0` | Sampling probability (0-1) |
140
- | `console.enabled` | boolean | `true` | Enable console logs |
141
- | `console.logLevel` | string | `"info"` | Minimum log level |
142
-
143
- ## Comparison with Other Observability Plugins
144
-
145
- | Plugin | Traces | Metrics | Logs | Backend |
146
- |--------|--------|---------|------|---------|
147
- | observable-zipkin | ✅ | ❌ | Console | Zipkin |
148
- | observable-opentelemetry | ✅ | ✅ | ✅ | OTLP Collector |
149
- | observable-default | ❌ | ❌ | Console | - |
88
+ - GitHub: `https://github.com/BetterCorp/better-service-base/tree/master/plugins/nodejs/observable-zipkin`
89
+ - BSB Registry (package): `https://io.bsbcode.dev/packages/nodejs/@bsb/observable-zipkin`
150
90
 
151
91
  ## License
152
92
 
153
- AGPL-3.0 - See LICENSE file for details.
154
-
155
- Commercial licenses available at https://www.bettercorp.dev
93
+ (AGPL-3.0-only OR Commercial)
package/bsb-tests.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "nodejs": [
3
+ {
4
+ "id": "observable-zipkin",
5
+ "skip": true,
6
+ "default": {
7
+ "config": {},
8
+ "setup": null,
9
+ "dispose": null
10
+ },
11
+ "tests": []
12
+ }
13
+ ]
14
+ }
@@ -26,33 +26,28 @@
26
26
  */
27
27
  import { BSBObservable, BSBObservableConstructor, BSBError } from "@bsb/base";
28
28
  import { DTrace, LogMeta } from "@bsb/base";
29
- import { z } from "zod";
30
- export declare const Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObject<{
31
- serviceName: z.ZodDefault<z.ZodString>;
32
- serviceVersion: z.ZodOptional<z.ZodString>;
33
- zipkin: z.ZodObject<{
34
- url: z.ZodDefault<z.ZodString>;
35
- headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
36
- statusCodeTagName: z.ZodDefault<z.ZodString>;
37
- statusDescriptionTagName: z.ZodDefault<z.ZodString>;
38
- }, z.core.$strip>;
39
- export: z.ZodObject<{
40
- maxBatchSize: z.ZodDefault<z.ZodNumber>;
41
- maxQueueSize: z.ZodDefault<z.ZodNumber>;
42
- scheduledDelayMillis: z.ZodDefault<z.ZodNumber>;
43
- }, z.core.$strip>;
44
- resourceAttributes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
45
- samplingRate: z.ZodDefault<z.ZodNumber>;
46
- console: z.ZodObject<{
47
- enabled: z.ZodDefault<z.ZodBoolean>;
48
- logLevel: z.ZodDefault<z.ZodEnum<{
49
- error: "error";
50
- debug: "debug";
51
- info: "info";
52
- warn: "warn";
53
- }>>;
54
- }, z.core.$strip>;
55
- }, z.core.$strip>>;
29
+ import * as av from "@anyvali/js";
30
+ export declare const Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
31
+ serviceName: av.OptionalSchema<av.StringSchema>;
32
+ serviceVersion: av.OptionalSchema<av.StringSchema>;
33
+ zipkin: av.ObjectSchema<{
34
+ url: av.OptionalSchema<av.StringSchema>;
35
+ headers: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
36
+ statusCodeTagName: av.OptionalSchema<av.StringSchema>;
37
+ statusDescriptionTagName: av.OptionalSchema<av.StringSchema>;
38
+ }>;
39
+ export: av.ObjectSchema<{
40
+ maxBatchSize: av.OptionalSchema<av.Int32Schema>;
41
+ maxQueueSize: av.OptionalSchema<av.Int32Schema>;
42
+ scheduledDelayMillis: av.OptionalSchema<av.Int32Schema>;
43
+ }>;
44
+ resourceAttributes: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
45
+ samplingRate: av.OptionalSchema<av.NumberSchema>;
46
+ console: av.ObjectSchema<{
47
+ enabled: av.OptionalSchema<av.BoolSchema>;
48
+ logLevel: av.OptionalSchema<av.EnumSchema<string[]>>;
49
+ }>;
50
+ }>>;
56
51
  /**
57
52
  * Zipkin observable plugin for distributed tracing
58
53
  *
@@ -60,32 +55,27 @@ export declare const Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObjec
60
55
  * Provides console logging fallback for non-trace observability.
61
56
  */
62
57
  export declare class Plugin extends BSBObservable<InstanceType<typeof Config>> {
63
- static Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObject<{
64
- serviceName: z.ZodDefault<z.ZodString>;
65
- serviceVersion: z.ZodOptional<z.ZodString>;
66
- zipkin: z.ZodObject<{
67
- url: z.ZodDefault<z.ZodString>;
68
- headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
69
- statusCodeTagName: z.ZodDefault<z.ZodString>;
70
- statusDescriptionTagName: z.ZodDefault<z.ZodString>;
71
- }, z.core.$strip>;
72
- export: z.ZodObject<{
73
- maxBatchSize: z.ZodDefault<z.ZodNumber>;
74
- maxQueueSize: z.ZodDefault<z.ZodNumber>;
75
- scheduledDelayMillis: z.ZodDefault<z.ZodNumber>;
76
- }, z.core.$strip>;
77
- resourceAttributes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
78
- samplingRate: z.ZodDefault<z.ZodNumber>;
79
- console: z.ZodObject<{
80
- enabled: z.ZodDefault<z.ZodBoolean>;
81
- logLevel: z.ZodDefault<z.ZodEnum<{
82
- error: "error";
83
- debug: "debug";
84
- info: "info";
85
- warn: "warn";
86
- }>>;
87
- }, z.core.$strip>;
88
- }, z.core.$strip>>;
58
+ static Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
59
+ serviceName: av.OptionalSchema<av.StringSchema>;
60
+ serviceVersion: av.OptionalSchema<av.StringSchema>;
61
+ zipkin: av.ObjectSchema<{
62
+ url: av.OptionalSchema<av.StringSchema>;
63
+ headers: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
64
+ statusCodeTagName: av.OptionalSchema<av.StringSchema>;
65
+ statusDescriptionTagName: av.OptionalSchema<av.StringSchema>;
66
+ }>;
67
+ export: av.ObjectSchema<{
68
+ maxBatchSize: av.OptionalSchema<av.Int32Schema>;
69
+ maxQueueSize: av.OptionalSchema<av.Int32Schema>;
70
+ scheduledDelayMillis: av.OptionalSchema<av.Int32Schema>;
71
+ }>;
72
+ resourceAttributes: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
73
+ samplingRate: av.OptionalSchema<av.NumberSchema>;
74
+ console: av.ObjectSchema<{
75
+ enabled: av.OptionalSchema<av.BoolSchema>;
76
+ logLevel: av.OptionalSchema<av.EnumSchema<string[]>>;
77
+ }>;
78
+ }>>;
89
79
  private logFormatter;
90
80
  private tracerProvider;
91
81
  private tracer;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * BSB (Better-Service-Base) is an event-bus based microservice framework.
4
3
  * Copyright (C) 2016 - 2025 BetterCorp (PTY) Ltd
@@ -25,70 +24,35 @@
25
24
  * You should have received a copy of the GNU Affero General Public License
26
25
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27
26
  */
28
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
29
- if (k2 === undefined) k2 = k;
30
- var desc = Object.getOwnPropertyDescriptor(m, k);
31
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
32
- desc = { enumerable: true, get: function() { return m[k]; } };
33
- }
34
- Object.defineProperty(o, k2, desc);
35
- }) : (function(o, m, k, k2) {
36
- if (k2 === undefined) k2 = k;
37
- o[k2] = m[k];
38
- }));
39
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
40
- Object.defineProperty(o, "default", { enumerable: true, value: v });
41
- }) : function(o, v) {
42
- o["default"] = v;
43
- });
44
- var __importStar = (this && this.__importStar) || (function () {
45
- var ownKeys = function(o) {
46
- ownKeys = Object.getOwnPropertyNames || function (o) {
47
- var ar = [];
48
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
49
- return ar;
50
- };
51
- return ownKeys(o);
52
- };
53
- return function (mod) {
54
- if (mod && mod.__esModule) return mod;
55
- var result = {};
56
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
57
- __setModuleDefault(result, mod);
58
- return result;
59
- };
60
- })();
61
- Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.Plugin = exports.Config = void 0;
63
- const base_1 = require("@bsb/base");
64
- const zod_1 = require("zod");
65
- const api = __importStar(require("@opentelemetry/api"));
66
- const resources_1 = require("@opentelemetry/resources");
67
- const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
68
- const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
69
- const exporter_zipkin_1 = require("@opentelemetry/exporter-zipkin");
70
- const ConfigSchema = zod_1.z.object({
71
- serviceName: zod_1.z.string().default("bsb-service"),
72
- serviceVersion: zod_1.z.string().optional(),
73
- zipkin: zod_1.z.object({
74
- url: zod_1.z.string().url().default("http://localhost:9411/api/v2/spans"),
75
- headers: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
76
- statusCodeTagName: zod_1.z.string().default("http.status_code"),
77
- statusDescriptionTagName: zod_1.z.string().default("http.status_text"),
78
- }),
79
- export: zod_1.z.object({
80
- maxBatchSize: zod_1.z.number().int().min(1).default(100),
81
- maxQueueSize: zod_1.z.number().int().min(1).default(2048),
82
- scheduledDelayMillis: zod_1.z.number().int().min(100).default(5000),
83
- }),
84
- resourceAttributes: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).default({}),
85
- samplingRate: zod_1.z.number().min(0).max(1).default(1.0),
86
- console: zod_1.z.object({
87
- enabled: zod_1.z.boolean().default(true),
88
- logLevel: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default('info'),
89
- }),
90
- });
91
- exports.Config = (0, base_1.createConfigSchema)({
27
+ import { BSBObservable, createConfigSchema, LogFormatter, BSBError } from "@bsb/base";
28
+ import * as av from "@anyvali/js";
29
+ import * as api from "@opentelemetry/api";
30
+ import { Resource } from "@opentelemetry/resources";
31
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
32
+ import { BasicTracerProvider, BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
33
+ import { ZipkinExporter } from "@opentelemetry/exporter-zipkin";
34
+ const ConfigSchema = av.object({
35
+ serviceName: av.optional(av.string()).default("bsb-service"),
36
+ serviceVersion: av.optional(av.string()),
37
+ zipkin: av.object({
38
+ url: av.optional(av.string().format("url")).default("http://localhost:9411/api/v2/spans"),
39
+ headers: av.optional(av.record(av.string())),
40
+ statusCodeTagName: av.optional(av.string()).default("http.status_code"),
41
+ statusDescriptionTagName: av.optional(av.string()).default("http.status_text"),
42
+ }, { unknownKeys: "strip" }),
43
+ export: av.object({
44
+ maxBatchSize: av.optional(av.int32().min(1)).default(100),
45
+ maxQueueSize: av.optional(av.int32().min(1)).default(2048),
46
+ scheduledDelayMillis: av.optional(av.int32().min(100)).default(5000),
47
+ }, { unknownKeys: "strip" }),
48
+ resourceAttributes: av.optional(av.record(av.string())).default({}),
49
+ samplingRate: av.optional(av.number().min(0).max(1)).default(1.0),
50
+ console: av.object({
51
+ enabled: av.optional(av.bool()).default(true),
52
+ logLevel: av.optional(av.enum_(['debug', 'info', 'warn', 'error'])).default('info'),
53
+ }, { unknownKeys: "strip" }),
54
+ }, { unknownKeys: "strip" });
55
+ export const Config = createConfigSchema({
92
56
  name: 'observable-zipkin',
93
57
  description: 'Zipkin tracing integration for BSB framework',
94
58
  version: '1.0.0',
@@ -100,10 +64,10 @@ exports.Config = (0, base_1.createConfigSchema)({
100
64
  * Exports traces directly to Zipkin using the Zipkin v2 API format.
101
65
  * Provides console logging fallback for non-trace observability.
102
66
  */
103
- class Plugin extends base_1.BSBObservable {
67
+ export class Plugin extends BSBObservable {
104
68
  constructor(config) {
105
69
  super(config);
106
- this.logFormatter = new base_1.LogFormatter();
70
+ this.logFormatter = new LogFormatter();
107
71
  this.tracerProvider = null;
108
72
  this.tracer = null;
109
73
  this.exporter = null;
@@ -111,21 +75,21 @@ class Plugin extends base_1.BSBObservable {
111
75
  this.spans = new Map();
112
76
  }
113
77
  async init() {
114
- const resource = new resources_1.Resource({
115
- [semantic_conventions_1.ATTR_SERVICE_NAME]: this.config.serviceName,
116
- ...(this.config.serviceVersion && { [semantic_conventions_1.ATTR_SERVICE_VERSION]: this.config.serviceVersion }),
78
+ const resource = new Resource({
79
+ [ATTR_SERVICE_NAME]: this.config.serviceName,
80
+ ...(this.config.serviceVersion && { [ATTR_SERVICE_VERSION]: this.config.serviceVersion }),
117
81
  ...this.config.resourceAttributes,
118
82
  });
119
- this.exporter = new exporter_zipkin_1.ZipkinExporter({
83
+ this.exporter = new ZipkinExporter({
120
84
  url: this.config.zipkin.url,
121
85
  headers: this.config.zipkin.headers,
122
86
  statusCodeTagName: this.config.zipkin.statusCodeTagName,
123
87
  statusDescriptionTagName: this.config.zipkin.statusDescriptionTagName,
124
88
  });
125
- this.tracerProvider = new sdk_trace_base_1.BasicTracerProvider({
89
+ this.tracerProvider = new BasicTracerProvider({
126
90
  resource,
127
91
  });
128
- this.tracerProvider.addSpanProcessor(new sdk_trace_base_1.BatchSpanProcessor(this.exporter, {
92
+ this.tracerProvider.addSpanProcessor(new BatchSpanProcessor(this.exporter, {
129
93
  maxQueueSize: this.config.export.maxQueueSize,
130
94
  maxExportBatchSize: this.config.export.maxBatchSize,
131
95
  scheduledDelayMillis: this.config.export.scheduledDelayMillis,
@@ -201,7 +165,7 @@ class Plugin extends base_1.BSBObservable {
201
165
  this.writeConsoleLog("warn", trace, pluginName, message, meta);
202
166
  }
203
167
  error(trace, pluginName, message, meta) {
204
- if (message instanceof base_1.BSBError) {
168
+ if (message instanceof BSBError) {
205
169
  if (message.raw !== null) {
206
170
  this.writeConsoleLog("error", message.raw.trace, pluginName, message.raw.message, message.raw.meta);
207
171
  }
@@ -292,5 +256,4 @@ class Plugin extends base_1.BSBObservable {
292
256
  this.exporter = null;
293
257
  }
294
258
  }
295
- exports.Plugin = Plugin;
296
- Plugin.Config = exports.Config;
259
+ Plugin.Config = Config;
@@ -2,130 +2,6 @@
2
2
  "pluginName": "observable-zipkin",
3
3
  "version": "1.0.0",
4
4
  "events": {},
5
- "configSchema": {
6
- "$schema": "https://json-schema.org/draft/2020-12/schema",
7
- "type": "object",
8
- "properties": {
9
- "serviceName": {
10
- "default": "bsb-service",
11
- "type": "string"
12
- },
13
- "serviceVersion": {
14
- "type": "string"
15
- },
16
- "zipkin": {
17
- "type": "object",
18
- "properties": {
19
- "url": {
20
- "default": "http://localhost:9411/api/v2/spans",
21
- "type": "string",
22
- "format": "uri"
23
- },
24
- "headers": {
25
- "type": "object",
26
- "propertyNames": {
27
- "type": "string"
28
- },
29
- "additionalProperties": {
30
- "type": "string"
31
- }
32
- },
33
- "statusCodeTagName": {
34
- "default": "http.status_code",
35
- "type": "string"
36
- },
37
- "statusDescriptionTagName": {
38
- "default": "http.status_text",
39
- "type": "string"
40
- }
41
- },
42
- "required": [
43
- "url",
44
- "statusCodeTagName",
45
- "statusDescriptionTagName"
46
- ],
47
- "additionalProperties": false
48
- },
49
- "export": {
50
- "type": "object",
51
- "properties": {
52
- "maxBatchSize": {
53
- "default": 100,
54
- "type": "integer",
55
- "minimum": 1,
56
- "maximum": 9007199254740991
57
- },
58
- "maxQueueSize": {
59
- "default": 2048,
60
- "type": "integer",
61
- "minimum": 1,
62
- "maximum": 9007199254740991
63
- },
64
- "scheduledDelayMillis": {
65
- "default": 5000,
66
- "type": "integer",
67
- "minimum": 100,
68
- "maximum": 9007199254740991
69
- }
70
- },
71
- "required": [
72
- "maxBatchSize",
73
- "maxQueueSize",
74
- "scheduledDelayMillis"
75
- ],
76
- "additionalProperties": false
77
- },
78
- "resourceAttributes": {
79
- "default": {},
80
- "type": "object",
81
- "propertyNames": {
82
- "type": "string"
83
- },
84
- "additionalProperties": {
85
- "type": "string"
86
- }
87
- },
88
- "samplingRate": {
89
- "default": 1,
90
- "type": "number",
91
- "minimum": 0,
92
- "maximum": 1
93
- },
94
- "console": {
95
- "type": "object",
96
- "properties": {
97
- "enabled": {
98
- "default": true,
99
- "type": "boolean"
100
- },
101
- "logLevel": {
102
- "default": "info",
103
- "type": "string",
104
- "enum": [
105
- "debug",
106
- "info",
107
- "warn",
108
- "error"
109
- ]
110
- }
111
- },
112
- "required": [
113
- "enabled",
114
- "logLevel"
115
- ],
116
- "additionalProperties": false
117
- }
118
- },
119
- "required": [
120
- "serviceName",
121
- "zipkin",
122
- "export",
123
- "resourceAttributes",
124
- "samplingRate",
125
- "console"
126
- ],
127
- "additionalProperties": false
128
- },
129
5
  "pluginType": "observable",
130
6
  "capabilities": {
131
7
  "logging": {
@@ -11,129 +11,5 @@
11
11
  "distributed-tracing"
12
12
  ],
13
13
  "documentation": [],
14
- "dependencies": [],
15
- "configSchema": {
16
- "$schema": "https://json-schema.org/draft/2020-12/schema",
17
- "type": "object",
18
- "properties": {
19
- "serviceName": {
20
- "default": "bsb-service",
21
- "type": "string"
22
- },
23
- "serviceVersion": {
24
- "type": "string"
25
- },
26
- "zipkin": {
27
- "type": "object",
28
- "properties": {
29
- "url": {
30
- "default": "http://localhost:9411/api/v2/spans",
31
- "type": "string",
32
- "format": "uri"
33
- },
34
- "headers": {
35
- "type": "object",
36
- "propertyNames": {
37
- "type": "string"
38
- },
39
- "additionalProperties": {
40
- "type": "string"
41
- }
42
- },
43
- "statusCodeTagName": {
44
- "default": "http.status_code",
45
- "type": "string"
46
- },
47
- "statusDescriptionTagName": {
48
- "default": "http.status_text",
49
- "type": "string"
50
- }
51
- },
52
- "required": [
53
- "url",
54
- "statusCodeTagName",
55
- "statusDescriptionTagName"
56
- ],
57
- "additionalProperties": false
58
- },
59
- "export": {
60
- "type": "object",
61
- "properties": {
62
- "maxBatchSize": {
63
- "default": 100,
64
- "type": "integer",
65
- "minimum": 1,
66
- "maximum": 9007199254740991
67
- },
68
- "maxQueueSize": {
69
- "default": 2048,
70
- "type": "integer",
71
- "minimum": 1,
72
- "maximum": 9007199254740991
73
- },
74
- "scheduledDelayMillis": {
75
- "default": 5000,
76
- "type": "integer",
77
- "minimum": 100,
78
- "maximum": 9007199254740991
79
- }
80
- },
81
- "required": [
82
- "maxBatchSize",
83
- "maxQueueSize",
84
- "scheduledDelayMillis"
85
- ],
86
- "additionalProperties": false
87
- },
88
- "resourceAttributes": {
89
- "default": {},
90
- "type": "object",
91
- "propertyNames": {
92
- "type": "string"
93
- },
94
- "additionalProperties": {
95
- "type": "string"
96
- }
97
- },
98
- "samplingRate": {
99
- "default": 1,
100
- "type": "number",
101
- "minimum": 0,
102
- "maximum": 1
103
- },
104
- "console": {
105
- "type": "object",
106
- "properties": {
107
- "enabled": {
108
- "default": true,
109
- "type": "boolean"
110
- },
111
- "logLevel": {
112
- "default": "info",
113
- "type": "string",
114
- "enum": [
115
- "debug",
116
- "info",
117
- "warn",
118
- "error"
119
- ]
120
- }
121
- },
122
- "required": [
123
- "enabled",
124
- "logLevel"
125
- ],
126
- "additionalProperties": false
127
- }
128
- },
129
- "required": [
130
- "serviceName",
131
- "zipkin",
132
- "export",
133
- "resourceAttributes",
134
- "samplingRate",
135
- "console"
136
- ],
137
- "additionalProperties": false
138
- }
14
+ "dependencies": []
139
15
  }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@bsb/observable-zipkin",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Zipkin tracing integration for BSB framework",
5
+ "type": "module",
5
6
  "main": "lib/plugins/observable-zipkin/index.js",
6
7
  "types": "lib/plugins/observable-zipkin/index.d.ts",
7
8
  "scripts": {
@@ -24,26 +25,25 @@
24
25
  "license": "(AGPL-3.0-only OR Commercial)",
25
26
  "author": {
26
27
  "name": "BetterCorp (PTY) Ltd",
27
- "email": "nick@bettercorp.dev",
28
+ "email": "ninja@bettercorp.dev",
28
29
  "url": "https://bettercorp.dev/"
29
30
  },
30
31
  "peerDependencies": {
31
32
  "@bsb/base": "^9.0.0"
32
33
  },
33
34
  "dependencies": {
35
+ "@anyvali/js": "^0.2.0",
34
36
  "@opentelemetry/api": "^1.9.0",
35
37
  "@opentelemetry/exporter-zipkin": "^1.28.0",
36
38
  "@opentelemetry/resources": "^1.28.0",
37
39
  "@opentelemetry/sdk-trace-base": "^1.28.0",
38
- "@opentelemetry/semantic-conventions": "^1.28.0",
39
- "zod": "^4.3.6"
40
+ "@opentelemetry/semantic-conventions": "^1.28.0"
40
41
  },
41
42
  "devDependencies": {
42
- "@bsb/base": "file:../../../nodejs",
43
+ "@bsb/base": "^9.0.0",
43
44
  "@types/node": "^22.10.5",
44
45
  "rimraf": "^6.0.1",
45
46
  "typescript": "^5.7.3"
46
47
  },
47
- "homepage": "https://io.bsbcode.dev/plugins/bsb/observable-zipkin"
48
+ "homepage": "https://io.bsbcode.dev/packages/nodejs/@bsb/observable-zipkin"
48
49
  }
49
-
@@ -33,38 +33,34 @@ import {
33
33
  BSBError
34
34
  } from "@bsb/base";
35
35
  import { DTrace, LogMeta } from "@bsb/base";
36
- import { z } from "zod";
36
+ import * as av from "@anyvali/js";
37
37
  import * as api from "@opentelemetry/api";
38
38
  import { Resource } from "@opentelemetry/resources";
39
39
  import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
40
40
  import { BasicTracerProvider, BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
41
41
  import { ZipkinExporter } from "@opentelemetry/exporter-zipkin";
42
42
 
43
- const ConfigSchema = z.object({
44
- serviceName: z.string().default("bsb-service"),
45
- serviceVersion: z.string().optional(),
46
-
47
- zipkin: z.object({
48
- url: z.string().url().default("http://localhost:9411/api/v2/spans"),
49
- headers: z.record(z.string(), z.string()).optional(),
50
- statusCodeTagName: z.string().default("http.status_code"),
51
- statusDescriptionTagName: z.string().default("http.status_text"),
52
- }),
53
-
54
- export: z.object({
55
- maxBatchSize: z.number().int().min(1).default(100),
56
- maxQueueSize: z.number().int().min(1).default(2048),
57
- scheduledDelayMillis: z.number().int().min(100).default(5000),
58
- }),
59
-
60
- resourceAttributes: z.record(z.string(), z.string()).default({}),
61
- samplingRate: z.number().min(0).max(1).default(1.0),
62
-
63
- console: z.object({
64
- enabled: z.boolean().default(true),
65
- logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
66
- }),
67
- });
43
+ const ConfigSchema = av.object({
44
+ serviceName: av.optional(av.string()).default("bsb-service"),
45
+ serviceVersion: av.optional(av.string()),
46
+ zipkin: av.object({
47
+ url: av.optional(av.string().format("url")).default("http://localhost:9411/api/v2/spans"),
48
+ headers: av.optional(av.record(av.string())),
49
+ statusCodeTagName: av.optional(av.string()).default("http.status_code"),
50
+ statusDescriptionTagName: av.optional(av.string()).default("http.status_text"),
51
+ }, { unknownKeys: "strip" }),
52
+ export: av.object({
53
+ maxBatchSize: av.optional(av.int32().min(1)).default(100),
54
+ maxQueueSize: av.optional(av.int32().min(1)).default(2048),
55
+ scheduledDelayMillis: av.optional(av.int32().min(100)).default(5000),
56
+ }, { unknownKeys: "strip" }),
57
+ resourceAttributes: av.optional(av.record(av.string())).default({}),
58
+ samplingRate: av.optional(av.number().min(0).max(1)).default(1.0),
59
+ console: av.object({
60
+ enabled: av.optional(av.bool()).default(true),
61
+ logLevel: av.optional(av.enum_(['debug', 'info', 'warn', 'error'])).default('info'),
62
+ }, { unknownKeys: "strip" }),
63
+ }, { unknownKeys: "strip" });
68
64
 
69
65
  export const Config = createConfigSchema(
70
66
  {
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
- "module": "commonjs",
4
+ "module": "NodeNext",
5
5
  "lib": ["ES2020"],
6
6
  "declaration": true,
7
7
  "outDir": "./lib",
@@ -10,7 +10,7 @@
10
10
  "esModuleInterop": true,
11
11
  "skipLibCheck": true,
12
12
  "forceConsistentCasingInFileNames": true,
13
- "moduleResolution": "node",
13
+ "moduleResolution": "NodeNext",
14
14
  "resolveJsonModule": true,
15
15
  "types": ["node"]
16
16
  },