rian 0.0.3 → 0.1.0

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.
@@ -19,7 +19,7 @@ const convert_value_to_anyvalue = (value) => {
19
19
  any_value.arrayValue = {
20
20
  values: value.map((i) => convert_value_to_anyvalue(i)),
21
21
  };
22
- else
22
+ else if (value)
23
23
  any_value.kvlistValue = { values: convert_object_to_kv(value) };
24
24
  return any_value;
25
25
  };
@@ -17,7 +17,7 @@ const convert_value_to_anyvalue = (value) => {
17
17
  any_value.arrayValue = {
18
18
  values: value.map((i) => convert_value_to_anyvalue(i)),
19
19
  };
20
- else
20
+ else if (value)
21
21
  any_value.kvlistValue = { values: convert_object_to_kv(value) };
22
22
  return any_value;
23
23
  };
@@ -26,8 +26,13 @@ const exporter = (request) => (spans, context) => {
26
26
  kind: kind === 'INTERNAL' ? undefined : kind,
27
27
  timestamp: span.start * 1000,
28
28
  duration: span.end ? (span.end - span.start) * 1000 : undefined,
29
- localEndpoint: context.localEndpoint,
30
- tags: flattie.flattie(Object.assign({}, context, span_ctx), '.', true),
29
+ localEndpoint: context.localEndpoint || {
30
+ serviceName: span_ctx['service.name'],
31
+ },
32
+ tags: flattie.flattie({
33
+ ...context,
34
+ ...span_ctx,
35
+ }, '.', true),
31
36
  annotations: span.events.map((i) => ({
32
37
  value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
33
38
  timestamp: i.timestamp * 1000,
@@ -24,8 +24,13 @@ const exporter = (request) => (spans, context) => {
24
24
  kind: kind === 'INTERNAL' ? undefined : kind,
25
25
  timestamp: span.start * 1000,
26
26
  duration: span.end ? (span.end - span.start) * 1000 : undefined,
27
- localEndpoint: context.localEndpoint,
28
- tags: flattie(Object.assign({}, context, span_ctx), '.', true),
27
+ localEndpoint: context.localEndpoint || {
28
+ serviceName: span_ctx['service.name'],
29
+ },
30
+ tags: flattie({
31
+ ...context,
32
+ ...span_ctx,
33
+ }, '.', true),
29
34
  annotations: span.events.map((i) => ({
30
35
  value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
31
36
  timestamp: i.timestamp * 1000,
package/index.d.ts CHANGED
@@ -1,8 +1,4 @@
1
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
2
 
7
3
  /**
8
4
  * Spans are units within a distributed trace. Spans encapsulate mainly 3 pieces of information, a
@@ -96,30 +92,6 @@ interface Scope {
96
92
  * Forks the span into a new child span.
97
93
  */
98
94
  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
95
  /**
124
96
  * Allows the span's context to be set. Passing an object will be `Object.assign`ed into the
125
97
  * current context.
@@ -170,7 +142,7 @@ interface Options {
170
142
  /**
171
143
  * @borrows {@link Sampler}
172
144
  */
173
- sampler?: Sampler;
145
+ sampler?: Sampler | boolean;
174
146
  context?: Context;
175
147
  /**
176
148
  * A root, or extracted w3c traceparent stringed header.
package/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const package_json = require('rian/package.json');
4
4
  const tctx = require('tctx');
5
+ const rian = require('rian');
5
6
 
6
7
  function _interopNamespace(e) {
7
8
  if (e && e.__esModule) return e;
@@ -28,12 +29,11 @@ const set_error = (scope, error) => {
28
29
  error,
29
30
  });
30
31
  };
31
- const measure = (fn, // TODO: fn doesnt see scope correctly
32
- scope, promises, ...args) => {
32
+ const measureFn = (scope, fn, ...args) => {
33
33
  try {
34
34
  var r = fn(...args, scope), is_promise = r instanceof Promise;
35
- if (is_promise)
36
- promises.push(r
35
+ if (is_promise && rian.PROMISES.has(scope))
36
+ rian.ADD_PROMISE(scope, r
37
37
  .catch((e) => void set_error(scope, e))
38
38
  .finally(() => scope.end()));
39
39
  return r;
@@ -47,8 +47,44 @@ scope, promises, ...args) => {
47
47
  scope.end();
48
48
  }
49
49
  };
50
+ /**
51
+ * With a passed function — will start a span, and run the function, when the function finishes
52
+ * the span finishes.
53
+ *
54
+ * The measure method will return whatever the function is, so if it's a promise, it returns a
55
+ * promise and so on. Any error is caught and re thrown, and automatically tracked in the
56
+ * context under the `error` property.
57
+ *
58
+ * All promises are tracked, and awaited on a `tracer.end`.
59
+ *
60
+ * @example
61
+ *
62
+ * ```text
63
+ * const data = await measure(scope, get_data, 'user_id_123');
64
+ * ^ ^ ^
65
+ * | | |
66
+ * | | the first argument to get_data
67
+ * | function to be called
68
+ * return value from get_data
69
+ * ```
70
+ */
71
+ const measure = (scope, fn, // TODO: fn doesnt see scope correctly
72
+ ...args) => measureFn(scope, fn, ...args);
50
73
 
51
74
  // ==> impl
75
+ /**
76
+ * @internal
77
+ */
78
+ const PROMISES = new WeakMap();
79
+ /**
80
+ * @internal
81
+ */
82
+ const ADD_PROMISE = (scope, promise) => {
83
+ if (PROMISES.has(scope))
84
+ PROMISES.get(scope).push(promise);
85
+ else
86
+ PROMISES.set(scope, [promise]);
87
+ };
52
88
  /**
53
89
  * The default sampler;
54
90
  *
@@ -70,10 +106,12 @@ const sdk_object = {
70
106
  };
71
107
  const create = (name, options) => {
72
108
  const spans = new Set();
73
- const promises = [];
74
109
  const sampler = options.sampler || defaultSampler;
110
+ const sampler_callable = typeof sampler !== 'boolean';
75
111
  const span = (name, parent) => {
76
- const should_sample = sampler(name, parent, options.context);
112
+ const should_sample = sampler_callable
113
+ ? sampler(name, parent, options.context)
114
+ : sampler;
77
115
  const id = parent
78
116
  ? parent.child(should_sample)
79
117
  : tctx__namespace.make(should_sample);
@@ -87,10 +125,9 @@ const create = (name, options) => {
87
125
  };
88
126
  if (should_sample)
89
127
  spans.add(span_obj);
90
- const $ = (cb) => measure(cb, $, promises);
128
+ const $ = (cb) => measure($, cb);
91
129
  $.traceparent = id;
92
130
  $.fork = (name) => span(name, id);
93
- $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
94
131
  $.set_context = (ctx) => {
95
132
  if (typeof ctx === 'function')
96
133
  return void (span_obj.context = ctx(span_obj.context));
@@ -116,7 +153,8 @@ const create = (name, options) => {
116
153
  const endRoot = root.end.bind(root);
117
154
  root.end = async () => {
118
155
  endRoot();
119
- await Promise.all(promises);
156
+ if (PROMISES.has(root))
157
+ await Promise.all(PROMISES.get(root));
120
158
  return options.exporter(spans, {
121
159
  ...(options.context || {}),
122
160
  ...sdk_object,
@@ -125,4 +163,6 @@ const create = (name, options) => {
125
163
  return root;
126
164
  };
127
165
 
166
+ exports.ADD_PROMISE = ADD_PROMISE;
167
+ exports.PROMISES = PROMISES;
128
168
  exports.create = create;
package/index.mjs CHANGED
@@ -1,17 +1,17 @@
1
1
  import { name, version } from 'rian/package.json';
2
2
  import * as tctx from 'tctx';
3
+ import { PROMISES as PROMISES$1, ADD_PROMISE as ADD_PROMISE$1 } from 'rian';
3
4
 
4
5
  const set_error = (scope, error) => {
5
6
  scope.set_context({
6
7
  error,
7
8
  });
8
9
  };
9
- const measure = (fn, // TODO: fn doesnt see scope correctly
10
- scope, promises, ...args) => {
10
+ const measureFn = (scope, fn, ...args) => {
11
11
  try {
12
12
  var r = fn(...args, scope), is_promise = r instanceof Promise;
13
- if (is_promise)
14
- promises.push(r
13
+ if (is_promise && PROMISES$1.has(scope))
14
+ ADD_PROMISE$1(scope, r
15
15
  .catch((e) => void set_error(scope, e))
16
16
  .finally(() => scope.end()));
17
17
  return r;
@@ -25,8 +25,44 @@ scope, promises, ...args) => {
25
25
  scope.end();
26
26
  }
27
27
  };
28
+ /**
29
+ * With a passed function — will start a span, and run the function, when the function finishes
30
+ * the span finishes.
31
+ *
32
+ * The measure method will return whatever the function is, so if it's a promise, it returns a
33
+ * promise and so on. Any error is caught and re thrown, and automatically tracked in the
34
+ * context under the `error` property.
35
+ *
36
+ * All promises are tracked, and awaited on a `tracer.end`.
37
+ *
38
+ * @example
39
+ *
40
+ * ```text
41
+ * const data = await measure(scope, get_data, 'user_id_123');
42
+ * ^ ^ ^
43
+ * | | |
44
+ * | | the first argument to get_data
45
+ * | function to be called
46
+ * return value from get_data
47
+ * ```
48
+ */
49
+ const measure = (scope, fn, // TODO: fn doesnt see scope correctly
50
+ ...args) => measureFn(scope, fn, ...args);
28
51
 
29
52
  // ==> impl
53
+ /**
54
+ * @internal
55
+ */
56
+ const PROMISES = new WeakMap();
57
+ /**
58
+ * @internal
59
+ */
60
+ const ADD_PROMISE = (scope, promise) => {
61
+ if (PROMISES.has(scope))
62
+ PROMISES.get(scope).push(promise);
63
+ else
64
+ PROMISES.set(scope, [promise]);
65
+ };
30
66
  /**
31
67
  * The default sampler;
32
68
  *
@@ -48,10 +84,12 @@ const sdk_object = {
48
84
  };
49
85
  const create = (name, options) => {
50
86
  const spans = new Set();
51
- const promises = [];
52
87
  const sampler = options.sampler || defaultSampler;
88
+ const sampler_callable = typeof sampler !== 'boolean';
53
89
  const span = (name, parent) => {
54
- const should_sample = sampler(name, parent, options.context);
90
+ const should_sample = sampler_callable
91
+ ? sampler(name, parent, options.context)
92
+ : sampler;
55
93
  const id = parent
56
94
  ? parent.child(should_sample)
57
95
  : tctx.make(should_sample);
@@ -65,10 +103,9 @@ const create = (name, options) => {
65
103
  };
66
104
  if (should_sample)
67
105
  spans.add(span_obj);
68
- const $ = (cb) => measure(cb, $, promises);
106
+ const $ = (cb) => measure($, cb);
69
107
  $.traceparent = id;
70
108
  $.fork = (name) => span(name, id);
71
- $.measure = (name, cb, ...args) => measure(cb, span(name, id), promises, ...args);
72
109
  $.set_context = (ctx) => {
73
110
  if (typeof ctx === 'function')
74
111
  return void (span_obj.context = ctx(span_obj.context));
@@ -94,7 +131,8 @@ const create = (name, options) => {
94
131
  const endRoot = root.end.bind(root);
95
132
  root.end = async () => {
96
133
  endRoot();
97
- await Promise.all(promises);
134
+ if (PROMISES.has(root))
135
+ await Promise.all(PROMISES.get(root));
98
136
  return options.exporter(spans, {
99
137
  ...(options.context || {}),
100
138
  ...sdk_object,
@@ -103,4 +141,4 @@ const create = (name, options) => {
103
141
  return root;
104
142
  };
105
143
 
106
- export { create };
144
+ export { ADD_PROMISE, PROMISES, create };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rian",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "Effective tracing for the edge and origins",
5
5
  "keywords": [
6
6
  "opentelemetry",
@@ -37,6 +37,10 @@
37
37
  "import": "./exporter.zipkin.mjs",
38
38
  "require": "./exporter.zipkin.js"
39
39
  },
40
+ "./utils": {
41
+ "import": "./utils.mjs",
42
+ "require": "./utils.js"
43
+ },
40
44
  "./package.json": "./package.json"
41
45
  },
42
46
  "main": "./index.js",
package/utils.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { Scope } from 'rian';
2
+
3
+ declare type MeasureFn = ((...args: [...args: any[]]) => any) | ((...args: [...args: any[], scope: Scope]) => any);
4
+ declare type RealMeasureFnParams<T extends unknown[]> = T extends [] ? [] : T extends [...rest: infer U, scope: Scope] ? U : T;
5
+ /**
6
+ * With a passed function — will start a span, and run the function, when the function finishes
7
+ * the span finishes.
8
+ *
9
+ * The measure method will return whatever the function is, so if it's a promise, it returns a
10
+ * promise and so on. Any error is caught and re thrown, and automatically tracked in the
11
+ * context under the `error` property.
12
+ *
13
+ * All promises are tracked, and awaited on a `tracer.end`.
14
+ *
15
+ * @example
16
+ *
17
+ * ```text
18
+ * const data = await measure(scope, get_data, 'user_id_123');
19
+ * ^ ^ ^
20
+ * | | |
21
+ * | | the first argument to get_data
22
+ * | function to be called
23
+ * return value from get_data
24
+ * ```
25
+ */
26
+ declare const measure: <Fn extends MeasureFn>(scope: Scope, fn: Fn, ...args: RealMeasureFnParams<Parameters<Fn>>) => ReturnType<Fn>;
27
+ /**
28
+ * Wraps any function with a measured scoped function. Useful for when defer function execution
29
+ * till a later time.
30
+ *
31
+ * @example
32
+ *
33
+ * ```js
34
+ * const wrapped = wrap(scope, my_function);
35
+ *
36
+ * // ... lots of things, where the access to `scope` is lost.
37
+ *
38
+ * wrapped();
39
+ * ```
40
+ */
41
+ declare const wrap: <Fn extends MeasureFn>(scope: Scope, fn: Fn) => Fn;
42
+
43
+ export { MeasureFn, measure, wrap };
package/utils.js ADDED
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ const rian = require('rian');
4
+
5
+ const set_error = (scope, error) => {
6
+ scope.set_context({
7
+ error,
8
+ });
9
+ };
10
+ const measureFn = (scope, fn, ...args) => {
11
+ try {
12
+ var r = fn(...args, scope), is_promise = r instanceof Promise;
13
+ if (is_promise && rian.PROMISES.has(scope))
14
+ rian.ADD_PROMISE(scope, 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
+ * With a passed function — will start a span, and run the function, when the function finishes
30
+ * the span finishes.
31
+ *
32
+ * The measure method will return whatever the function is, so if it's a promise, it returns a
33
+ * promise and so on. Any error is caught and re thrown, and automatically tracked in the
34
+ * context under the `error` property.
35
+ *
36
+ * All promises are tracked, and awaited on a `tracer.end`.
37
+ *
38
+ * @example
39
+ *
40
+ * ```text
41
+ * const data = await measure(scope, get_data, 'user_id_123');
42
+ * ^ ^ ^
43
+ * | | |
44
+ * | | the first argument to get_data
45
+ * | function to be called
46
+ * return value from get_data
47
+ * ```
48
+ */
49
+ const measure = (scope, fn, // TODO: fn doesnt see scope correctly
50
+ ...args) => measureFn(scope, fn, ...args);
51
+ /**
52
+ * Wraps any function with a measured scoped function. Useful for when defer function execution
53
+ * till a later time.
54
+ *
55
+ * @example
56
+ *
57
+ * ```js
58
+ * const wrapped = wrap(scope, my_function);
59
+ *
60
+ * // ... lots of things, where the access to `scope` is lost.
61
+ *
62
+ * wrapped();
63
+ * ```
64
+ */
65
+ const wrap = (scope, fn) => function () {
66
+ return measureFn(scope, fn, ...arguments);
67
+ };
68
+
69
+ exports.measure = measure;
70
+ exports.wrap = wrap;
package/utils.mjs ADDED
@@ -0,0 +1,67 @@
1
+ import { PROMISES, ADD_PROMISE } from 'rian';
2
+
3
+ const set_error = (scope, error) => {
4
+ scope.set_context({
5
+ error,
6
+ });
7
+ };
8
+ const measureFn = (scope, fn, ...args) => {
9
+ try {
10
+ var r = fn(...args, scope), is_promise = r instanceof Promise;
11
+ if (is_promise && PROMISES.has(scope))
12
+ ADD_PROMISE(scope, r
13
+ .catch((e) => void set_error(scope, e))
14
+ .finally(() => scope.end()));
15
+ return r;
16
+ }
17
+ catch (e) {
18
+ set_error(scope, e);
19
+ throw e;
20
+ }
21
+ finally {
22
+ if (is_promise !== true)
23
+ scope.end();
24
+ }
25
+ };
26
+ /**
27
+ * With a passed function — will start a span, and run the function, when the function finishes
28
+ * the span finishes.
29
+ *
30
+ * The measure method will return whatever the function is, so if it's a promise, it returns a
31
+ * promise and so on. Any error is caught and re thrown, and automatically tracked in the
32
+ * context under the `error` property.
33
+ *
34
+ * All promises are tracked, and awaited on a `tracer.end`.
35
+ *
36
+ * @example
37
+ *
38
+ * ```text
39
+ * const data = await measure(scope, get_data, 'user_id_123');
40
+ * ^ ^ ^
41
+ * | | |
42
+ * | | the first argument to get_data
43
+ * | function to be called
44
+ * return value from get_data
45
+ * ```
46
+ */
47
+ const measure = (scope, fn, // TODO: fn doesnt see scope correctly
48
+ ...args) => measureFn(scope, fn, ...args);
49
+ /**
50
+ * Wraps any function with a measured scoped function. Useful for when defer function execution
51
+ * till a later time.
52
+ *
53
+ * @example
54
+ *
55
+ * ```js
56
+ * const wrapped = wrap(scope, my_function);
57
+ *
58
+ * // ... lots of things, where the access to `scope` is lost.
59
+ *
60
+ * wrapped();
61
+ * ```
62
+ */
63
+ const wrap = (scope, fn) => function () {
64
+ return measureFn(scope, fn, ...arguments);
65
+ };
66
+
67
+ export { measure, wrap };