rian 0.0.5 → 0.2.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.
@@ -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;