rian 0.0.2-alpha.10 → 0.0.2-alpha.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ import * as rian from 'rian';
2
+
3
+ interface Config {
4
+ onRequest(payload: any): void;
5
+ }
6
+ declare const exporter: (config: Config) => rian.Exporter;
7
+
8
+ export { Config, exporter };
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ const package_json = require('rian/package.json');
4
+
5
+ const SpanStatusCode_UNSET = 0;
6
+ const SpanStatusCode_ERROR = 2;
7
+ const convert_value_to_anyvalue = (value) => {
8
+ let type = typeof value, any_value = {};
9
+ if (type === 'string')
10
+ any_value.stringValue = value;
11
+ else if (type === 'number')
12
+ if (Number.isInteger(value))
13
+ any_value.intValue = value;
14
+ else
15
+ any_value.doubleValue = value;
16
+ else if (type === 'boolean')
17
+ any_value.boolValue = value;
18
+ else if (Array.isArray(value))
19
+ any_value.arrayValue = {
20
+ values: value.map((i) => convert_value_to_anyvalue(i)),
21
+ };
22
+ else
23
+ any_value.kvlistValue = { values: convert_object_to_kv(value) };
24
+ return any_value;
25
+ };
26
+ const convert_object_to_kv = (input) => {
27
+ const value = [];
28
+ for (let key of Object.keys(input)) {
29
+ value.push({
30
+ key,
31
+ value: convert_value_to_anyvalue(input[key]),
32
+ });
33
+ }
34
+ return value;
35
+ };
36
+ // https://github.com/open-telemetry/opentelemetry-proto/blob/b43e9b18b76abf3ee040164b55b9c355217151f3/opentelemetry/proto/trace/v1/trace.proto#L127-L155
37
+ const map_kind = (kind) => {
38
+ switch (kind) {
39
+ default:
40
+ case 'INTERNAL': {
41
+ return 1;
42
+ }
43
+ case 'SERVER': {
44
+ return 2;
45
+ }
46
+ case 'CLIENT': {
47
+ return 3;
48
+ }
49
+ case 'PRODUCER': {
50
+ return 4;
51
+ }
52
+ case 'CONSUMER': {
53
+ return 5;
54
+ }
55
+ }
56
+ };
57
+ const exporter = (config) => (spans, context) => {
58
+ const otel_spans = [];
59
+ for (let span of spans) {
60
+ const kind = span.context.kind;
61
+ delete span.context.kind;
62
+ let status;
63
+ if ('error' in span.context) {
64
+ status = {
65
+ code: SpanStatusCode_ERROR,
66
+ };
67
+ if ('message' in span.context.error) {
68
+ status.message = span.context.error.message;
69
+ }
70
+ delete span.context.error;
71
+ }
72
+ otel_spans.push({
73
+ traceId: span.id.trace_id,
74
+ spanId: span.id.parent_id,
75
+ parentSpanId: span.parent?.parent_id,
76
+ name: span.name,
77
+ kind: map_kind(kind || 'INTERNAL'),
78
+ startTimeUnixNano: span.start * 1000000,
79
+ endTimeUnixNano: span.end ? span.end * 1000000 : undefined,
80
+ droppedAttributesCount: 0,
81
+ droppedEventsCount: 0,
82
+ droppedLinksCount: 0,
83
+ attributes: convert_object_to_kv(span.context),
84
+ status: status || { code: SpanStatusCode_UNSET },
85
+ });
86
+ }
87
+ return config.onRequest({
88
+ resourceSpans: [
89
+ {
90
+ resource: {
91
+ attributes: convert_object_to_kv(context),
92
+ droppedAttributesCount: 0,
93
+ },
94
+ instrumentationLibrarySpans: [
95
+ {
96
+ instrumentationLibrary: {
97
+ name: package_json.name,
98
+ version: package_json.version,
99
+ },
100
+ spans: otel_spans,
101
+ },
102
+ ],
103
+ },
104
+ ],
105
+ });
106
+ };
107
+
108
+ exports.exporter = exporter;
@@ -0,0 +1,106 @@
1
+ import { name, version } from 'rian/package.json';
2
+
3
+ const SpanStatusCode_UNSET = 0;
4
+ const SpanStatusCode_ERROR = 2;
5
+ const convert_value_to_anyvalue = (value) => {
6
+ let type = typeof value, any_value = {};
7
+ if (type === 'string')
8
+ any_value.stringValue = value;
9
+ else if (type === 'number')
10
+ if (Number.isInteger(value))
11
+ any_value.intValue = value;
12
+ else
13
+ any_value.doubleValue = value;
14
+ else if (type === 'boolean')
15
+ any_value.boolValue = value;
16
+ else if (Array.isArray(value))
17
+ any_value.arrayValue = {
18
+ values: value.map((i) => convert_value_to_anyvalue(i)),
19
+ };
20
+ else
21
+ any_value.kvlistValue = { values: convert_object_to_kv(value) };
22
+ return any_value;
23
+ };
24
+ const convert_object_to_kv = (input) => {
25
+ const value = [];
26
+ for (let key of Object.keys(input)) {
27
+ value.push({
28
+ key,
29
+ value: convert_value_to_anyvalue(input[key]),
30
+ });
31
+ }
32
+ return value;
33
+ };
34
+ // https://github.com/open-telemetry/opentelemetry-proto/blob/b43e9b18b76abf3ee040164b55b9c355217151f3/opentelemetry/proto/trace/v1/trace.proto#L127-L155
35
+ const map_kind = (kind) => {
36
+ switch (kind) {
37
+ default:
38
+ case 'INTERNAL': {
39
+ return 1;
40
+ }
41
+ case 'SERVER': {
42
+ return 2;
43
+ }
44
+ case 'CLIENT': {
45
+ return 3;
46
+ }
47
+ case 'PRODUCER': {
48
+ return 4;
49
+ }
50
+ case 'CONSUMER': {
51
+ return 5;
52
+ }
53
+ }
54
+ };
55
+ const exporter = (config) => (spans, context) => {
56
+ const otel_spans = [];
57
+ for (let span of spans) {
58
+ const kind = span.context.kind;
59
+ delete span.context.kind;
60
+ let status;
61
+ if ('error' in span.context) {
62
+ status = {
63
+ code: SpanStatusCode_ERROR,
64
+ };
65
+ if ('message' in span.context.error) {
66
+ status.message = span.context.error.message;
67
+ }
68
+ delete span.context.error;
69
+ }
70
+ otel_spans.push({
71
+ traceId: span.id.trace_id,
72
+ spanId: span.id.parent_id,
73
+ parentSpanId: span.parent?.parent_id,
74
+ name: span.name,
75
+ kind: map_kind(kind || 'INTERNAL'),
76
+ startTimeUnixNano: span.start * 1000000,
77
+ endTimeUnixNano: span.end ? span.end * 1000000 : undefined,
78
+ droppedAttributesCount: 0,
79
+ droppedEventsCount: 0,
80
+ droppedLinksCount: 0,
81
+ attributes: convert_object_to_kv(span.context),
82
+ status: status || { code: SpanStatusCode_UNSET },
83
+ });
84
+ }
85
+ return config.onRequest({
86
+ resourceSpans: [
87
+ {
88
+ resource: {
89
+ attributes: convert_object_to_kv(context),
90
+ droppedAttributesCount: 0,
91
+ },
92
+ instrumentationLibrarySpans: [
93
+ {
94
+ instrumentationLibrary: {
95
+ name: name,
96
+ version: version,
97
+ },
98
+ spans: otel_spans,
99
+ },
100
+ ],
101
+ },
102
+ ],
103
+ });
104
+ };
105
+
106
+ export { exporter };
@@ -0,0 +1,8 @@
1
+ import * as rian from 'rian';
2
+
3
+ interface Config {
4
+ onRequest(payload: any): void;
5
+ }
6
+ declare const exporter: (config: Config) => rian.Exporter;
7
+
8
+ export { Config, exporter };
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const flattie = require('flattie');
4
+
5
+ const exporter = (config) => (spans, context) => {
6
+ const zipkin = [];
7
+ for (let span of spans) {
8
+ const kind = span.context.kind;
9
+ delete span.context.kind;
10
+ if ('error' in span.context) {
11
+ const error = span.context.error;
12
+ if ('message' in error) {
13
+ span.context.error = {
14
+ name: error.name,
15
+ message: error.message,
16
+ stack: error.stack,
17
+ };
18
+ }
19
+ else {
20
+ span.context.error = true;
21
+ }
22
+ }
23
+ zipkin.push({
24
+ id: span.id.parent_id,
25
+ traceId: span.id.trace_id,
26
+ parentId: span.parent?.parent_id,
27
+ name: span.name,
28
+ kind: kind === 'INTERNAL' ? undefined : kind,
29
+ timestamp: span.start * 1000,
30
+ duration: span.end ? (span.end - span.start) * 1000 : undefined,
31
+ localEndpoint: context.localEndpoint,
32
+ tags: flattie.flattie(Object.assign({}, context, span.context), '.', true),
33
+ });
34
+ }
35
+ return config.onRequest(zipkin);
36
+ };
37
+
38
+ exports.exporter = exporter;
@@ -0,0 +1,36 @@
1
+ import { flattie } from 'flattie';
2
+
3
+ const exporter = (config) => (spans, context) => {
4
+ const zipkin = [];
5
+ for (let span of spans) {
6
+ const kind = span.context.kind;
7
+ delete span.context.kind;
8
+ if ('error' in span.context) {
9
+ const error = span.context.error;
10
+ if ('message' in error) {
11
+ span.context.error = {
12
+ name: error.name,
13
+ message: error.message,
14
+ stack: error.stack,
15
+ };
16
+ }
17
+ else {
18
+ span.context.error = true;
19
+ }
20
+ }
21
+ zipkin.push({
22
+ id: span.id.parent_id,
23
+ traceId: span.id.trace_id,
24
+ parentId: span.parent?.parent_id,
25
+ name: span.name,
26
+ kind: kind === 'INTERNAL' ? undefined : kind,
27
+ timestamp: span.start * 1000,
28
+ duration: span.end ? (span.end - span.start) * 1000 : undefined,
29
+ localEndpoint: context.localEndpoint,
30
+ tags: flattie(Object.assign({}, context, span.context), '.', true),
31
+ });
32
+ }
33
+ return config.onRequest(zipkin);
34
+ };
35
+
36
+ export { exporter };
package/index.d.ts CHANGED
@@ -1,37 +1,142 @@
1
1
  import { Traceparent } from 'tctx';
