@lad-tech/nsc-toolkit 1.27.0 → 1.28.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # [1.27.0](https://github.com/lad-tech/nsc-toolkit/compare/v1.26.2...v1.27.0) (2025-02-06)
1
+ ## [1.28.1](https://github.com/lad-tech/nsc-toolkit/compare/v1.28.0...v1.28.1) (2025-07-01)
2
2
 
3
3
 
4
- ### Features
4
+ ### Bug Fixes
5
5
 
6
- * New option for consumer ackPolicy ([#144](https://github.com/lad-tech/nsc-toolkit/issues/144)) ([0426f4e](https://github.com/lad-tech/nsc-toolkit/commit/0426f4e1da4ff092354f0e175d9ad9a295dfb074))
6
+ * Meter for batch consumer ([#147](https://github.com/lad-tech/nsc-toolkit/issues/147)) ([94a20b3](https://github.com/lad-tech/nsc-toolkit/commit/94a20b3b70caee64ac7a26998bc1019193c13516))
package/dist/Client.js CHANGED
@@ -10,6 +10,7 @@ const node_stream_1 = require("node:stream");
10
10
  const promises_1 = require("node:timers/promises");
11
11
  const Root_1 = require("./Root");
12
12
  const StreamManager_1 = require("./StreamManager");
13
+ const Meter_1 = require("./Meter");
13
14
  class Client extends Root_1.Root {
14
15
  constructor({ broker, events, loggerOutputFormatter, serviceName, baggage, cache, Ref }) {
15
16
  super(broker, loggerOutputFormatter);
@@ -35,6 +36,11 @@ class Client extends Root_1.Root {
35
36
  data = (0, nats_1.StringCodec)().decode(event.data);
36
37
  }
37
38
  const message = { data };
39
+ let baggage;
40
+ if (event.headers) {
41
+ baggage = this.getBaggageFromNATSHeader(event.headers);
42
+ }
43
+ message.meter = new Meter_1.Meter(eventName, baggage);
38
44
  if (this.isJsMessage(event)) {
39
45
  message.ack = event.ack.bind(event);
40
46
  message.nak = event.nak.bind(event);
@@ -45,6 +51,7 @@ class Client extends Root_1.Root {
45
51
  async startBatchWatch(fetcher, listener, eventName) {
46
52
  while (true) {
47
53
  const batch = [];
54
+ const baggages = [];
48
55
  const events = await fetcher.fetch();
49
56
  for await (const event of events) {
50
57
  let data;
@@ -58,9 +65,19 @@ class Client extends Root_1.Root {
58
65
  message.ack = event.ack.bind(event);
59
66
  message.nak = event.nak.bind(event);
60
67
  batch.push(message);
68
+ let baggage;
69
+ if (event.headers) {
70
+ baggage = this.getBaggageFromNATSHeader(event.headers);
71
+ if (baggage) {
72
+ baggages.push(baggage);
73
+ }
74
+ }
75
+ message.meter = new Meter_1.Meter(eventName, baggage);
76
+ }
77
+ if (batch.length > 0) {
78
+ const meter = new Meter_1.Meter(eventName, undefined, baggages);
79
+ listener.emit(eventName, batch, meter);
61
80
  }
62
- if (batch.length > 0)
63
- listener.emit(eventName, batch);
64
81
  }
65
82
  }
66
83
  getListener(serviceNameFrom, options) {
@@ -264,31 +281,23 @@ class Client extends Root_1.Root {
264
281
  request.end();
265
282
  });
266
283
  }
267
- convertBaggaggeToExternalHeader(baggage) {
268
- if (!baggage) {
269
- return {};
270
- }
271
- const headers = {};
272
- if (baggage.expired) {
273
- headers['nsc-expired'] = baggage.expired;
274
- }
275
- if (baggage.requestId) {
276
- headers['x-request-id'] = baggage.requestId;
277
- }
278
- if (baggage.traceId) {
279
- headers['nsc-trace-id'] = baggage.traceId;
280
- }
281
- if (baggage.spanId) {
282
- headers['nsc-span-id'] = baggage.spanId;
283
- }
284
- if (baggage.traceFlags) {
285
- headers['nsc-trace-flags'] = baggage.traceFlags;
286
- }
287
- return headers;
288
- }
289
284
  isJsMessage(message) {
290
285
  return !!message.ack && !!message.nak;
291
286
  }
287
+ getBaggageFromNATSHeader(headers) {
288
+ const traceId = headers.get('nsc-trace-id');
289
+ const spanId = headers.get('nsc-span-id');
290
+ const traceFlags = headers.has('nsc-trace-flags') ? +headers.get('nsc-trace-flags') : undefined;
291
+ const requestId = headers.has('x-request-id') ? String(headers.get('x-request-id')) : undefined;
292
+ if (traceId && spanId && traceFlags) {
293
+ return {
294
+ traceId,
295
+ spanId,
296
+ traceFlags,
297
+ requestId,
298
+ };
299
+ }
300
+ }
292
301
  }
293
302
  exports.Client = Client;
294
303
  //# sourceMappingURL=Client.js.map
package/dist/Meter.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Meter = void 0;
4
+ const interfaces_1 = require("./interfaces");
5
+ const opentelemetry = require("@opentelemetry/api");
6
+ const Root_1 = require("./Root");
7
+ const node_crypto_1 = require("node:crypto");
8
+ class Meter extends Root_1.Root {
9
+ constructor(name, baggage, links) {
10
+ super();
11
+ this.name = name;
12
+ this.baggage = baggage;
13
+ this.links = links;
14
+ this.SPAN_ID_BYTE_LENGTH = 8;
15
+ }
16
+ start() {
17
+ const tracer = opentelemetry.trace.getTracer('');
18
+ const links = [];
19
+ if (this.links && this.links.length) {
20
+ this.links.forEach(link => {
21
+ links.push({
22
+ context: { traceId: link.traceId, spanId: link.spanId, traceFlags: link.traceFlags },
23
+ });
24
+ });
25
+ }
26
+ if (!this.baggage && links.length) {
27
+ this.baggage = {
28
+ traceId: links[0].context.traceId,
29
+ spanId: (0, node_crypto_1.randomBytes)(this.SPAN_ID_BYTE_LENGTH).toString('hex'),
30
+ traceFlags: links[0].context.traceFlags,
31
+ };
32
+ }
33
+ const linksOption = links.length ? { links } : {};
34
+ this.span = tracer.startSpan(this.name, { kind: opentelemetry.SpanKind.CONSUMER, ...linksOption }, this.getContext(this.baggage));
35
+ }
36
+ end(error) {
37
+ if (!this.span) {
38
+ return;
39
+ }
40
+ if (error) {
41
+ this.span.setAttribute('error', true);
42
+ this.span.setAttribute('error.kind', error.message);
43
+ }
44
+ this.span.end();
45
+ }
46
+ measure(func, arg, context, tag) {
47
+ const tracer = opentelemetry.trace.getTracer('');
48
+ let spanContext;
49
+ if (this.span) {
50
+ spanContext = opentelemetry.trace.setSpan(opentelemetry.context.active(), this.span);
51
+ }
52
+ const options = { kind: opentelemetry.SpanKind.INTERNAL };
53
+ if ((tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.LOCATION]) === 'external') {
54
+ options.kind = opentelemetry.SpanKind.CLIENT;
55
+ }
56
+ const span = tracer.startSpan(func.name, options, spanContext);
57
+ this.applyTag(span, tag);
58
+ const result = func.apply(context, arg);
59
+ if (result.then) {
60
+ return result.then((result) => {
61
+ span.end();
62
+ return result;
63
+ }, (error) => {
64
+ span.setAttribute('error', true);
65
+ span.setAttribute('error.kind', error.message);
66
+ span.end();
67
+ throw error;
68
+ });
69
+ }
70
+ else {
71
+ span.end();
72
+ }
73
+ return result;
74
+ }
75
+ }
76
+ exports.Meter = Meter;
77
+ //# sourceMappingURL=Meter.js.map
package/dist/Root.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Root = void 0;
4
4
  const toolbelt_1 = require("@lad-tech/toolbelt");
5
5
  const opentelemetry = require("@opentelemetry/api");
6
+ const interfaces_1 = require("./interfaces");
6
7
  const Union_1 = require("./Union");
7
8
  class Root {
8
9
  constructor(broker, outputFormatter) {
@@ -52,7 +53,7 @@ class Root {
52
53
  return expired;
53
54
  }
54
55
  catch (error) {
55
- console.error(error);
56
+ this.logger.error(error);
56
57
  process.exit(1);
57
58
  }
58
59
  }
@@ -75,6 +76,45 @@ class Root {
75
76
  },
76
77
  };
77
78
  }
79
+ convertBaggaggeToExternalHeader(baggage) {
80
+ if (!baggage) {
81
+ return {};
82
+ }
83
+ const headers = {};
84
+ if (baggage.expired) {
85
+ headers['nsc-expired'] = baggage.expired;
86
+ }
87
+ if (baggage.requestId) {
88
+ headers['x-request-id'] = baggage.requestId;
89
+ }
90
+ if (baggage.traceId) {
91
+ headers['nsc-trace-id'] = baggage.traceId;
92
+ }
93
+ if (baggage.spanId) {
94
+ headers['nsc-span-id'] = baggage.spanId;
95
+ }
96
+ if (baggage.traceFlags) {
97
+ headers['nsc-trace-flags'] = baggage.traceFlags;
98
+ }
99
+ return headers;
100
+ }
101
+ applyTag(span, tag) {
102
+ if (!tag) {
103
+ return;
104
+ }
105
+ if ((tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.TYPE]) === 'dbms') {
106
+ span.setAttribute('db.system', tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.NAME]);
107
+ if (tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.TARGET]) {
108
+ span.setAttribute('db.name', tag[interfaces_1.TagKey.TARGET]);
109
+ }
110
+ }
111
+ if ((tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.TYPE]) === 'api') {
112
+ span.setAttribute('net.peer.name', tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.NAME]);
113
+ if (tag === null || tag === void 0 ? void 0 : tag[interfaces_1.TagKey.TARGET]) {
114
+ span.setAttribute('http.target', tag[interfaces_1.TagKey.TARGET]);
115
+ }
116
+ }
117
+ }
78
118
  }
