rian 0.0.5 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ import type { Exporter } from 'rian';
2
+
3
+ export const exporter: (request: (payload: any) => any) => Exporter;
@@ -0,0 +1,110 @@
1
+ // src/exporter.otel.http.ts
2
+ const { name:rian_name, version:rian_version } = require('rian/package.json');
3
+ var SpanStatusCode_UNSET = 0;
4
+ var SpanStatusCode_ERROR = 2;
5
+ var 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 if (value)
21
+ any_value.kvlistValue = { values: convert_object_to_kv(value) };
22
+ return any_value;
23
+ };
24
+ var 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
+ var map_kind = (kind) => {
35
+ switch (kind) {
36
+ default:
37
+ case "INTERNAL": {
38
+ return 1;
39
+ }
40
+ case "SERVER": {
41
+ return 2;
42
+ }
43
+ case "CLIENT": {
44
+ return 3;
45
+ }
46
+ case "PRODUCER": {
47
+ return 4;
48
+ }
49
+ case "CONSUMER": {
50
+ return 5;
51
+ }
52
+ }
53
+ };
54
+ var exporter = (request) => (spans, context) => {
55
+ const otel_spans = [];
56
+ for (let span of spans) {
57
+ const { kind, error, ...span_ctx } = span.context;
58
+ let status;
59
+ if (error) {
60
+ status = {
61
+ code: SpanStatusCode_ERROR
62
+ };
63
+ if ("message" in error) {
64
+ status.message = error.message;
65
+ }
66
+ }
67
+ otel_spans.push({
68
+ traceId: span.id.trace_id,
69
+ spanId: span.id.parent_id,
70
+ parentSpanId: span.parent?.parent_id,
71
+ name: span.name,
72
+ kind: map_kind(kind || "INTERNAL"),
73
+ startTimeUnixNano: span.start * 1e6,
74
+ endTimeUnixNano: span.end ? span.end * 1e6 : void 0,
75
+ droppedAttributesCount: 0,
76
+ droppedEventsCount: 0,
77
+ droppedLinksCount: 0,
78
+ attributes: convert_object_to_kv(span_ctx),
79
+ status: status || { code: SpanStatusCode_UNSET },
80
+ events: span.events.map((i) => ({
81
+ name: i.name,
82
+ attributes: convert_object_to_kv(i.attributes),
83
+ droppedAttributesCount: 0,
84
+ timeUnixNano: i.timestamp * 1e6
85
+ }))
86
+ });
87
+ }
88
+ return request({
89
+ resourceSpans: [
90
+ {
91
+ resource: {
92
+ attributes: convert_object_to_kv(context),
93
+ droppedAttributesCount: 0
94
+ },
95
+ instrumentationLibrarySpans: [
96
+ {
97
+ instrumentationLibrary: {
98
+ name: rian_name,
99
+ version: rian_version
100
+ },
101
+ spans: otel_spans
102
+ }
103
+ ]
104
+ }
105
+ ]
106
+ });
107
+ };
108
+
109
+
110
+ exports.exporter = exporter;
@@ -0,0 +1,110 @@
1
+ // src/exporter.otel.http.ts
2
+ import { name as rian_name, version as rian_version } from "rian/package.json";
3
+ var SpanStatusCode_UNSET = 0;
4
+ var SpanStatusCode_ERROR = 2;
5
+ var 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 if (value)
21
+ any_value.kvlistValue = { values: convert_object_to_kv(value) };
22
+ return any_value;
23
+ };
24
+ var 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
+ var map_kind = (kind) => {
35
+ switch (kind) {
36
+ default:
37
+ case "INTERNAL": {
38
+ return 1;
39
+ }
40
+ case "SERVER": {
41
+ return 2;
42
+ }
43
+ case "CLIENT": {
44
+ return 3;
45
+ }
46
+ case "PRODUCER": {
47
+ return 4;
48
+ }
49
+ case "CONSUMER": {
50
+ return 5;
51
+ }
52
+ }
53
+ };
54
+ var exporter = (request) => (spans, context) => {
55
+ const otel_spans = [];
56
+ for (let span of spans) {
57
+ const { kind, error, ...span_ctx } = span.context;
58
+ let status;
59
+ if (error) {
60
+ status = {
61
+ code: SpanStatusCode_ERROR
62
+ };
63
+ if ("message" in error) {
64
+ status.message = error.message;
65
+ }
66
+ }
67
+ otel_spans.push({
68
+ traceId: span.id.trace_id,
69
+ spanId: span.id.parent_id,
70
+ parentSpanId: span.parent?.parent_id,
71
+ name: span.name,
72
+ kind: map_kind(kind || "INTERNAL"),
73
+ startTimeUnixNano: span.start * 1e6,
74
+ endTimeUnixNano: span.end ? span.end * 1e6 : void 0,
75
+ droppedAttributesCount: 0,
76
+ droppedEventsCount: 0,
77
+ droppedLinksCount: 0,
78
+ attributes: convert_object_to_kv(span_ctx),
79
+ status: status || { code: SpanStatusCode_UNSET },
80
+ events: span.events.map((i) => ({
81
+ name: i.name,
82
+ attributes: convert_object_to_kv(i.attributes),
83
+ droppedAttributesCount: 0,
84
+ timeUnixNano: i.timestamp * 1e6
85
+ }))
86
+ });
87
+ }
88
+ return request({
89
+ resourceSpans: [
90
+ {
91
+ resource: {
92
+ attributes: convert_object_to_kv(context),
93
+ droppedAttributesCount: 0
94
+ },
95
+ instrumentationLibrarySpans: [
96
+ {
97
+ instrumentationLibrary: {
98
+ name: rian_name,
99
+ version: rian_version
100
+ },
101
+ spans: otel_spans
102
+ }
103
+ ]
104
+ }
105
+ ]
106
+ });
107
+ };
108
+ export {
109
+ exporter
110
+ };
@@ -0,0 +1,3 @@
1
+ import type { Exporter } from 'rian';
2
+
3
+ export const exporter: (request: (payload: any) => any) => Exporter;
@@ -0,0 +1,43 @@
1
+ // src/exporter.zipkin.ts
2
+ const { flattie } = require('flattie');
3
+ var exporter = (request) => (spans, context) => {
4
+ const zipkin = [];
5
+ for (let span of spans) {
6
+ const { kind, error, ...span_ctx } = span.context;
7
+ if (error) {
8
+ if ("message" in error) {
9
+ span_ctx.error = {
10
+ name: error.name,
11
+ message: error.message,
12
+ stack: error.stack
13
+ };
14
+ } else {
15
+ span_ctx.error = true;
16
+ }
17
+ }
18
+ zipkin.push({
19
+ id: span.id.parent_id,
20
+ traceId: span.id.trace_id,
21
+ parentId: span.parent ? span.parent.parent_id : void 0,
22
+ name: span.name,
23
+ kind: kind === "INTERNAL" ? void 0 : kind,
24
+ timestamp: span.start * 1e3,
25
+ duration: span.end ? (span.end - span.start) * 1e3 : void 0,
26
+ localEndpoint: context.localEndpoint || {
27
+ serviceName: span_ctx["service.name"]
28
+ },
29
+ tags: flattie({
30
+ ...context,
31
+ ...span_ctx
32
+ }, ".", true),
33
+ annotations: span.events.map((i) => ({
34
+ value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
35
+ timestamp: i.timestamp * 1e3
36
+ }))
37
+ });
38
+ }
39
+ return request(zipkin);
40
+ };
41
+
42
+
43
+ exports.exporter = exporter;
@@ -0,0 +1,43 @@
1
+ // src/exporter.zipkin.ts
2
+ import { flattie } from "flattie";
3
+ var exporter = (request) => (spans, context) => {
4
+ const zipkin = [];
5
+ for (let span of spans) {
6
+ const { kind, error, ...span_ctx } = span.context;
7
+ if (error) {
8
+ if ("message" in error) {
9
+ span_ctx.error = {
10
+ name: error.name,
11
+ message: error.message,
12
+ stack: error.stack
13
+ };
14
+ } else {
15
+ span_ctx.error = true;
16
+ }
17
+ }
18
+ zipkin.push({
19
+ id: span.id.parent_id,
20
+ traceId: span.id.trace_id,
21
+ parentId: span.parent ? span.parent.parent_id : void 0,
22
+ name: span.name,
23
+ kind: kind === "INTERNAL" ? void 0 : kind,
24
+ timestamp: span.start * 1e3,
25
+ duration: span.end ? (span.end - span.start) * 1e3 : void 0,
26
+ localEndpoint: context.localEndpoint || {
27
+ serviceName: span_ctx["service.name"]
28
+ },
29
+ tags: flattie({
30
+ ...context,
31
+ ...span_ctx
32
+ }, ".", true),
33
+ annotations: span.events.map((i) => ({
34
+ value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
35
+ timestamp: i.timestamp * 1e3
36
+ }))
37
+ });
38
+ }
39
+ return request(zipkin);
40
+ };
41
+ export {
42
+ exporter
43
+ };
package/index.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- import { Traceparent } from 'tctx';
2
- import { Scope as Scope$1 } from 'rian';
3
-
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
1
  /**
8
2
  * Spans are units within a distributed trace. Spans encapsulate mainly 3 pieces of information, a
9
3
  * {@link Span.name|name}, and a {@link Span.start|start} and {@link Span.end|end} time.
@@ -24,134 +18,124 @@ declare type RealMeasureFnParams<T extends unknown[]> = T extends [] ? [] : T ex
24
18
  * Spans are aimed to interoperate with
25
19
  * {@link https://github.com/opentracing/specification/blob/master/specification.md|OpenTracing's Spans}, albeit not entirely api compatible — they do share principles.
26
20
  */
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
- */
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
- */
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
- */
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
- */
55
- start: 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
- */
76
- context: Context;
77
- /**
78
- * Events are user-defined timestamped annotations of "events" that happened during the
79
- * lifetime of a span. Consisting of a textual message, and optional attributes.
80
- *
81
- * As a rule-of-thumb use events to attach verbose information about a span, than an entirely
82
- * new span.
83
- */
84
- events: {
85
- name: string;
86
- timestamp: number;
87
- attributes: Context;
88
- }[];
21
+ export interface Span {
22
+ /**
23
+ * A human-readable name for this span. For example the function name, the name of a subtask,
24
+ * or stage of the larger stack.
25
+ *
26
+ * @example
27
+ * "resolve_user_ids"
28
+ * "[POST] /api"
29
+ */
30
+ name: string;
31
+
32
+ /**
33
+ * A w3c trace context compatible id for this span. Will .toString() into an injectable header.
34
+ *
35
+ * @see https://www.w3.org/TR/trace-context/#traceparent-header
36
+ * @see https://github.com/maraisr/tctx
37
+ */
38
+ id: Traceparent;
39
+
40
+ /**
41
+ * Is the id of rhe parent if this is not the parent {@link Span}.
42
+ *
43
+ * @see {@link Span.id}
44
+ */
45
+ parent: Traceparent | undefined;
46
+
47
+ /**
48
+ * The time represented as a UNIX epoch timestamp in milliseconds when this span was created.
49
+ * Typically, via
50
+ * {@link Scope.fork|tracer.fork()}.
51
+ */
52
+ start: number;
53
+
54
+ /**
55
+ * The UNIX epoch timestamp in milliseconds when the span ended, or undefined if ending was not
56
+ * captured during the current trace. Time should then be assumed as current time.
57
+ */
58
+ end?: number;
59
+
60
+ /**
61
+ * An arbitrary context object useful for storing information during a trace.
62
+ *
63
+ * Usually following a convention such as `tag.*`, `http.*` or any of the
64
+ * {@link https://github.com/opentracing/specification/blob/master/semantic_conventions.md|Semantic Conventions outlined by OpenTracing}.
65
+ *
66
+ * ### Note!
67
+ *
68
+ * There are a few keys with "powers"
69
+ *
70
+ * - `kind` when set will coerce into the exports scheme, aka INTERNAL in zipkin will be
71
+ * `"INTERNAL"`, or `1` in otel
72
+ * - `error` when set, will be assumed to be an `Error` instance, and thus its `.message` wil
73
+ * exist as `error.message` in zipkin, and `status: 2` in otel.
74
+ */
75
+ context: Context;
76
+
77
+ /**
78
+ * Events are user-defined timestamped annotations of "events" that happened during the
79
+ * lifetime of a span. Consisting of a textual message, and optional attributes.
80
+ *
81
+ * As a rule-of-thumb use events to attach verbose information about a span, than an entirely
82
+ * new span.
83
+ */
84
+ events: { name: string; timestamp: number; attributes: Context }[];
89
85
  }