2
+ import { Scope as Scope$1 } from 'rian';
2
3
 
3
- declare type Span = {
4
+ declare type MeasureFn = ((...args: [...args: any[]]) => any) | ((...args: [...args: any[], scope: Scope$1]) => any);
5
+ declare type RealMeasureFnParams<T extends unknown[]> = T extends [] ? [] : T extends [...rest: infer U, scope: Scope$1] ? U : T;
6
+
7
+ /**
8
+ * Spans are units within a distributed trace. Spans encapsulate mainly 3 pieces of information, a
9
+ * {@link Span.name|name}, and a {@link Span.start|start} and {@link Span.end|end} time.
10
+ *
11
+ * Each span should be named, not too vague, and not too precise. For example, "resolve_user_ids"
12
+ * and not "resolver_user_ids[1,2,3]" nor "resolve".
13
+ *
14
+ * A span forms part of a wider trace, and can be visualized like:
15
+ *
16
+ * ```plain
17
+ * [Span A················································(2ms)]
18
+ * [Span B·········································(1.7ms)]
19
+ * [Span D···············(0.8ms)] [Span C......(0.6ms)]
20
+ * ```
21
+ *
22
+ * ---
23
+ *
24
+ * Spans are aimed to interoperate with
25
+ * {@link https://github.com/opentracing/specification/blob/master/specification.md|OpenTracing's Spans}, albeit not entirely api compatible — they do share principles.
26
+ */
27
+ interface Span {
28
+ /**
29
+ * A human-readable name for this span. For example the function name, the name of a subtask,
30
+ * or stage of the larger stack.
31
+ *
32
+ * @example
33
+ * "resolve_user_ids"
34
+ * "[POST] /api"
35
+ */
4
36
  name: string;
37
+ /**
38
+ * A w3c trace context compatible id for this span. Will .toString() into an injectable header.
39
+ *
40
+ * @see https://www.w3.org/TR/trace-context/#traceparent-header
41
+ * @see https://github.com/maraisr/tctx
42
+ */
5
43
  id: Traceparent;
44
+ /**
45
+ * Is the id of rhe parent if this is not the parent {@link Span}.
46
+ *
47
+ * @see {@link Span.id}
48
+ */
6
49
  parent?: Traceparent;
50
+ /**
51
+ * The time represented as a UNIX epoch timestamp in milliseconds when this span was created.
52
+ * Typically, via
53
+ * {@link Scope.fork|tracer.fork()}.
54
+ */
7
55
  start: number;
8
- end: number;
56
+ /**
57
+ * The UNIX epoch timestamp in milliseconds when the span ended, or undefined if ending was not
58
+ * captured during the current trace. Time should then be assumed as current time.
59
+ */
60
+ end?: number;
61
+ /**
62
+ * An arbitrary context object useful for storing information during a trace.
63
+ *
64
+ * Usually following a convention such as `tag.*`, `http.*` or any of the
65
+ * {@link https://github.com/opentracing/specification/blob/master/semantic_conventions.md|Semantic Conventions outlined by OpenTracing}.
66
+ *
67
+ * ### Note!
68
+ *
69
+ * There are a few keys with "powers"
70
+ *
71
+ * - `kind` when set will coerce into the exports scheme, aka INTERNAL in zipkin will be
72
+ * `"INTERNAL"`, or `1` in otel
73
+ * - `error` when set, will be assumed to be an `Error` instance, and thus its `.message` wil
74
+ * exist as `error.message` in zipkin, and `status: 2` in otel.
75
+ */
9
76
  context: Context;
10
- };
11
- declare type Collector = (spans: ReadonlySet<Span>) => any;
12
- declare type Context = {
77
+ }
78
+ /**
79
+ * An exporter is a method called when the parent scope ends, gets given a Set of all spans traced
80
+ * during this execution.
81
+ */
82
+ declare type Exporter = (spans: ReadonlySet<Span>, context: Context) => any;
83
+ /**
84
+ * @borrows {@link Span.context}
85
+ */
86
+ interface Context {
13
87
  [property: string]: any;
14
- };
15
- declare type Options = {
16
- collector: Collector;
88
+ }
89
+ /**
90
+ * Should return true when you want to sample the span, this is ran before the span is traced — so
91
+ * decisions is made preemptively.
92
+ *
93
+ * The Span itself will still be included in the {@link Options.exporter|exporter}, and can be
94
+ * filtered out there.
95
+ *
96
+ * Sampling does impact the traceparent, for injection — and is encoded there.
97
+ */
98
+ declare type Sampler = (name: string, parentId?: Traceparent, context?: Context) => boolean;
99
+ interface Options {
100
+ /**
101
+ * @borrows {@link Exporter}
102
+ */
103
+ exporter: Exporter;
104
+ /**
105
+ * @borrows {@link Sampler}
106
+ */
107
+ sampler?: Sampler;
108
+ context?: Context;
109
+ /**
110
+ * A root, or extracted w3c traceparent stringed header.
111
+ *
112
+ * If the id is malformed, the {@link create} method will throw an exception. If no root is
113
+ * provided then one will be created obeying the {@link Options.sampler|sampling} rules.
114
+ */
17
115
  traceparent?: string;
18
- };
19
- declare type OmitScopeParam<T extends unknown[]> = T extends [] ? [] : T extends [infer H, ...infer R] ? H extends Scope ? OmitScopeParam<R> : [H, ...OmitScopeParam<R>] : T;
116
+ }
20
117
  interface CallableScope extends Scope {
21
118
  (cb: (scope: Omit<Scope, 'end'>) => void): ReturnType<typeof cb>;
22
119
  }