79
119
  exports.Root = Root;
80
120
  //# sourceMappingURL=Root.js.map
package/dist/Service.js CHANGED
@@ -44,11 +44,12 @@ class Service extends Root_1.Root {
44
44
  if (options.events) {
45
45
  const events = Object.keys(options.events.list);
46
46
  this.emitter = events.reduce((result, eventName) => {
47
- result[eventName] = ((params, uniqId, rollupId) => {
47
+ result[eventName] = ((params, uniqId, rollupId, external) => {
48
48
  var _a, _b, _c;
49
49
  const subject = [options.name];
50
50
  const eventOptions = (_a = options.events) === null || _a === void 0 ? void 0 : _a.list[eventName];
51
- if ((_b = eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.options) === null || _b === void 0 ? void 0 : _b.stream) {
51
+ const isStream = (_b = eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.options) === null || _b === void 0 ? void 0 : _b.stream;
52
+ if (isStream) {
52
53
  const prefix = (_c = options.events) === null || _c === void 0 ? void 0 : _c.streamOptions.prefix;
53
54
  if (!prefix) {
54
55
  throw new Error(`Stream prefix not set for event ${String(eventName)} marked as stream`);
@@ -61,14 +62,32 @@ class Service extends Root_1.Root {
61
62
  settings = { headers: (0, nats_1.headers)() };
62
63
  settings.headers.append(this.UNIQ_ID_HEADER, uniqId);
63
64
  }
64
- if (rollupId) {
65
+ if (rollupId && isStream) {
65
66
  settings = settings !== null && settings !== void 0 ? settings : { headers: (0, nats_1.headers)() };
66
67
  settings.headers.append(this.ROLLUP_HEADER, this.ROLLUP_STRATEGY);
67
68
  subject.push(rollupId);
68
69
  }
69
- else {
70
+ else if (rollupId && !isStream) {
71
+ this.logger.warn(`${String(eventName)}. Rollup is available only for streams`);
72
+ }
73
+ else if (isStream) {
70
74
  subject.push(this.BASE_EVENT_SUFFIX);
71
75
  }
76
+ if (external) {
77
+ const baggage = this.getBaggageFromExternalHeader(external);
78
+ const tracer = api_1.trace.getTracer('');
79
+ const context = this.getContext(this.isBaggageContainTrace(baggage) ? baggage : undefined);
80
+ const span = tracer.startSpan(String(eventName), { kind: api_1.SpanKind.PRODUCER }, context);
81
+ const eventSpanContext = span.spanContext();
82
+ const eventHeader = this.convertBaggaggeToExternalHeader(eventSpanContext);
83
+ if (!settings) {
84
+ settings = { headers: (0, nats_1.headers)() };
85
+ }
86
+ for (const [key, value] of Object.entries(eventHeader)) {
87
+ settings.headers.append(key, `${value}`);
88
+ }
89
+ span.end();
90
+ }
72
91
  this.broker.publish(subject.join('.'), this.buildMessage(params), settings);
73
92
  });
74
93
  return result;
@@ -97,41 +116,42 @@ class Service extends Root_1.Root {
97
116
  provider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(exporter));
98
117
  provider.register();
99
118
  }
100
- finishSpan(span, error) {
119
+ finishSpan(span, error, tag) {
101
120
  if (error) {
102
121
  span.setAttribute('error', true);
103
122
  span.setAttribute('error.kind', error.message);
104
123
  }
124
+ this.applyTag(span, tag);
105
125
  span.end();
106
126
  }
107
127
  /**
108
128
  * Wrapper for async methods. Create span
109
129
  */
110
- perform(func, funcContext, arg, tracer, context) {
130
+ perform(func, funcContext, arg, tracer, context, tag) {
111
131
  const span = tracer.startSpan(func.name, undefined, context);
112
132
  try {
113
133
  const result = func.apply(funcContext, arg);
114
134
  if (result.then) {
115
135
  return result.then((result) => {
116
- this.finishSpan(span);
136
+ this.finishSpan(span, undefined, tag);
117
137
  return result;
118
138
  }, (error) => {
119
- this.finishSpan(span, error);
139
+ this.finishSpan(span, error, tag);
120
140
  throw error;
121
141
  });
122
142
  }
123
- this.finishSpan(span);
143
+ this.finishSpan(span, undefined, tag);
124
144
  return result;
125
145
  }
126
146
  catch (error) {
127
- this.finishSpan(span, error);
147
+ this.finishSpan(span, error, tag);
128
148
  throw error;
129
149
  }
130
150
  }
131
151
  /**
132
152
  * Build trap for object with async methods
133
153
  */
134
- getTrap(instance, tracer, baggage) {
154
+ getTrap(instance, tracer, baggage, tag) {
135
155
  const perform = this.perform.bind(this);
136
156
  const context = this.getContext(baggage);
137
157
  return {
@@ -139,7 +159,7 @@ class Service extends Root_1.Root {
139
159
  const method = Reflect.get(target, propKey, receiver);
140
160
  if (typeof method === 'function') {
141
161
  return function (...args) {
142
- return perform(method, instance, args, tracer, context);
162
+ return perform(method, instance, args, tracer, context, tag);
143
163
  };
144
164
  }
145
165
  else {
@@ -154,11 +174,13 @@ class Service extends Root_1.Root {
154
174
  createObjectWithDependencies(method, tracer, baggage) {
155
175
  const services = _1.ServiceContainer.get(method.settings.action) || new Map();
156
176
  const instances = _1.InstanceContainer.get(method.settings.action) || new Map();
177
+ const tags = new Map();
157
178
  const dependences = { [_1.ConstructorDependencyKey]: [] };
158
179
  const dependencyStorage = Reflect.getMetadata(_1.dependencyStorageMetaKey, method);
159
180
  if (dependencyStorage && dependencyStorage.size) {
160
181
  // for constructor
161
182
  dependencyStorage.forEach((dependencyKey, propertyName) => {
183
+ var _a;
162
184
  if (Array.isArray(dependencyKey)) {
163
185
  if (propertyName === _1.ConstructorDependencyKey) {
164
186
  dependencyKey.forEach((item, index) => {
@@ -184,6 +206,9 @@ class Service extends Root_1.Root {
184
206
  }
185
207
  if (dependency.type === _1.DependencyType.ADAPTER) {
186
208
  instances.set(propertyName, _1.container.getInstance(dependencyKey));
209
+ if ((_a = dependency.options) === null || _a === void 0 ? void 0 : _a.tag) {
210
+ tags.set(propertyName, dependency.options.tag);
211
+ }
187
212
  }
188
213
  if (dependency.type === _1.DependencyType.CONSTANT) {
189
214
  dependences[propertyName] = dependency.value;
@@ -197,7 +222,7 @@ class Service extends Root_1.Root {
197
222
  }
198
223
  if (instances.size) {
199
224
  instances.forEach((instance, key) => {
200
- const trap = this.getTrap(instance, tracer, baggage);
225
+ const trap = this.getTrap(instance, tracer, baggage, tags.get(key));
201
226
  dependences[key] = new Proxy(instance, trap);
202
227
  });
203
228
  }
@@ -231,7 +256,7 @@ class Service extends Root_1.Root {
231
256
  * If there is no baggage. For example, in HTTP Gateway
232
257
  */
233
258
  getRootBaggage(subject, headers, ownTimeout) {
234
- const baggage = headers ? this.getBaggageFromHTTPHeader(headers) : undefined;
259
+ const baggage = headers ? this.getBaggageFromExternalHeader(headers) : undefined;
235
260
  const tracer = api_1.trace.getTracer('');
236
261
  const context = this.getContext(this.isBaggageContainTrace(baggage) ? baggage : undefined);
237
262
  const span = tracer.startSpan(subject, undefined, context);
@@ -328,7 +353,7 @@ class Service extends Root_1.Root {
328
353
  if (other.length || wrongServiceName || !Method) {
329
354
  throw new Error('Wrong url or service name or action');
330
355
  }
331
- const baggage = this.getBaggageFromHTTPHeader(request.headers);
356
+ const baggage = this.getBaggageFromExternalHeader(request.headers);
332
357
  if ((_b = (_a = Method.settings.options) === null || _a === void 0 ? void 0 : _a.useStream) === null || _b === void 0 ? void 0 : _b.request) {
333
358
  const result = await this.handled(request, Method, baggage);
334
359
  if (Method.settings.options.useStream.response && result.payload instanceof node_stream_1.Readable) {
@@ -373,11 +398,12 @@ class Service extends Root_1.Root {
373
398
  metadata: baggage,
374
399
  outputFormatter: this.options.loggerOutputFormatter,
375
400
  });
401
+ const nextBaggage = this.getNextBaggage(span, baggage);
376
402
  try {
377
- const requestedDependencies = this.createObjectWithDependencies(Method, tracer, this.getNextBaggage(span, baggage));
403
+ const requestedDependencies = this.createObjectWithDependencies(Method, tracer, nextBaggage);
378
404
  const context = this.createMethodContext(Method, requestedDependencies);
379
405
  context['logger'] = logger;
380
- context['emitter'] = this.emitter;
406
+ context['emitter'] = this.getWrappedEmitter(nextBaggage);
381
407
  const response = await context.handler.call(context, payload);
382
408
  const result = {
383
409
  payload: response,
@@ -393,6 +419,28 @@ class Service extends Root_1.Root {
393
419
  return this.buildErrorMessage(error);
394
420
  }
395
421
  }
422
+ /**
423
+ * Wrap emitter for luggage baggagge
424
+ */
425
+ getWrappedEmitter(baggage) {
426
+ if (!baggage) {
427
+ return this.emitter;
428
+ }
429
+ const externalBaggage = this.convertBaggaggeToExternalHeader(baggage);
430
+ return new Proxy(this.emitter, {
431
+ get(target, propKey, receiver) {
432
+ const event = Reflect.get(target, propKey, receiver);
433
+ if (typeof event === 'function') {
434
+ return (params, uniqId, rollupId, userExternalBaggage) => {
435
+ return event(params, uniqId, rollupId, userExternalBaggage !== null && userExternalBaggage !== void 0 ? userExternalBaggage : externalBaggage);
436
+ };
437
+ }
438
+ else {
439
+ return event;
440
+ }
441
+ },
442
+ });
443
+ }
396
444
  /**
397
445
  * Make error object if error instance of Error object for logger
398
446
  */
@@ -607,7 +655,7 @@ class Service extends Root_1.Root {
607
655
  port: this.httpPort,
608
656
  };
609
657
  }
610
- getBaggageFromHTTPHeader(headers) {
658
+ getBaggageFromExternalHeader(headers) {
611
659
  const expired = headers['nsc-expired'] ? +headers['nsc-expired'] : undefined;
612
660
  const traceId = headers['nsc-trace-id'];
613
661
  const spanId = headers['nsc-span-id'];
@@ -1,10 +1,16 @@
1
1
  "use strict";
2
2
  // COMMON
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DependencyType = void 0;
4
+ exports.TagKey = exports.DependencyType = void 0;
5
5
  exports.DependencyType = {
6
6
  SERVICE: 'service',
7
7
  ADAPTER: 'adapter',
8
8
  CONSTANT: 'constant', // Just an object
9
9
  };
10
+ exports.TagKey = {
11
+ LOCATION: 'location',
12
+ TYPE: 'type',
13
+ NAME: 'name',
14
+ TARGET: 'target',
15
+ };
10
16
  //# sourceMappingURL=interfaces.js.map
@@ -26,7 +26,7 @@ export declare class Client<E extends Emitter = Emitter> extends Root {
26
26
  private isStream;
27
27
  private makeBrokerRequest;
28
28
  private makeHttpRequest;
29
- private convertBaggaggeToExternalHeader;
30
29
  private isJsMessage;
30
+ private getBaggageFromNATSHeader;
31
31
  }
32
32
  export {};
@@ -1,12 +1,14 @@
1
- import { ClientService, DependencyType, InitializableService } from '.';
1
+ import { ClientService, DependencyType, InitializableService, Tag } from '.';
2
2
  type Constant = Record<string, any>;
3
3
  type Service<R extends Constant = Constant> = ClientService<R>;
4
4
  export type Adapter<R extends Constant = Constant> = new (...args: any[]) => R;
5
5
  export type Singlton = {
6
6
  singlton: true;
7
+ tag?: Tag;
7
8
  };
8
9
  export type NeedInit = {
9
10
  init: true;
11
+ tag?: Tag;
10
12
  };
11
13
  export type AdapterOptions = Singlton | NeedInit;
12
14
  type Dependency = Service | Adapter | Constant;
@@ -0,0 +1,13 @@
1
+ import { Baggage, EventMeter, Tag } from './interfaces';
2
+ import { Root } from './Root';
3
+ export declare class Meter extends Root implements EventMeter {
4
+ private name;
5
+ private baggage?;
6
+ private links?;
7
+ private span?;
8
+ private readonly SPAN_ID_BYTE_LENGTH;
9
+ constructor(name: string, baggage?: Baggage | undefined, links?: Baggage[] | undefined);
10
+ start(): void;
11
+ end(error?: Error): void;
12
+ measure<T extends (...args: any[]) => any>(func: T, arg: Parameters<T>, context: unknown, tag?: Tag): ReturnType<T>;
13
+ }
@@ -1,7 +1,7 @@
1
1
  import { Logs } from '@lad-tech/toolbelt';
2
2
  import * as opentelemetry from '@opentelemetry/api';
3
3
  import type { NatsConnection } from 'nats';
4
- import type { Baggage } from './interfaces';
4
+ import { type Baggage, type ExternalBaggage, type Tag } from './interfaces';
5
5
  import { Broker } from './Union';
6
6
  export declare class Root {
7
7
  protected readonly SERVICE_SUBJECT_FOR_GET_HTTP_SETTINGS = "get_http_settings";
@@ -24,4 +24,6 @@ export declare class Root {
24
24
  code: number | undefined;
25
25
  };
26
26
  };
27
+ protected convertBaggaggeToExternalHeader(baggage?: Partial<Baggage>): ExternalBaggage;
28
+ protected applyTag(span: opentelemetry.Span, tag?: Tag): void;
27
29
  }
@@ -88,6 +88,10 @@ export declare class Service<E extends Emitter = Emitter> extends Root {
88
88
  * Run business logic for request
89
89
  */
90
90
  private handled;
91
+ /**
92
+ * Wrap emitter for luggage baggagge
93
+ */
94
+ private getWrappedEmitter;
91
95
  /**
92
96
  * Make error object if error instance of Error object for logger
93
97
  */
@@ -132,5 +136,5 @@ export declare class Service<E extends Emitter = Emitter> extends Root {
132
136
  private upHTTPServer;
133
137
  private getMyIpV4;
134
138
  private getHttpSettings;
135
- private getBaggageFromHTTPHeader;
139
+ private getBaggageFromExternalHeader;
136
140
  }
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
+ /// <reference types="node" />
3
4
  import { Logs } from '@lad-tech/toolbelt';
4
5
  import { Transform, TransformCallback, TransformOptions } from 'stream';
5
6
  export declare class BufferToJsonTransform<T = any> extends Transform {
@@ -2,7 +2,7 @@
2
2
  import { Closed, ConsumerInfoable, Destroyable, Msg, NatsError, Subscription } from 'nats';
3
3
  import { PassThrough } from 'node:stream';
4
4
  export declare class UnionSubscription extends PassThrough implements Subscription, Destroyable, Closed, ConsumerInfoable {
5
- closed: Promise<void>;
5
+ closed: any;
6
6
  unsubscribe(max?: number): void;
7
7
  drain(): Promise<void>;
8
8
  isDraining(): boolean;
@@ -85,10 +85,12 @@ export interface StreamManagerParam {
85
85
  }
86
86
  export interface EmitterEvent<D extends Record<string, any>> {
87
87
  data: D;
88
+ meter: EventMeter;
88
89
  }
89
90
  export interface EmitterStreamEvent<D extends Record<string, any>> extends EmitterEvent<D> {
90
91
  ack: () => void;
91
92
  nak: (millis: number) => void;
93
+ meter: EventMeter;
92
94
  }
93
95
  export interface StreamAction {
94
96
  action: string;
@@ -136,7 +138,7 @@ export interface Listener<E extends Emitter> {
136
138
  off<A extends keyof E>(action: A, handler: E[A]): void;
137
139
  }
138
140
  export interface ListenerBatch<E extends Emitter> {
139
- on<A extends keyof E>(action: A, handler: (params: Array<Parameters<E[A]>[0]>) => void): void;
141
+ on<A extends keyof E>(action: A, handler: (params: Array<Parameters<E[A]>[0]>, meter: EventMeter) => void): void;
140
142
  off<A extends keyof E>(action: A, handler: (params: Array<Parameters<E[A]>[0]>) => void): void;
141
143
  }
142
144
  export interface HttpSettings {
@@ -157,3 +159,23 @@ export declare const DependencyType: {
157
159
  readonly ADAPTER: "adapter";
158
160
  readonly CONSTANT: "constant";
159
161
  };
162
+ export type TagKey = typeof TagKey[keyof typeof TagKey];
163
+ export declare const TagKey: {
164
+ readonly LOCATION: "location";
165
+ readonly TYPE: "type";
166
+ readonly NAME: "name";
167
+ readonly TARGET: "target";
168
+ };
169
+ export type LocationTagValue = 'internal' | 'external';
170
+ export type TypeTagValue = 'dbms' | 'api';
171
+ export type Tag = {
172
+ [TagKey.LOCATION]: LocationTagValue;
173
+ [TagKey.TYPE]: TypeTagValue;
174
+ [TagKey.NAME]: string;
175
+ [TagKey.TARGET]?: string;
176
+ };
177
+ export interface EventMeter {
178
+ start(): void;
179
+ end(): void;
180
+ measure<T extends (...args: any[]) => any>(func: T, arg: Parameters<T>, context: any, tag?: Tag): ReturnType<T>;
181
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lad-tech/nsc-toolkit",
3
- "version": "1.27.0",
3
+ "version": "1.28.1",
4
4
  "description": "Toolkit for create microservices around NATS",
5
5
  "main": "dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "@semantic-release/changelog": "^6.0.2",
18
18
  "@semantic-release/npm": "^9.0.1",
19
19
  "@types/jest": "^27.5.2",
20
- "@types/node": "^17.0.42",
20
+ "@types/node": "^22.13.13",
21
21
  "eslint": "^7.32.0",
22
22
  "eslint-config-airbnb-base": "^15.0.0",
23
23
  "eslint-config-prettier": "^8.5.0",
@@ -41,7 +41,7 @@
41
41
  "@opentelemetry/sdk-trace-base": "^1.3.1",
42
42
  "@opentelemetry/semantic-conventions": "^1.3.1",
43
43
  "ajv": "^8.11.0",
44
- "nats": "^2.28.2",
44
+ "nats": "^2.29.3",
45
45
  "reflect-metadata": "^0.1.13"
46
46
  },
47
47
  "peerDependencies": {