@mukhy/mtn-telemetry-sdk 1.0.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.
Files changed (52) hide show
  1. package/.github/workflows/node.js.yml +81 -0
  2. package/.github/workflows/npm-publish-github-packages.yml +53 -0
  3. package/README.md +146 -0
  4. package/__test__/demo-test.js +3 -0
  5. package/__test__/test-runner.js +54 -0
  6. package/__test__/test.js +5 -0
  7. package/apps/.gradle/8.9/checksums/checksums.lock +0 -0
  8. package/apps/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  9. package/apps/.gradle/8.9/fileChanges/last-build.bin +0 -0
  10. package/apps/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  11. package/apps/.gradle/8.9/gc.properties +0 -0
  12. package/apps/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  13. package/apps/.gradle/buildOutputCleanup/cache.properties +2 -0
  14. package/apps/.gradle/vcs-1/gc.properties +0 -0
  15. package/apps/build.gradle +14 -0
  16. package/dist/business.d.ts +26 -0
  17. package/dist/business.js +79 -0
  18. package/dist/context.d.ts +3 -0
  19. package/dist/context.js +27 -0
  20. package/dist/index.d.ts +7 -0
  21. package/dist/index.js +45 -0
  22. package/dist/instrumentations/app-state.d.ts +7 -0
  23. package/dist/instrumentations/app-state.js +58 -0
  24. package/dist/instrumentations/fetch.d.ts +1 -0
  25. package/dist/instrumentations/fetch.js +41 -0
  26. package/dist/instrumentations/react-nav.d.ts +1 -0
  27. package/dist/instrumentations/react-nav.js +23 -0
  28. package/dist/providers.d.ts +13 -0
  29. package/dist/providers.js +87 -0
  30. package/dist/resource.d.ts +2 -0
  31. package/dist/resource.js +32 -0
  32. package/dist/types.d.ts +15 -0
  33. package/dist/types.js +2 -0
  34. package/package.json +52 -0
  35. package/src/business.tsx +92 -0
  36. package/src/context.js +74 -0
  37. package/src/context.ts +24 -0
  38. package/src/index.js +127 -0
  39. package/src/index.ts +47 -0
  40. package/src/instrumentations/app-state.js +70 -0
  41. package/src/instrumentations/app-state.ts +64 -0
  42. package/src/instrumentations/fetch.js +106 -0
  43. package/src/instrumentations/fetch.ts +41 -0
  44. package/src/instrumentations/react-nav.js +73 -0
  45. package/src/instrumentations/react-nav.ts +23 -0
  46. package/src/providers.js +83 -0
  47. package/src/providers.ts +95 -0
  48. package/src/resource.js +22 -0
  49. package/src/resource.ts +40 -0
  50. package/src/types.js +2 -0
  51. package/src/types.ts +22 -0
  52. package/tsconfig.json +18 -0
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installFetchInstrumentation = installFetchInstrumentation;
4
+ const api_1 = require("@opentelemetry/api");
5
+ function installFetchInstrumentation(_tracerProvider) {
6
+ const tracer = api_1.trace.getTracer('mtn-sdk:fetch');
7
+ const originalFetch = globalThis.fetch;
8
+ if (!originalFetch)
9
+ return async () => { };
10
+ globalThis.fetch = (async (input, init) => {
11
+ const url = typeof input === 'string' ? input : input === null || input === void 0 ? void 0 : input.url;
12
+ const method = ((init === null || init === void 0 ? void 0 : init.method) || (typeof input !== 'string' ? input === null || input === void 0 ? void 0 : input.method : 'GET') || 'GET').toUpperCase();
13
+ return tracer.startActiveSpan(`HTTP ${method}`, { kind: api_1.SpanKind.CLIENT, attributes: {
14
+ 'http.method': method,
15
+ 'http.url': String(url),
16
+ } }, async (span) => {
17
+ var _a, _b;
18
+ try {
19
+ const headers = new Headers((init === null || init === void 0 ? void 0 : init.headers) || (typeof input !== 'string' ? input === null || input === void 0 ? void 0 : input.headers : undefined) || {});
20
+ const spanContext = span.spanContext();
21
+ if (spanContext && spanContext.traceId && spanContext.spanId) {
22
+ headers.set('traceparent', `00-${spanContext.traceId}-${spanContext.spanId}-01`);
23
+ }
24
+ const res = await originalFetch(typeof input === 'string' ? url : { ...input, headers }, init ? { ...init, headers } : undefined);
25
+ span.setAttribute('http.status_code', res.status);
26
+ if (!res.ok)
27
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR });
28
+ return res;
29
+ }
30
+ catch (e) {
31
+ (_a = span.recordException) === null || _a === void 0 ? void 0 : _a.call(span, e);
32
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: String((_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : e) });
33
+ throw e;
34
+ }
35
+ finally {
36
+ span.end();
37
+ }
38
+ });
39
+ });
40
+ return async () => { globalThis.fetch = originalFetch; };
41
+ }
@@ -0,0 +1 @@
1
+ export declare function installReactNavigationInstrumentation(_tracerProvider: any): () => Promise<void>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installReactNavigationInstrumentation = installReactNavigationInstrumentation;
4
+ const api_1 = require("@opentelemetry/api");
5
+ function installReactNavigationInstrumentation(_tracerProvider) {
6
+ const tracer = api_1.trace.getTracer('mtn-sdk:navigation');
7
+ let unsubscribe;
8
+ function attach(navRef) {
9
+ var _a;
10
+ if (!navRef)
11
+ return;
12
+ unsubscribe = (_a = navRef.addListener) === null || _a === void 0 ? void 0 : _a.call(navRef, 'state', () => {
13
+ var _a, _b;
14
+ const route = (_a = navRef.getCurrentRoute) === null || _a === void 0 ? void 0 : _a.call(navRef);
15
+ const name = (_b = route === null || route === void 0 ? void 0 : route.name) !== null && _b !== void 0 ? _b : 'unknown';
16
+ tracer.startActiveSpan(`Screen ${name}`, { kind: api_1.SpanKind.INTERNAL, attributes: { 'screen.name': name } }, (span) => span.end());
17
+ });
18
+ }
19
+ function detach() { unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe(); }
20
+ const shutdown = async () => { detach(); };
21
+ globalThis.__MTN_OTEL_ATTACH_NAV__ = attach;
22
+ return shutdown;
23
+ }
@@ -0,0 +1,13 @@
1
+ import { NodeSDK } from '@opentelemetry/sdk-node';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
3
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
4
+ import { Resource } from '@opentelemetry/resources';
5
+ import type { OTelRNOptions } from './types';
6
+ export declare function buildProviders(opts: OTelRNOptions & {
7
+ resource: Resource;
8
+ }): {
9
+ sdk: NodeSDK;
10
+ shutdown: () => Promise<void>;
11
+ traceExporter: OTLPTraceExporter;
12
+ metricExporter: OTLPMetricExporter;
13
+ };
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildProviders = buildProviders;
4
+ const sdk_node_1 = require("@opentelemetry/sdk-node");
5
+ const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
6
+ const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
7
+ const exporter_metrics_otlp_http_1 = require("@opentelemetry/exporter-metrics-otlp-http");
8
+ function buildProviders(opts) {
9
+ var _a, _b, _c, _d;
10
+ const traceExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({
11
+ url: (_a = opts.otlp.tracesUrl) !== null && _a !== void 0 ? _a : 'http://localhost:4318/v1/traces',
12
+ headers: (_b = opts.otlp.headers) !== null && _b !== void 0 ? _b : {},
13
+ });
14
+ const metricExporter = new exporter_metrics_otlp_http_1.OTLPMetricExporter({
15
+ url: (_c = opts.otlp.metricsUrl) !== null && _c !== void 0 ? _c : 'http://localhost:4318/v1/metrics',
16
+ headers: (_d = opts.otlp.headers) !== null && _d !== void 0 ? _d : {},
17
+ });
18
+ const sdk = new sdk_node_1.NodeSDK({
19
+ resource: opts.resource,
20
+ traceExporter,
21
+ metricReader: new sdk_metrics_1.PeriodicExportingMetricReader({
22
+ exporter: metricExporter,
23
+ exportIntervalMillis: 60000,
24
+ }),
25
+ });
26
+ const shutdown = async () => {
27
+ await sdk.shutdown();
28
+ };
29
+ // start immediately
30
+ sdk.start();
31
+ return { sdk, shutdown, traceExporter, metricExporter };
32
+ }
33
+ // import { NodeSDK } from '@opentelemetry/sdk-node';
34
+ // import { BatchSpanProcessor, ParentBasedSampler, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';
35
+ // import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
36
+ // import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
37
+ // import { Resource } from '@opentelemetry/resources';
38
+ // import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
39
+ //
40
+ // export function buildProviders(args: {
41
+ // resource: Resource;
42
+ // tracesUrl: string;
43
+ // metricsUrl?: string;
44
+ // headers?: Record<string, string>;
45
+ // samplingRatio: number;
46
+ // }) {
47
+ // // Configure trace exporter
48
+ // const traceExporter = new OTLPTraceExporter({
49
+ // url: args.tracesUrl,
50
+ // headers: args.headers,
51
+ // });
52
+ //
53
+ // // Configure metric exporter (optional)
54
+ // const metricExporter = args.metricsUrl
55
+ // ? new OTLPMetricExporter({
56
+ // url: args.metricsUrl,
57
+ // headers: args.headers,
58
+ // })
59
+ // : undefined;
60
+ //
61
+ // // Create NodeSDK instance
62
+ // const sdk = new NodeSDK({
63
+ // resource: args.resource,
64
+ // sampler: new ParentBasedSampler({
65
+ // root: new TraceIdRatioBasedSampler(args.samplingRatio),
66
+ // }),
67
+ // spanProcessor: new BatchSpanProcessor(traceExporter, {
68
+ // maxQueueSize: 2048,
69
+ // scheduledDelayMillis: 5000,
70
+ // exportTimeoutMillis: 10000,
71
+ // maxExportBatchSize: 256,
72
+ // }),
73
+ // metricReader: metricExporter
74
+ // ? new PeriodicExportingMetricReader({
75
+ // exporter: metricExporter,
76
+ // exportIntervalMillis: 60000,
77
+ // exportTimeoutMillis: 15000,
78
+ // })
79
+ // : undefined,
80
+ // });
81
+ //
82
+ // async function shutdown() {
83
+ // await sdk.shutdown();
84
+ // }
85
+ //
86
+ // return { sdk, shutdown };
87
+ // }
@@ -0,0 +1,2 @@
1
+ import type { OTelRNOptions } from './types';
2
+ export declare function buildResource(opts: OTelRNOptions): any;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildResource = buildResource;
7
+ // import resource from the *build* path
8
+ // import directly from the implementation file (not just the type index)
9
+ // import the runtime implementation (not just the type)
10
+ const ResourceImpl = require("@opentelemetry/resources/build/src/Resource");
11
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
12
+ const react_native_device_info_1 = __importDefault(require("react-native-device-info"));
13
+ // get the runtime Resource class
14
+ const { Resource } = ResourceImpl;
15
+ function buildResource(opts) {
16
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
17
+ const attrs = {
18
+ [semantic_conventions_1.SEMRESATTRS_SERVICE_NAME]: opts.serviceName,
19
+ [semantic_conventions_1.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: (_a = opts.environment) !== null && _a !== void 0 ? _a : 'dev',
20
+ [semantic_conventions_1.SEMRESATTRS_SERVICE_VERSION]: (_d = (_b = opts.release) !== null && _b !== void 0 ? _b : (_c = react_native_device_info_1.default.getVersion) === null || _c === void 0 ? void 0 : _c.call(react_native_device_info_1.default)) !== null && _d !== void 0 ? _d : 'unknown',
21
+ 'device.manufacturer': (_f = (_e = react_native_device_info_1.default.getManufacturerSync) === null || _e === void 0 ? void 0 : _e.call(react_native_device_info_1.default)) !== null && _f !== void 0 ? _f : 'unknown',
22
+ 'device.model': (_h = (_g = react_native_device_info_1.default.getModel) === null || _g === void 0 ? void 0 : _g.call(react_native_device_info_1.default)) !== null && _h !== void 0 ? _h : 'unknown',
23
+ 'device.os': `${(_k = (_j = react_native_device_info_1.default.getSystemName) === null || _j === void 0 ? void 0 : _j.call(react_native_device_info_1.default)) !== null && _k !== void 0 ? _k : 'unknown'} ${(_m = (_l = react_native_device_info_1.default.getSystemVersion) === null || _l === void 0 ? void 0 : _l.call(react_native_device_info_1.default)) !== null && _m !== void 0 ? _m : ''}`,
24
+ 'app.bundle': (_p = (_o = react_native_device_info_1.default.getBundleId) === null || _o === void 0 ? void 0 : _o.call(react_native_device_info_1.default)) !== null && _p !== void 0 ? _p : 'unknown',
25
+ 'app.build': (_r = (_q = react_native_device_info_1.default.getBuildNumber) === null || _q === void 0 ? void 0 : _q.call(react_native_device_info_1.default)) !== null && _r !== void 0 ? _r : 'unknown',
26
+ 'app.isEmulator': (_t = (_s = react_native_device_info_1.default.isEmulatorSync) === null || _s === void 0 ? void 0 : _s.call(react_native_device_info_1.default)) !== null && _t !== void 0 ? _t : false,
27
+ ...opts.attributes,
28
+ };
29
+ const base = Resource.default();
30
+ const custom = new Resource({ attributes: attrs });
31
+ return base.merge(custom);
32
+ }
@@ -0,0 +1,15 @@
1
+ export interface OTelRNOptions {
2
+ serviceName: string;
3
+ environment?: string;
4
+ release?: string;
5
+ otlp: {
6
+ tracesUrl: string;
7
+ metricsUrl?: string;
8
+ headers?: Record<string, string>;
9
+ };
10
+ enableFetch?: boolean;
11
+ enableNavigation?: boolean;
12
+ enableAppState?: boolean;
13
+ samplingRatio?: number;
14
+ attributes?: Record<string, any>;
15
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@mukhy/mtn-telemetry-sdk",
3
+ "version": "1.0.0",
4
+ "description": "MTN Telemetry SDK for React and React Native applications",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "clean": "rm -rf dist",
9
+ "build": "tsc",
10
+ "prepare": "yarn run clean && yarn run build",
11
+ "test": "echo \"No tests yet\" && exit 0"
12
+ },
13
+ "keywords": [
14
+ "SDK",
15
+ "telemetry",
16
+ "MTN",
17
+ "react",
18
+ "react-native",
19
+ "typescript"
20
+ ],
21
+ "author": "Muutassim Mukhtar <muutassim.mukhtar@emtn.com>",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/triplemcoder14/mtn-telemetry-sdk.git"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "registry": "https://registry.npmjs.org/"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^19.2.2",
33
+ "@types/react-native": "^0.73.0",
34
+ "typescript": "^5.1.6"
35
+ },
36
+ "peerDependencies": {
37
+ "react": ">=18.0.0",
38
+ "react-native": ">=0.72.0"
39
+ },
40
+ "dependencies": {
41
+ "@opentelemetry/api": "^1.9.0",
42
+ "@opentelemetry/exporter-metrics-otlp-http": "^0.206.0",
43
+ "@opentelemetry/exporter-trace-otlp-http": "^0.206.0",
44
+ "@opentelemetry/resources": "^2.1.0",
45
+ "@opentelemetry/sdk-metrics": "^2.1.0",
46
+ "@opentelemetry/sdk-node": "^0.206.0",
47
+ "@opentelemetry/sdk-trace-base": "^2.1.0",
48
+ "@opentelemetry/sdk-trace-node": "^2.1.0",
49
+ "@opentelemetry/semantic-conventions": "^1.37.0",
50
+ "react-native-device-info": "^14.1.1"
51
+ }
52
+ }
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import { Pressable, PressableProps } from 'react-native';
3
+ import { trace, SpanKind } from '@opentelemetry/api';
4
+
5
+ /**
6
+ * BusinessTracer — captures business journeys and steps
7
+ */
8
+ export class BusinessTracer {
9
+ private static currentJourney?: { name: string; startTime: number };
10
+
11
+ /**
12
+ * Start a business journey (e.g. "UserOnboarding", "PurchaseFlow")
13
+ */
14
+ static start(journeyName: string, attrs: Record<string, any> = {}) {
15
+ const tracer = trace.getTracer('mtn-sdk:business');
16
+ const span = tracer.startSpan(`Journey ${journeyName}`, {
17
+ kind: SpanKind.INTERNAL,
18
+ attributes: {
19
+ 'business.journey': journeyName,
20
+ ...attrs,
21
+ },
22
+ });
23
+ this.currentJourney = { name: journeyName, startTime: Date.now() };
24
+ span.end(); // parent marker span; steps are separate child spans
25
+ }
26
+
27
+ /**
28
+ * Record a business step within a journey (e.g. "PaymentAuthorized")
29
+ */
30
+ static step(stepName: string, attrs: Record<string, any> = {}) {
31
+ const tracer = trace.getTracer('mtn-sdk:business');
32
+ const journey = this.currentJourney?.name ?? 'unknown';
33
+ const span = tracer.startSpan(`Step ${stepName}`, {
34
+ kind: SpanKind.INTERNAL,
35
+ attributes: {
36
+ 'business.journey': journey,
37
+ 'business.step': stepName,
38
+ ...attrs,
39
+ },
40
+ });
41
+ span.end();
42
+ }
43
+
44
+ /**
45
+ * Complete a business journey
46
+ */
47
+ static complete(attrs: Record<string, any> = {}) {
48
+ const tracer = trace.getTracer('mtn-sdk:business');
49
+ const journey = this.currentJourney?.name ?? 'unknown';
50
+ const dur = this.currentJourney
51
+ ? Date.now() - this.currentJourney.startTime
52
+ : undefined;
53
+
54
+ const span = tracer.startSpan(`Journey ${journey} Complete`, {
55
+ kind: SpanKind.INTERNAL,
56
+ attributes: {
57
+ 'business.journey': journey,
58
+ 'business.completed': true,
59
+ 'business.duration_ms': dur,
60
+ ...attrs,
61
+ },
62
+ });
63
+
64
+ span.end();
65
+ this.currentJourney = undefined;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * TrackedPressable — wraps a Pressable and records user interactions as steps
71
+ */
72
+ export function TrackedPressable({
73
+ onPress,
74
+ accessibilityLabel,
75
+ children,
76
+ ...rest
77
+ }: PressableProps & { children?: React.ReactNode }) {
78
+ const label =
79
+ (accessibilityLabel as string) ||
80
+ (typeof children === 'string' ? children : 'pressable');
81
+
82
+ const handlePress = (e: any) => {
83
+ BusinessTracer.step(`tap:${label}`);
84
+ onPress?.(e);
85
+ };
86
+
87
+ return (
88
+ <Pressable {...rest} onPress={handlePress}>
89
+ {children}
90
+ </Pressable>
91
+ );
92
+ }
package/src/context.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.startActiveSpan = startActiveSpan;
40
+ exports.withParent = withParent;
41
+ var api_1 = require("@opentelemetry/api");
42
+ function startActiveSpan(name, fn, kind) {
43
+ var _this = this;
44
+ if (kind === void 0) { kind = api_1.SpanKind.INTERNAL; }
45
+ var tracer = api_1.trace.getTracer('mtn-sdk');
46
+ return tracer.startActiveSpan(name, { kind: kind }, function (span) { return __awaiter(_this, void 0, void 0, function () {
47
+ var result, err_1;
48
+ var _a, _b;
49
+ return __generator(this, function (_c) {
50
+ switch (_c.label) {
51
+ case 0:
52
+ _c.trys.push([0, 2, 3, 4]);
53
+ return [4 /*yield*/, fn(span)];
54
+ case 1:
55
+ result = _c.sent();
56
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
57
+ return [2 /*return*/, result];
58
+ case 2:
59
+ err_1 = _c.sent();
60
+ (_a = span.recordException) === null || _a === void 0 ? void 0 : _a.call(span, err_1);
61
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: String((_b = err_1 === null || err_1 === void 0 ? void 0 : err_1.message) !== null && _b !== void 0 ? _b : err_1) });
62
+ throw err_1;
63
+ case 3:
64
+ span.end();
65
+ return [7 /*endfinally*/];
66
+ case 4: return [2 /*return*/];
67
+ }
68
+ });
69
+ }); });
70
+ }
71
+ function withParent(parentContext, fn) {
72
+ if (parentContext === void 0) { parentContext = api_1.context.active(); }
73
+ return api_1.context.with(parentContext, fn);
74
+ }
package/src/context.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { context, trace, SpanKind, SpanStatusCode } from '@opentelemetry/api';
2
+
3
+
4
+ export function startActiveSpan<T>(name: string, fn: (span: any) => Promise<T> | T, kind: SpanKind = SpanKind.INTERNAL) {
5
+ const tracer = trace.getTracer('mtn-sdk');
6
+ return tracer.startActiveSpan(name, { kind }, async (span) => {
7
+ try {
8
+ const result = await fn(span);
9
+ span.setStatus({ code: SpanStatusCode.OK });
10
+ return result;
11
+ } catch (err: any) {
12
+ span.recordException?.(err);
13
+ span.setStatus({ code: SpanStatusCode.ERROR, message: String(err?.message ?? err) });
14
+ throw err;
15
+ } finally {
16
+ span.end();
17
+ }
18
+ });
19
+ }
20
+
21
+
22
+ export function withParent<T>(parentContext = context.active(), fn: () => T): T {
23
+ return context.with(parentContext, fn);
24
+ }
package/src/index.js ADDED
@@ -0,0 +1,127 @@
1
+ yarn"use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
+ return new (P || (P = Promise))(function (resolve, reject) {
19
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
23
+ });
24
+ };
25
+ var __generator = (this && this.__generator) || function (thisArg, body) {
26
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
27
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
28
+ function verb(n) { return function (v) { return step([n, v]); }; }
29
+ function step(op) {
30
+ if (f) throw new TypeError("Generator is already executing.");
31
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
32
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
33
+ if (y = 0, t) op = [op[0] & 2, t.value];
34
+ switch (op[0]) {
35
+ case 0: case 1: t = op; break;
36
+ case 4: _.label++; return { value: op[1], done: false };
37
+ case 5: _.label++; y = op[1]; op = [0]; continue;
38
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
39
+ default:
40
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
41
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
42
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
43
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
44
+ if (t[2]) _.ops.pop();
45
+ _.trys.pop(); continue;
46
+ }
47
+ op = body.call(thisArg, _);
48
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
49
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
+ }
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.MTNOTel = void 0;
54
+ var providers_1 = require("./providers");
55
+ var resource_1 = require("./resource");
56
+ var fetch_1 = require("./instrumentations/fetch");
57
+ var react_nav_1 = require("./instrumentations/react-nav");
58
+ // import { installReactNavigationInstrumentation } from './instrumentations/react-navigation';
59
+ var app_state_1 = require("./instrumentations/app-state");
60
+ var MTNOTel = /** @class */ (function () {
61
+ function MTNOTel() {
62
+ this.shutdownFns = [];
63
+ }
64
+ MTNOTel.init = function (opts) {
65
+ var _a;
66
+ if (MTNOTel._instance)
67
+ return MTNOTel._instance;
68
+ var resource = (0, resource_1.buildResource)(opts);
69
+ var _b = (0, providers_1.buildProviders)({
70
+ resource: resource,
71
+ tracesUrl: opts.otlp.tracesUrl,
72
+ metricsUrl: opts.otlp.metricsUrl,
73
+ headers: opts.otlp.headers,
74
+ samplingRatio: (_a = opts.samplingRatio) !== null && _a !== void 0 ? _a : 1.0,
75
+ }), tracerProvider = _b.tracerProvider, meterProvider = _b.meterProvider, shutdown = _b.shutdown;
76
+ var sdk = new MTNOTel();
77
+ sdk.shutdownFns.push(shutdown);
78
+ if (opts.enableFetch) {
79
+ sdk.shutdownFns.push((0, fetch_1.installFetchInstrumentation)(tracerProvider));
80
+ }
81
+ if (opts.enableNavigation) {
82
+ sdk.shutdownFns.push((0, react_nav_1.installReactNavigationInstrumentation)(tracerProvider));
83
+ }
84
+ if (opts.enableAppState) {
85
+ sdk.shutdownFns.push((0, app_state_1.installAppStateInstrumentation)(tracerProvider, meterProvider));
86
+ }
87
+ MTNOTel._instance = sdk;
88
+ return sdk;
89
+ };
90
+ MTNOTel.prototype.flushAndShutdown = function () {
91
+ return __awaiter(this, void 0, void 0, function () {
92
+ var _i, _a, fn, _b;
93
+ return __generator(this, function (_c) {
94
+ switch (_c.label) {
95
+ case 0:
96
+ _i = 0, _a = this.shutdownFns.reverse();
97
+ _c.label = 1;
98
+ case 1:
99
+ if (!(_i < _a.length)) return [3 /*break*/, 6];
100
+ fn = _a[_i];
101
+ _c.label = 2;
102
+ case 2:
103
+ _c.trys.push([2, 4, , 5]);
104
+ return [4 /*yield*/, fn()];
105
+ case 3:
106
+ _c.sent();
107
+ return [3 /*break*/, 5];
108
+ case 4:
109
+ _b = _c.sent();
110
+ return [3 /*break*/, 5];
111
+ case 5:
112
+ _i++;
113
+ return [3 /*break*/, 1];
114
+ case 6:
115
+ MTNOTel._instance = null;
116
+ return [2 /*return*/];
117
+ }
118
+ });
119
+ });
120
+ };
121
+ MTNOTel._instance = null;
122
+ return MTNOTel;
123
+ }());
124
+ exports.MTNOTel = MTNOTel;
125
+ __exportStar(require("./types"), exports);
126
+ __exportStar(require("./context"), exports);
127
+ __exportStar(require("./business"), exports);
package/src/index.ts ADDED
@@ -0,0 +1,47 @@
1
+ import { buildProviders } from './providers';
2
+ import { buildResource } from './resource';
3
+ import { installFetchInstrumentation } from './instrumentations/fetch';
4
+ import { installReactNavigationInstrumentation } from './instrumentations/react-nav';
5
+ import { installAppStateInstrumentation } from './instrumentations/app-state';
6
+ import { trace, metrics } from '@opentelemetry/api';
7
+ import type { OTelRNOptions } from './types';
8
+
9
+ export class MTNOTel {
10
+ private static _instance: MTNOTel | null = null;
11
+ private shutdownFns: Array<() => Promise<void>> = [];
12
+
13
+ static async init(opts: OTelRNOptions) {
14
+ if (MTNOTel._instance) return MTNOTel._instance;
15
+
16
+ // await and async resource builder
17
+ const resource = await buildResource(opts);
18
+ const { sdk, shutdown } = buildProviders({ ...opts, resource });
19
+
20
+ const instance = new MTNOTel();
21
+ instance.shutdownFns.push(shutdown);
22
+
23
+ // using otel api to get global tracer and meter
24
+ const tracer = trace.getTracer(opts.serviceName);
25
+ const meter = metrics.getMeter(opts.serviceName);
26
+
27
+ // conditionally install instrumentation
28
+ if (opts.enableFetch) {
29
+ instance.shutdownFns.push(installFetchInstrumentation(tracer));
30
+ }
31
+ if (opts.enableNavigation) {
32
+ instance.shutdownFns.push(installReactNavigationInstrumentation(tracer));
33
+ }
34
+ if (opts.enableAppState) {
35
+ instance.shutdownFns.push(installAppStateInstrumentation(tracer, meter));
36
+ }
37
+
38
+ MTNOTel._instance = instance;
39
+ return instance;
40
+ }
41
+
42
+ async flushAndShutdown() {
43
+ for (const fn of this.shutdownFns) {
44
+ await fn();
45
+ }
46
+ }
47
+ }