90
- interface Scope {
91
- /**
92
- * A W3C traceparent. One can .toString() this if you want to cross a network.
93
- */
94
- traceparent: Traceparent;
95
- /**
96
- * Forks the span into a new child span.
97
- */
98
- fork(name: string): CallableScope;
99
- /**
100
- * With a passed function — will start a span, and run the function, when the function finishes
101
- * the span finishes.
102
- *
103
- * The measure method will return whatever the function is, so if it's a promise, it returns a
104
- * promise and so on. Any error is caught and re thrown, and automatically tracked in the
105
- * context under the `error` property.
106
- *
107
- * All promises are tracked, and awaited on a `tracer.end`.
108
- *
109
- * @example
110
- *
111
- * ```text
112
- * const data = await scope.measure('name', get_data, 'user_id_123');
113
- * ^ ^ ^ ^
114
- * | | | |
115
- * | | | the first argument to get_data
116
- * | | function to be called
117
- * | the name of the sub scope
118
- * return value from get_data
119
- * ```
120
- */
121
- measure<Fn extends MeasureFn>(name: string, fn: Fn, // TODO: fn doesnt see scope correctly
122
- ...args: RealMeasureFnParams<Parameters<Fn>>): ReturnType<Fn>;
123
- /**
124
- * Allows the span's context to be set. Passing an object will be `Object.assign`ed into the
125
- * current context.
126
- *
127
- * Passing a function will be available to return a new context.
128
- */
129
- set_context(contextFn: Context | ((context: Context) => Context)): void;
130
- /**
131
- * Adds a new event to the span. As a rule-of-thumb use events to attach verbose information
132
- * about a span, than an entirely new span.
133
- */
134
- add_event(name: string, attributes?: Record<string, any>): void;
135
- /**
136
- * Ends the current span — setting its `end` timestamp. Not calling this, will have its `end`
137
- * timestamp nulled out — when the tracer ends.
138
- */
139
- end(): void;
86
+
87
+ export interface Scope {
88
+ /**
89
+ * A W3C traceparent. One can .toString() this if you want to cross a network.
90
+ */
91
+ traceparent: Traceparent;
92
+
93
+ /**
94
+ * Forks the span into a new child span.
95
+ */
96
+ fork(name: string): CallableScope;
97
+
98
+ /**
99
+ * Allows the span's context to be set. Passing an object will be `Object.assign`ed into the
100
+ * current context.
101
+ *
102
+ * Passing a function will be available to return a new context.
103
+ */
104
+ set_context(contextFn: Context | ((context: Context) => Context)): void;
105
+
106
+ /**
107
+ * Adds a new event to the span. As a rule-of-thumb use events to attach verbose information
108
+ * about a span, than an entirely new span.
109
+ */
110
+ add_event(name: string, attributes?: Record<string, any>): void;
111
+
112
+ /**
113
+ * Ends the current span setting its `end` timestamp. Not calling this, will have its `end`
114
+ * timestamp nulled out — when the tracer ends.
115
+ */
116
+ end(): void;
140
117
  }
141
- interface Tracer extends Omit<Scope, 'end'> {
142
- end(): ReturnType<Exporter>;
118
+
119
+ export interface Tracer extends Omit<Scope, 'end'> {
120
+ end(): ReturnType<Exporter>;
143
121
  }
122
+
144
123
  /**
145
124
  * An exporter is a method called when the parent scope ends, gets given a Set of all spans traced
146
125
  * during this execution.
147
126
  */
148
- declare type Exporter = (spans: ReadonlySet<Readonly<Span>>, context: Context) => any;
127
+ export type Exporter = (
128
+ spans: ReadonlySet<Readonly<Span>>,
129
+ context: Context,
130
+ ) => any;
131
+
149
132
  /**
150
133
  * @borrows {@link Span.context}
151
134
  */
152
- interface Context {
153
- [property: string]: any;
135
+ export interface Context {
136
+ [property: string]: any;
154
137
  }
138
+
155
139
  /**
156
140
  * Should return true when you want to sample the span, this is ran before the span is traced — so
157
141
  * decisions is made preemptively.
@@ -161,28 +145,45 @@ interface Context {
161
145
  *
162
146
  * Sampling does impact the traceparent, for injection — and is encoded there.
163
147
  */
164
- declare type Sampler = (name: string, parentId?: Traceparent, context?: Context) => boolean;
165
- interface Options {
166
- /**
167
- * @borrows {@link Exporter}
168
- */
169
- exporter: Exporter;
170
- /**
171
- * @borrows {@link Sampler}
172
- */
173
- sampler?: Sampler | boolean;
174
- context?: Context;
175
- /**
176
- * A root, or extracted w3c traceparent stringed header.
177
- *
178
- * If the id is malformed, the {@link create} method will throw an exception. If no root is
179
- * provided then one will be created obeying the {@link Options.sampler|sampling} rules.
180
- */
181
- traceparent?: string;
148
+ export type Sampler = (
149
+ name: string,
150
+ parentId?: Traceparent,
151
+ context?: Context,
152
+ ) => boolean;
153
+
154
+ export interface Options {
155
+ /**
156
+ * @borrows {@link Exporter}
157
+ */
158
+ exporter: Exporter;
159
+
160
+ /**
161
+ * @borrows {@link Sampler}
162
+ */
163
+ sampler?: Sampler | boolean;
164
+
165
+ context?: Context;
166
+
167
+ /**
168
+ * A root, or extracted w3c traceparent stringed header.
169
+ *
170
+ * If the id is malformed, the {@link create} method will throw an exception. If no root is
171
+ * provided then one will be created obeying the {@link Options.sampler|sampling} rules.
172
+ */
173
+ traceparent?: string;
182
174
  }
183
- interface CallableScope extends Scope {
184
- (cb: (scope: Omit<Scope, 'end'>) => void): ReturnType<typeof cb>;
175
+
176
+ export const create: (name: string, options: Options) => Tracer;
177
+
178
+ // ==> internals
179
+
180
+ /** @internal */
181
+ export interface CallableScope extends Scope {
182
+ (cb: (scope: Omit<Scope, 'end'>) => void): ReturnType<typeof cb>;
185
183
  }
186
- declare const create: (name: string, options: Options) => Tracer;
187
184
 
188
- export { Context, Exporter, Options, Sampler, Scope, Span, Tracer, create };
185
+ /** @internal */
186
+ export const PROMISES: WeakMap<Scope, Promise<any>[]>;
187
+
188
+ /** @internal */
189
+ export const ADD_PROMISE: (scope: Scope, promise: Promise<any>) => void;