rian 0.0.2-alpha.1 → 0.0.2-alpha.13

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,35 +1,134 @@
1
- import { Traceparent } from 'rian/tracecontext';
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;
9
- attributes: Attributes;
10
- };
11
- declare type Collector = (spans: ReadonlySet<Span>) => any;
12
- declare type Attributes = {
13
- [property: string]: string | number | boolean | undefined | Error;
14
- };
15
- declare type Options = {
16
- collector: Collector;
17
- traceparent?: Traceparent;
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;
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
+ */
76
+ context: 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 {
87
+ [property: string]: any;
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
+ */
115
+ traceparent?: string;
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, ...args: OmitScopeParam<Params>): ReturnType<Fn>;
27
- set_attributes(attributes: Attributes): void;
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>;
125
+ set_context(contextFn: (context: Context) => Context): void;
126
+ set_context(context: Context): void;
28
127
  end(): void;
29
128
  }
30
- interface Tracer extends Scope {
31
- end(): ReturnType<Collector>;
129
+ interface Tracer extends Omit<Scope, 'end'> {
130
+ end(): ReturnType<Exporter>;
32
131
  }
33
132
  declare const create: (name: string, options: Options) => Tracer;
34
133
 
35
- export { Attributes, Collector, Options, Scope, Span, Tracer, create };
134
+ export { Context, Exporter, Options, Sampler, Scope, Span, Tracer, create };
package/index.js CHANGED
@@ -1,75 +1,117 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.create = void 0;
5
- const tracecontext_1 = require("rian/tracecontext");
6
- const measure = (cb, scope, promises) => {
7
- const set_error = (error) => {
8
- scope.set_attributes({
9
- error,
10
- });
11
- };
3
+ const package_json = require('rian/package.json');
4
+ const tctx = require('tctx');
5
+
6
+ function _interopNamespace(e) {
7
+ if (e && e.__esModule) return e;
8
+ const n = Object.create(null);
9
+ if (e) {
10
+ for (const k in e) {
11
+ if (k !== 'default') {
12
+ const d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ }
19
+ }
20
+ n["default"] = e;
21
+ return n;
22
+ }
23
+
24
+ const tctx__namespace = /*#__PURE__*/_interopNamespace(tctx);
25
+
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) => {
12
33
  try {
13
- const r = cb();
14
- if (r instanceof Promise)
15
- promises.push(r.catch(set_error).finally(() => scope.end()));
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()));
16
39
  return r;
17
40
  }
18
41
  catch (e) {
19
- set_error(e);
42
+ set_error(scope, e);
20
43
  throw e;
21
44
  }
22
45
  finally {
23
- scope.end();
46
+ if (is_promise !== true)
47
+ scope.end();
24
48
  }
25
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,
70
+ };
26
71
  const create = (name, options) => {
27
72
  const spans = new Set();
28
73
  const promises = [];
29
- const scope = (name, parent) => {
30
- const me = parent ? parent.child() : (0, tracecontext_1.make_traceparent)();
31
- const attributes = {};
32
- const start = performance.now();
33
- let ended = false;
34
- const $ = {
35
- get traceparent() {
36
- return me;
37
- },
38
- fork(name) {
39
- return scope(name, me);
40
- },
41
- measure(name, cb, ...args) {
42
- const scope = this.fork(name);
43
- return measure(() => cb(...args, scope), scope, promises);
44
- },
45
- set_attributes(attr) {
46
- Object.assign(attributes, attr);
47
- },
48
- end() {
49
- if (ended)
50
- return void 0;
51
- spans.add({
52
- id: me,
53
- parent,
54
- start,
55
- end: performance.now(),
56
- name,
57
- attributes,
58
- });
59
- ended = true;
60
- },
74
+ const span = (name, parent) => {
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);
79
+ const start = Date.now();
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);
90
+ $.traceparent = id;
91
+ $.fork = (name) => span(name, id);
92
+ $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
93
+ $.set_context = (ctx) => {
94
+ if (typeof ctx === 'function')
95
+ return void (span_obj.context = ctx(span_obj.context));
96
+ Object.assign(span_obj.context, ctx);
61
97
  };
62
- return Object.setPrototypeOf((cb) => measure(cb, $, promises), $);
98
+ $.end = () => {
99
+ if (span_obj.end)
100
+ return void 0;
101
+ span_obj.end = Date.now();
102
+ };
103
+ return $;
63
104
  };
64
- const me = scope(name, typeof options.traceparent === 'string'
65
- ? (0, tracecontext_1.parse_traceparent)(options.traceparent)
66
- : options.traceparent);
67
- const meEnd = me.end.bind(me);
68
- me.end = async () => {
105
+ const root = span(name, typeof options.traceparent === 'string'
106
+ ? tctx__namespace.parse(options.traceparent)
107
+ : undefined);
108
+ const endRoot = root.end.bind(root);
109
+ root.end = async () => {
110
+ endRoot();
69
111
  await Promise.all(promises);
70
- meEnd();
71
- return options.collector(spans);
112
+ return options.exporter(spans, Object.assign(options.context || {}, sdk_object));
72
113
  };
73
- return me;
114
+ return root;
74
115
  };
116
+
75
117
  exports.create = create;
package/index.mjs CHANGED
@@ -1,73 +1,95 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.create = void 0;
3
- const tracecontext_1 = require("rian/tracecontext");
4
- const measure = (cb, scope, promises) => {
5
- const set_error = (error) => {
6
- scope.set_attributes({
7
- error,
8
- });
9
- };
1
+ import { name, version } from 'rian/package.json';
2
+ import * as tctx from 'tctx';
3
+
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) => {
10
11
  try {
11
- const r = cb();
12
- if (r instanceof Promise)
13
- promises.push(r.catch(set_error).finally(() => scope.end()));
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()));
14
17
  return r;
15
18
  }