23
120
  interface Scope {
24
121
  traceparent: Traceparent;
25
- fork(name: string, traceparent?: Traceparent): CallableScope;
26
- measure<Fn extends (...args: any[]) => any, Params extends Parameters<Fn>>(name: string, fn: Fn, // TODO Fix types here
27
- ...args: OmitScopeParam<Params>): ReturnType<Fn>;
122
+ fork(name: string): CallableScope;
123
+ measure<Fn extends MeasureFn>(name: string, fn: Fn, // TODO: fn doesnt see scope correctly
124
+ ...args: RealMeasureFnParams<Parameters<Fn>>): ReturnType<Fn>;
28
125
  set_context(contextFn: (context: Context) => Context): void;
29
126
  set_context(context: Context): void;
30
127
  end(): void;
31
128
  }
32
- interface Tracer extends Scope {
33
- end(): ReturnType<Collector>;
129
+ interface Tracer {
130
+ /**
131
+ * @borrows {@link Scope.fork}
132
+ */
133
+ span: Scope['fork'];
134
+ /**
135
+ * @borrows {@link Scope.measure}
136
+ */
137
+ measure: Scope['measure'];
138
+ end(): ReturnType<Exporter>;
34
139
  }
35
140
  declare const create: (name: string, options: Options) => Tracer;
36
141
 
37
- export { Collector, Context, Options, Scope, Span, Tracer, create };
142
+ export { Context, Exporter, Options, Sampler, Scope, Span, Tracer, create };
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const package_json = require('rian/package.json');
3
4
  const tctx = require('tctx');
4
5
 
5
6
  function _interopNamespace(e) {
@@ -22,72 +23,97 @@ function _interopNamespace(e) {
22
23
 
23
24
  const tctx__namespace = /*#__PURE__*/_interopNamespace(tctx);
24
25
 
25
- const measure = (cb, scope, promises) => {
26
- const set_error = (error) => {
27
- scope.set_context({
28
- error,
29
- });
30
- };
31
- return (...args) => {
32
- try {
33
- var r = cb(...args, scope), is_promise = r instanceof Promise;
34
- if (is_promise)
35
- promises.push(r.catch(set_error).finally(() => scope.end()));
36
- return r;
37
- }
38
- catch (e) {
39
- set_error(e);
40
- throw e;
41
- }
42
- finally {
43
- if (is_promise !== true)
44
- scope.end();
45
- }
46
- };
26
+ const set_error = (scope, error) => {
27
+ scope.set_context({
28
+ error,
29
+ });
30
+ };
31
+ const measure = (fn, // TODO: fn doesnt see scope correctly
32
+ scope, promises, ...args) => {
33
+ try {
34
+ var r = fn(...args, scope), is_promise = r instanceof Promise;
35
+ if (is_promise)
36
+ promises.push(r
37
+ .catch((e) => void set_error(scope, e))
38
+ .finally(() => scope.end()));
39
+ return r;
40
+ }
41
+ catch (e) {
42
+ set_error(scope, e);
43
+ throw e;
44
+ }
45
+ finally {
46
+ if (is_promise !== true)
47
+ scope.end();
48
+ }
49
+ };
50
+
51
+ // ==> impl
52
+ /**
53
+ * The default sampler;
54
+ *
55
+ * If no parent
56
+ * ~> sample
57
+ * if parent was off
58
+ * ~> never sample
59
+ * if parent was on
60
+ * ~> always sample
61
+ */
62
+ const defaultSampler = (_name, parentId) => {
63
+ if (!parentId)
64
+ return true;
65
+ return tctx__namespace.is_sampled(parentId);
66
+ };
67
+ const sdk_object = {
68
+ 'telemetry.sdk.name': package_json.name,
69
+ 'telemetry.sdk.version': package_json.version,
47
70
  };
48
71
  const create = (name, options) => {
49
72
  const spans = new Set();
50
73
  const promises = [];
51
74
  const span = (name, parent) => {
52
- const id = parent ? parent.child() : tctx__namespace.make(true);
53
- let context = {};
75
+ const should_sample = (options.sampler || defaultSampler)(name, parent, options.context);
76
+ const id = parent
77
+ ? parent.child(should_sample)
78
+ : tctx__namespace.make(should_sample);
54
79
  const start = Date.now();
55
- let ended = false;
56
- // @ts-ignore
57
- const $ = (cb) => measure(cb, $, promises)();
80
+ const span_obj = {
81
+ id,
82
+ parent,
83
+ start,
84
+ name,
85
+ context: {},
86
+ };
87
+ if (should_sample)
88
+ spans.add(span_obj);
89
+ const $ = (cb) => measure(cb, $, promises);
58
90
  $.traceparent = id;
59
91
  $.fork = (name) => span(name, id);
60
- $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises)(...args);
92
+ $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
61
93
  $.set_context = (ctx) => {
62
94
  if (typeof ctx === 'function')
63
- return void (context = ctx(context));
64
- Object.assign(context, ctx);
95
+ return void (span_obj.context = ctx(span_obj.context));
96
+ Object.assign(span_obj.context, ctx);
65
97
  };
66
98
  $.end = () => {
67
- if (ended)
99
+ if (span_obj.end)
68
100
  return void 0;
69
- spans.add({
70
- id,
71
- parent,
72
- start,
73
- end: Date.now(),
74
- name,
75
- context,
76
- });
77
- ended = true;
101
+ span_obj.end = Date.now();
78
102
  };
79
103
  return $;
80
104
  };
81
105
  const root = span(name, typeof options.traceparent === 'string'
82
106
  ? tctx__namespace.parse(options.traceparent)
83
107
  : undefined);
84
- const meEnd = root.end.bind(root);
85
- root.end = async () => {
86
- meEnd();
87
- await Promise.all(promises);
88
- return options.collector(spans);
108
+ return {
109
+ span: root.fork.bind(root),
110
+ measure: root.measure.bind(root),
111
+ async end() {
112
+ root.end();
113
+ await Promise.all(promises);
114
+ return options.exporter(spans, Object.assign(options.context || {}, sdk_object));
115
+ },
89
116
  };
90
- return root;
91
117
  };
92
118
 
93
119
  exports.create = create;
package/index.mjs CHANGED
@@ -1,71 +1,97 @@
1
+ import { name, version } from 'rian/package.json';
1
2
  import * as tctx from 'tctx';
2
3
 
3
- const measure = (cb, scope, promises) => {
4
- const set_error = (error) => {
5
- scope.set_context({
6
- error,
7
- });
8
- };
9
- return (...args) => {
10
- try {
11
- var r = cb(...args, scope), is_promise = r instanceof Promise;
12
- if (is_promise)
13
- promises.push(r.catch(set_error).finally(() => scope.end()));
14
- return r;
15
- }
16
- catch (e) {
17
- set_error(e);
18
- throw e;
19
- }
20
- finally {
21
- if (is_promise !== true)
22
- scope.end();
23
- }
24
- };
4
+ const set_error = (scope, error) => {
5
+ scope.set_context({
6
+ error,
7
+ });
8
+ };
9
+ const measure = (fn, // TODO: fn doesnt see scope correctly
10
+ scope, promises, ...args) => {
11
+ try {
12
+ var r = fn(...args, scope), is_promise = r instanceof Promise;
13
+ if (is_promise)
14
+ promises.push(r
15
+ .catch((e) => void set_error(scope, e))
16
+ .finally(() => scope.end()));
17
+ return r;
18
+ }
19
+ catch (e) {
20
+ set_error(scope, e);
21
+ throw e;
22
+ }
23
+ finally {
24
+ if (is_promise !== true)
25
+ scope.end();
26
+ }
27
+ };
28
+
29
+ // ==> impl
30
+ /**
31
+ * The default sampler;
32
+ *
33
+ * If no parent
34
+ * ~> sample
35
+ * if parent was off
36
+ * ~> never sample
37
+ * if parent was on
38
+ * ~> always sample
39
+ */
40
+ const defaultSampler = (_name, parentId) => {
41
+ if (!parentId)
42
+ return true;
43
+ return tctx.is_sampled(parentId);
44
+ };
45
+ const sdk_object = {
46
+ 'telemetry.sdk.name': name,
47
+ 'telemetry.sdk.version': version,
25
48
  };
26
49
  const create = (name, options) => {
27
50
  const spans = new Set();
28
51
  const promises = [];
29
52
  const span = (name, parent) => {
30
- const id = parent ? parent.child() : tctx.make(true);
31
- let context = {};
53
+ const should_sample = (options.sampler || defaultSampler)(name, parent, options.context);
54
+ const id = parent
55
+ ? parent.child(should_sample)
56
+ : tctx.make(should_sample);
32
57
  const start = Date.now();
33
- let ended = false;
34
- // @ts-ignore
35
- const $ = (cb) => measure(cb, $, promises)();
58
+ const span_obj = {
59
+ id,
60
+ parent,
61
+ start,
62
+ name,
63
+ context: {},
64
+ };
65
+ if (should_sample)
66
+ spans.add(span_obj);
67
+ const $ = (cb) => measure(cb, $, promises);
36
68
  $.traceparent = id;
37
69
  $.fork = (name) => span(name, id);
38
- $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises)(...args);
70
+ $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
39
71
  $.set_context = (ctx) => {
40
72
  if (typeof ctx === 'function')
41
- return void (context = ctx(context));
42
- Object.assign(context, ctx);
73
+ return void (span_obj.context = ctx(span_obj.context));
74
+ Object.assign(span_obj.context, ctx);
43
75
  };
44
76
  $.end = () => {
45
- if (ended)
77
+ if (span_obj.end)
46
78
  return void 0;
47
- spans.add({
48
- id,
49
- parent,
50
- start,
51
- end: Date.now(),
52
- name,
53
- context,
54
- });
55
- ended = true;
79
+ span_obj.end = Date.now();
56
80
  };
57
81
  return $;
58
82
  };
59
83
  const root = span(name, typeof options.traceparent === 'string'
60
84
  ? tctx.parse(options.traceparent)
61
85
  : undefined);
62
- const meEnd = root.end.bind(root);
63
- root.end = async () => {
64
- meEnd();
65
- await Promise.all(promises);
66
- return options.collector(spans);
86
+ return {
87
+ span: root.fork.bind(root),
88
+ measure: root.measure.bind(root),
89
+ async end() {
90
+ root.end();
91
+ await Promise.all(promises);
92
+ return options.exporter(spans, Object.assign(options.context || {}, sdk_object));
93
+ },
67
94
  };
68
- return root;
69
95
  };
70
96
 
71
97
  export { create };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rian",
3
- "version": "0.0.2-alpha.10",
3
+ "version": "0.0.2-alpha.11",
4
4
  "description": "A tracer for the edge",
5
5
  "keywords": [
6
6
  "TODO"
@@ -19,6 +19,14 @@
19
19
  "import": "./index.mjs",
20
20
  "require": "./index.js"
21
21
  },
22
+ "./exporter.otel.http": {
23
+ "import": "./exporter.otel.http.mjs",
24
+ "require": "./exporter.otel.http.js"
25
+ },
26
+ "./exporter.zipkin": {
27
+ "import": "./exporter.zipkin.mjs",
28
+ "require": "./exporter.zipkin.js"
29
+ },
22
30
  "./package.json": "./package.json"
23
31
  },
24
32
  "main": "./index.js",
@@ -30,6 +38,7 @@
30
38
  "*.d.ts"
31
39
  ],
32
40
  "dependencies": {
41
+ "flattie": "^1.1.0",
33
42
  "tctx": "^0.0.10"
34
43
  }
35
44
  }