16
19
  catch (e) {
17
- set_error(e);
20
+ set_error(scope, e);
18
21
  throw e;
19
22
  }
20
23
  finally {
21
- scope.end();
24
+ if (is_promise !== true)
25
+ scope.end();
22
26
  }
23
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,
48
+ };
24
49
  const create = (name, options) => {
25
50
  const spans = new Set();
26
51
  const promises = [];
27
- const scope = (name, parent) => {
28
- const me = parent ? parent.child() : (0, tracecontext_1.make_traceparent)();
29
- const attributes = {};
30
- const start = performance.now();
31
- let ended = false;
32
- const $ = {
33
- get traceparent() {
34
- return me;
35
- },
36
- fork(name) {
37
- return scope(name, me);
38
- },
39
- measure(name, cb, ...args) {
40
- const scope = this.fork(name);
41
- return measure(() => cb(...args, scope), scope, promises);
42
- },
43
- set_attributes(attr) {
44
- Object.assign(attributes, attr);
45
- },
46
- end() {
47
- if (ended)
48
- return void 0;
49
- spans.add({
50
- id: me,
51
- parent,
52
- start,
53
- end: performance.now(),
54
- name,
55
- attributes,
56
- });
57
- ended = true;
58
- },
52
+ const span = (name, parent) => {
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);
57
+ const start = Date.now();
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);
68
+ $.traceparent = id;
69
+ $.fork = (name) => span(name, id);
70
+ $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
71
+ $.set_context = (ctx) => {
72
+ if (typeof ctx === 'function')
73
+ return void (span_obj.context = ctx(span_obj.context));
74
+ Object.assign(span_obj.context, ctx);
75
+ };
76
+ $.end = () => {
77
+ if (span_obj.end)
78
+ return void 0;
79
+ span_obj.end = Date.now();
59
80
  };
60
- return Object.setPrototypeOf((cb) => measure(cb, $, promises), $);
81
+ return $;
61
82
  };
62
- const me = scope(name, typeof options.traceparent === 'string'
63
- ? (0, tracecontext_1.parse_traceparent)(options.traceparent)
64
- : options.traceparent);
65
- const meEnd = me.end.bind(me);
66
- me.end = async () => {
83
+ const root = span(name, typeof options.traceparent === 'string'
84
+ ? tctx.parse(options.traceparent)
85
+ : undefined);
86
+ const endRoot = root.end.bind(root);
87
+ root.end = async () => {
88
+ endRoot();
67
89
  await Promise.all(promises);
68
- meEnd();
69
- return options.collector(spans);
90
+ return options.exporter(spans, Object.assign(options.context || {}, sdk_object));
70
91
  };
71
- return me;
92
+ return root;
72
93
  };
73
- exports.create = create;
94
+
95
+ export { create };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rian",
3
- "version": "0.0.2-alpha.1",
3
+ "version": "0.0.2-alpha.13",
4
4
  "description": "A tracer for the edge",
5
5
  "keywords": [
6
6
  "TODO"
@@ -19,9 +19,13 @@
19
19
  "import": "./index.mjs",
20
20
  "require": "./index.js"
21
21
  },
22
- "./tracecontext": {
23
- "import": "./tracecontext.mjs",
24
- "require": "./tracecontext.js"
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"
25
29
  },
26
30
  "./package.json": "./package.json"
27
31
  },
@@ -34,6 +38,7 @@
34
38
  "*.d.ts"
35
39
  ],
36
40
  "dependencies": {
37
- "tctx": "^0.0.6"
41
+ "flattie": "^1.1.0",
42
+ "tctx": "^0.0.10"
38
43
  }
39
44
  }
package/tracecontext.d.ts DELETED
@@ -1 +0,0 @@
1
- export { Traceparent, make as make_traceparent, parse as parse_traceparent } from 'tctx';
package/tracecontext.js DELETED
@@ -1,7 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.parse_traceparent = exports.make_traceparent = void 0;
5
- var tctx_1 = require("tctx");
6
- Object.defineProperty(exports, "make_traceparent", { enumerable: true, get: function () { return tctx_1.make; } });
7
- Object.defineProperty(exports, "parse_traceparent", { enumerable: true, get: function () { return tctx_1.parse; } });
package/tracecontext.mjs DELETED
@@ -1,5 +0,0 @@
1
- Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.parse_traceparent = exports.make_traceparent = void 0;
3
- var tctx_1 = require("tctx");
4
- Object.defineProperty(exports, "make_traceparent", { enumerable: true, get: function () { return tctx_1.make; } });
5
- Object.defineProperty(exports, "parse_traceparent", { enumerable: true, get: function () { return tctx_1.parse; } });