@coralogix/browser 2.11.1 → 2.13.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.
- package/CHANGELOG.md +12 -0
- package/README.md +23 -0
- package/index.esm2.js +163 -1
- package/package.json +1 -1
- package/src/processors/CoralogixExporter.d.ts +1 -0
- package/src/traces-exporter/trace-exporter.const.d.ts +4 -0
- package/src/traces-exporter/trace-exporter.d.ts +3 -0
- package/src/traces-exporter/traces-exporter.converter.d.ts +4 -0
- package/src/traces-exporter/traces-exporter.types.d.ts +71 -0
- package/src/traces-exporter/traces-exporter.utils.d.ts +9 -0
- package/src/types.d.ts +2 -0
- package/src/version.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 2.13.0 (2025-12-07)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- **traces-exporter:** improve trace metadata encoding
|
|
6
|
+
|
|
7
|
+
## 2.12.0 (2025-11-30)
|
|
8
|
+
|
|
9
|
+
### 🚀 Features
|
|
10
|
+
|
|
11
|
+
- Introduced the tracesExporter callback, enabling custom processing or exporting of collected trace events.
|
|
12
|
+
|
|
1
13
|
## 2.11.1 (2025-11-24)
|
|
2
14
|
|
|
3
15
|
### 🩹 Fixes
|
package/README.md
CHANGED
|
@@ -660,6 +660,7 @@ CoralogixRum.init({
|
|
|
660
660
|
```
|
|
661
661
|
|
|
662
662
|
#### Custom Propagation
|
|
663
|
+
|
|
663
664
|
```javascript
|
|
664
665
|
CoralogixRum.init({
|
|
665
666
|
// ...
|
|
@@ -773,8 +774,10 @@ CoralogixRum.init({
|
|
|
773
774
|
```
|
|
774
775
|
|
|
775
776
|
#### ignoreProxyUrlParams
|
|
777
|
+
|
|
776
778
|
If you want the SDK to ignore the cxforward parameter and always send data to the proxy URL directly, you can use the ignoreProxyUrlParams option.
|
|
777
779
|
By default, this option is disabled.
|
|
780
|
+
|
|
778
781
|
```javascript
|
|
779
782
|
CoralogixRum.init({
|
|
780
783
|
// ...
|
|
@@ -901,6 +904,26 @@ const customTracer = CoralogixRum.getCustomTracer({
|
|
|
901
904
|
// ... your code
|
|
902
905
|
```
|
|
903
906
|
|
|
907
|
+
### Traces Exporter
|
|
908
|
+
|
|
909
|
+
The `tracesExporter` callback gives you full control over how collected trace events are handled.
|
|
910
|
+
It receives a `TraceExporterData` object containing all trace data that the SDK has collected.
|
|
911
|
+
|
|
912
|
+
```ts
|
|
913
|
+
CoralogixRum.init({
|
|
914
|
+
tracesExporter: (data: TraceExporterData) => {
|
|
915
|
+
// Example: forward traces to your own backend endpoint
|
|
916
|
+
fetch('https://api.mycompany.com/rum-traces', {
|
|
917
|
+
method: 'POST',
|
|
918
|
+
headers: {
|
|
919
|
+
'Content-Type': 'application/json',
|
|
920
|
+
},
|
|
921
|
+
body: JSON.stringify(data),
|
|
922
|
+
});
|
|
923
|
+
},
|
|
924
|
+
});
|
|
925
|
+
```
|
|
926
|
+
|
|
904
927
|
### Soft Navigations — Experimental
|
|
905
928
|
|
|
906
929
|
Soft navigations are navigations that do not trigger a full page reload, such as SPA navigations. Defaults to false.
|
package/index.esm2.js
CHANGED
|
@@ -3381,6 +3381,157 @@ function isProcessorShouldStop(isActive) {
|
|
|
3381
3381
|
return !isActive || !!((_a = getSessionManager()) === null || _a === void 0 ? void 0 : _a.isIdleActive);
|
|
3382
3382
|
}
|
|
3383
3383
|
|
|
3384
|
+
var NANOS_IN_SECOND = 1000000000;
|
|
3385
|
+
var NANOS_PER_MILLISECOND = 1000000;
|
|
3386
|
+
var MAX_FUTURE_NANOS = 60 * 60 * NANOS_IN_SECOND;
|
|
3387
|
+
var MAX_PAST_NANOS = 24 * 60 * 60 * NANOS_IN_SECOND;
|
|
3388
|
+
|
|
3389
|
+
function toOtlpKeyValue(key, value) {
|
|
3390
|
+
if (!value) {
|
|
3391
|
+
return { key: key, value: { string_value: '' } };
|
|
3392
|
+
}
|
|
3393
|
+
switch (typeof value) {
|
|
3394
|
+
case 'string':
|
|
3395
|
+
return { key: key, value: { string_value: value } };
|
|
3396
|
+
case 'number':
|
|
3397
|
+
if (!Number.isFinite(value)) {
|
|
3398
|
+
return {
|
|
3399
|
+
key: key,
|
|
3400
|
+
value: { string_value: String(value) },
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3403
|
+
return Number.isInteger(value)
|
|
3404
|
+
? { key: key, value: { int_value: value } }
|
|
3405
|
+
: { key: key, value: { double_value: value } };
|
|
3406
|
+
case 'boolean':
|
|
3407
|
+
return { key: key, value: { bool_value: value } };
|
|
3408
|
+
default:
|
|
3409
|
+
return { key: key, value: { string_value: '' } };
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
function toOtlpAttributes(attributes) {
|
|
3413
|
+
if (!attributes)
|
|
3414
|
+
return [];
|
|
3415
|
+
return Object.entries(attributes).map(function (_a) {
|
|
3416
|
+
var _b = __read$1(_a, 2), k = _b[0], v = _b[1];
|
|
3417
|
+
return toOtlpKeyValue(k, v);
|
|
3418
|
+
});
|
|
3419
|
+
}
|
|
3420
|
+
function timestampToNanosNumber(timestamp) {
|
|
3421
|
+
var _a = __read$1(timestamp, 2), seconds = _a[0], nanos = _a[1];
|
|
3422
|
+
return seconds * NANOS_IN_SECOND + nanos;
|
|
3423
|
+
}
|
|
3424
|
+
function timestampToNanosString(timestamp) {
|
|
3425
|
+
var _a = __read$1(timestamp, 2), seconds = _a[0], nanos = _a[1];
|
|
3426
|
+
var secondsPart = String(seconds);
|
|
3427
|
+
var nanosPart = String(nanos).padStart(9, '0');
|
|
3428
|
+
return secondsPart + nanosPart;
|
|
3429
|
+
}
|
|
3430
|
+
function mapStatusCodeToOtlp(code) {
|
|
3431
|
+
var _a;
|
|
3432
|
+
if (code == null)
|
|
3433
|
+
return undefined;
|
|
3434
|
+
var STATUS_CODE_MAP = {
|
|
3435
|
+
0: 'STATUS_CODE_UNSET',
|
|
3436
|
+
1: 'STATUS_CODE_OK',
|
|
3437
|
+
2: 'STATUS_CODE_ERROR',
|
|
3438
|
+
};
|
|
3439
|
+
return (_a = STATUS_CODE_MAP[code]) !== null && _a !== void 0 ? _a : 'STATUS_CODE_UNSET';
|
|
3440
|
+
}
|
|
3441
|
+
function toOtlpStatus(spanStatus) {
|
|
3442
|
+
if (!spanStatus)
|
|
3443
|
+
return undefined;
|
|
3444
|
+
var code = mapStatusCodeToOtlp(spanStatus.code);
|
|
3445
|
+
var message = spanStatus.message;
|
|
3446
|
+
if (!code && !message)
|
|
3447
|
+
return undefined;
|
|
3448
|
+
return __assign({ code: code !== null && code !== void 0 ? code : 'STATUS_CODE_UNSET' }, (message ? { message: message } : {}));
|
|
3449
|
+
}
|
|
3450
|
+
function isWithinAllowedWindow(start, now) {
|
|
3451
|
+
return start <= now + MAX_FUTURE_NANOS && start >= now - MAX_PAST_NANOS;
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
function buildExporterPayload(logs) {
|
|
3455
|
+
var e_1, _a;
|
|
3456
|
+
var _b;
|
|
3457
|
+
var resourceSpans = [];
|
|
3458
|
+
var nowUnixNano = Date.now() * NANOS_PER_MILLISECOND;
|
|
3459
|
+
try {
|
|
3460
|
+
for (var logs_1 = __values$1(logs), logs_1_1 = logs_1.next(); !logs_1_1.done; logs_1_1 = logs_1.next()) {
|
|
3461
|
+
var entry = logs_1_1.value;
|
|
3462
|
+
var instrumentationData = entry.instrumentation_data;
|
|
3463
|
+
if (!instrumentationData)
|
|
3464
|
+
continue;
|
|
3465
|
+
var spanJson = mapCxSpanToOtlpSpan(instrumentationData.otelSpan);
|
|
3466
|
+
if (!spanJson)
|
|
3467
|
+
continue;
|
|
3468
|
+
var startNanos = timestampToNanosNumber(instrumentationData.otelSpan.startTime);
|
|
3469
|
+
if (!isWithinAllowedWindow(startNanos, nowUnixNano))
|
|
3470
|
+
continue;
|
|
3471
|
+
var resource = mapEntryToOtlpResource(entry, (_b = instrumentationData.otelResource) === null || _b === void 0 ? void 0 : _b.attributes);
|
|
3472
|
+
var scopeSpans = {
|
|
3473
|
+
spans: [spanJson],
|
|
3474
|
+
};
|
|
3475
|
+
resourceSpans.push({ resource: resource, scope_spans: [scopeSpans] });
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3479
|
+
finally {
|
|
3480
|
+
try {
|
|
3481
|
+
if (logs_1_1 && !logs_1_1.done && (_a = logs_1.return)) _a.call(logs_1);
|
|
3482
|
+
}
|
|
3483
|
+
finally { if (e_1) throw e_1.error; }
|
|
3484
|
+
}
|
|
3485
|
+
return { resource_spans: resourceSpans };
|
|
3486
|
+
}
|
|
3487
|
+
function stripOtelFieldsFromLogs(logs) {
|
|
3488
|
+
return logs.map(function (_a) {
|
|
3489
|
+
_a.instrumentation_data; var rest = __rest(_a, ["instrumentation_data"]);
|
|
3490
|
+
return rest;
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
function mapCxSpanToOtlpSpan(span) {
|
|
3494
|
+
var _a;
|
|
3495
|
+
if (!span.traceId || !span.spanId || !span.name) {
|
|
3496
|
+
if (getSdkConfig().debug) {
|
|
3497
|
+
console.debug('Missing required span fields: traceId, spanId, name', span);
|
|
3498
|
+
return null;
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
if (!span.startTime || !span.endTime) {
|
|
3502
|
+
if (getSdkConfig().debug) {
|
|
3503
|
+
console.debug('Missing span timestamps', span);
|
|
3504
|
+
}
|
|
3505
|
+
return null;
|
|
3506
|
+
}
|
|
3507
|
+
var startUnixNano = timestampToNanosString(span.startTime);
|
|
3508
|
+
var endUnixNano = timestampToNanosString(span.endTime);
|
|
3509
|
+
return __assign(__assign(__assign({ trace_id: span.traceId, span_id: span.spanId }, (span.parentSpanId ? { parentSpanId: span.parentSpanId } : {})), { name: (_a = span.name) !== null && _a !== void 0 ? _a : '', kind: 'SPAN_KIND_CLIENT', start_time_unix_nano: startUnixNano, end_time_unix_nano: endUnixNano, attributes: toOtlpAttributes(span.attributes) }), (span.status ? { status: toOtlpStatus(span.status) } : {}));
|
|
3510
|
+
}
|
|
3511
|
+
function mapEntryToOtlpResource(entry, extra) {
|
|
3512
|
+
var _a;
|
|
3513
|
+
var base = {
|
|
3514
|
+
'cx.application.name': entry.applicationName,
|
|
3515
|
+
'cx.subsystem.name': entry.subsystemName,
|
|
3516
|
+
};
|
|
3517
|
+
var merged = __assign(__assign({}, base), (extra !== null && extra !== void 0 ? extra : {}));
|
|
3518
|
+
if (!('service.name' in merged)) {
|
|
3519
|
+
merged['service.name'] = entry.applicationName;
|
|
3520
|
+
}
|
|
3521
|
+
var version = (_a = entry.version_metadata) === null || _a === void 0 ? void 0 : _a.app_version;
|
|
3522
|
+
if (version && !('service.version' in merged)) {
|
|
3523
|
+
merged['service.version'] = version;
|
|
3524
|
+
}
|
|
3525
|
+
var attributes = toOtlpAttributes(merged);
|
|
3526
|
+
return attributes.length ? { attributes: attributes } : {};
|
|
3527
|
+
}
|
|
3528
|
+
|
|
3529
|
+
function buildCustomTraces(logs) {
|
|
3530
|
+
var tracesPayload = buildExporterPayload(logs);
|
|
3531
|
+
var strippedLogs = stripOtelFieldsFromLogs(logs);
|
|
3532
|
+
return { tracesPayload: tracesPayload, strippedLogs: strippedLogs };
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3384
3535
|
var CoralogixExporter = (function () {
|
|
3385
3536
|
function CoralogixExporter() {
|
|
3386
3537
|
var _this = this;
|
|
@@ -3393,6 +3544,9 @@ var CoralogixExporter = (function () {
|
|
|
3393
3544
|
this.batchTimeDelay = BATCH_TIME_DELAY;
|
|
3394
3545
|
this.invokeLogRequest = function (logs, markCachedLogsSent) {
|
|
3395
3546
|
if (logs === null || logs === void 0 ? void 0 : logs.length) {
|
|
3547
|
+
if (_this.sdkConfig.tracesExporter) {
|
|
3548
|
+
logs = _this.buildAndExportOtelTraces(logs);
|
|
3549
|
+
}
|
|
3396
3550
|
_this.request
|
|
3397
3551
|
.send(JSON.stringify({
|
|
3398
3552
|
logs: logs,
|
|
@@ -3463,6 +3617,14 @@ var CoralogixExporter = (function () {
|
|
|
3463
3617
|
}
|
|
3464
3618
|
}
|
|
3465
3619
|
};
|
|
3620
|
+
CoralogixExporter.prototype.buildAndExportOtelTraces = function (logs) {
|
|
3621
|
+
var hasOtelSpanData = logs.some(function (log) { return !!log.instrumentation_data; });
|
|
3622
|
+
if (!hasOtelSpanData)
|
|
3623
|
+
return logs;
|
|
3624
|
+
var _a = buildCustomTraces(logs), tracesPayload = _a.tracesPayload, strippedLogs = _a.strippedLogs;
|
|
3625
|
+
this.sdkConfig.tracesExporter(tracesPayload);
|
|
3626
|
+
return strippedLogs;
|
|
3627
|
+
};
|
|
3466
3628
|
CoralogixExporter.prototype.clearCachedDataForSessionWithError = function () {
|
|
3467
3629
|
CxGlobal.cachedLogs = [];
|
|
3468
3630
|
this.batchTimeDelay = BATCH_TIME_DELAY;
|
|
@@ -3968,7 +4130,7 @@ function resolveUrlBlueprinters(urlBlueprinters) {
|
|
|
3968
4130
|
return resolvedUrlBlueprinters;
|
|
3969
4131
|
}
|
|
3970
4132
|
|
|
3971
|
-
var SDK_VERSION = '2.
|
|
4133
|
+
var SDK_VERSION = '2.13.0';
|
|
3972
4134
|
|
|
3973
4135
|
function shouldDropEvent(cxRumEvent, options) {
|
|
3974
4136
|
if (isDocumentErrorWithoutMessage(cxRumEvent)) {
|
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ export declare class CoralogixExporter implements SpanExporter, ProcessorBaseMod
|
|
|
14
14
|
export(spans: CxReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
15
15
|
private handleSessionWithError;
|
|
16
16
|
private invokeLogRequest;
|
|
17
|
+
private buildAndExportOtelTraces;
|
|
17
18
|
clearCachedDataForSessionWithError(): void;
|
|
18
19
|
shutdown(): Promise<void>;
|
|
19
20
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TraceExporterData } from './traces-exporter.types';
|
|
2
|
+
import { CxSpan } from '../types';
|
|
3
|
+
export declare function buildExporterPayload(logs: CxSpan[]): TraceExporterData;
|
|
4
|
+
export declare function stripOtelFieldsFromLogs(logs: CxSpan[]): Omit<CxSpan, 'instrumentation_data'>[];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { HrTime, SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
import { CxSpan } from '../types';
|
|
3
|
+
export interface OtlpAnyValueJson {
|
|
4
|
+
string_value?: string;
|
|
5
|
+
bool_value?: boolean;
|
|
6
|
+
int_value?: number | string;
|
|
7
|
+
double_value?: number | string;
|
|
8
|
+
}
|
|
9
|
+
export interface OtlpKeyValueJson {
|
|
10
|
+
key: string;
|
|
11
|
+
value?: OtlpAnyValueJson;
|
|
12
|
+
}
|
|
13
|
+
export type OtlpStatusCodeJson = 'STATUS_CODE_UNSET' | 'STATUS_CODE_OK' | 'STATUS_CODE_ERROR';
|
|
14
|
+
export interface OtlpStatusJson {
|
|
15
|
+
code?: OtlpStatusCodeJson;
|
|
16
|
+
message?: string;
|
|
17
|
+
}
|
|
18
|
+
export type OtlpSpanKindJson = 'SPAN_KIND_INTERNAL' | 'SPAN_KIND_SERVER' | 'SPAN_KIND_CLIENT' | 'SPAN_KIND_PRODUCER' | 'SPAN_KIND_CONSUMER';
|
|
19
|
+
export interface OtlpSpanJson {
|
|
20
|
+
trace_id: string;
|
|
21
|
+
span_id: string;
|
|
22
|
+
parent_span_id?: string;
|
|
23
|
+
name: string;
|
|
24
|
+
kind: OtlpSpanKindJson;
|
|
25
|
+
start_time_unix_nano: string;
|
|
26
|
+
end_time_unix_nano: string;
|
|
27
|
+
attributes?: OtlpKeyValueJson[];
|
|
28
|
+
status?: OtlpStatusJson;
|
|
29
|
+
}
|
|
30
|
+
export interface OtlpScopeJson {
|
|
31
|
+
name?: string;
|
|
32
|
+
version?: string;
|
|
33
|
+
attributes?: OtlpKeyValueJson[];
|
|
34
|
+
}
|
|
35
|
+
export interface OtlpScopeSpansJson {
|
|
36
|
+
scope?: OtlpScopeJson;
|
|
37
|
+
spans: OtlpSpanJson[];
|
|
38
|
+
}
|
|
39
|
+
export interface OtlpResourceJson {
|
|
40
|
+
attributes?: OtlpKeyValueJson[];
|
|
41
|
+
}
|
|
42
|
+
export interface OtlpResourceSpansJson {
|
|
43
|
+
resource?: OtlpResourceJson;
|
|
44
|
+
scope_spans: OtlpScopeSpansJson[];
|
|
45
|
+
}
|
|
46
|
+
export type CustomTimestamp = [seconds: number, nanos: number];
|
|
47
|
+
export type ResourceAttributes = Record<string, unknown>;
|
|
48
|
+
export interface TraceExporterData {
|
|
49
|
+
resource_spans: OtlpResourceSpansJson[];
|
|
50
|
+
}
|
|
51
|
+
export interface CxSpanOtelSpan {
|
|
52
|
+
spanId: string;
|
|
53
|
+
traceId: string;
|
|
54
|
+
sessionId?: string;
|
|
55
|
+
parentSpanId?: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
attributes?: Record<string, unknown>;
|
|
58
|
+
startTime?: HrTime;
|
|
59
|
+
endTime?: HrTime;
|
|
60
|
+
status?: {
|
|
61
|
+
code: SpanStatusCode | number;
|
|
62
|
+
message?: string;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface CxSpanOtelResource {
|
|
66
|
+
attributes?: Record<string, unknown>;
|
|
67
|
+
}
|
|
68
|
+
export interface BuildCustomTracesResult {
|
|
69
|
+
tracesPayload: TraceExporterData;
|
|
70
|
+
strippedLogs: CxSpan[];
|
|
71
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
import { CustomTimestamp, CxSpanOtelSpan, OtlpKeyValueJson, OtlpStatusCodeJson, OtlpStatusJson } from './traces-exporter.types';
|
|
3
|
+
export declare function toOtlpKeyValue(key: string, value: unknown): OtlpKeyValueJson;
|
|
4
|
+
export declare function toOtlpAttributes(attributes?: Record<string, unknown>): OtlpKeyValueJson[];
|
|
5
|
+
export declare function timestampToNanosNumber(timestamp: CustomTimestamp): number;
|
|
6
|
+
export declare function timestampToNanosString(timestamp: CustomTimestamp): string;
|
|
7
|
+
export declare function mapStatusCodeToOtlp(code?: SpanStatusCode | number): OtlpStatusCodeJson | undefined;
|
|
8
|
+
export declare function toOtlpStatus(spanStatus?: CxSpanOtelSpan['status']): OtlpStatusJson | undefined;
|
|
9
|
+
export declare function isWithinAllowedWindow(start: number, now: number): boolean;
|
package/src/types.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { MemoryUsageContext } from './instrumentations/memory-usage';
|
|
|
17
17
|
import { MFEMetadata } from './mfe/mfe.types';
|
|
18
18
|
import { UrlBasedLabelProvider } from './label-providers/url-based-label-provider';
|
|
19
19
|
import { CustomTracer, CustomTracerIgnoredInstruments } from './custom-spans';
|
|
20
|
+
import { TraceExporterData } from './traces-exporter/traces-exporter.types';
|
|
20
21
|
export interface CxStackFrame extends Partial<MFEMetadata> {
|
|
21
22
|
fileName?: string;
|
|
22
23
|
columnNumber?: number;
|
|
@@ -157,6 +158,7 @@ export interface CoralogixBrowserSdkConfig {
|
|
|
157
158
|
networkExtraConfig?: NetworkExtraConfig[];
|
|
158
159
|
supportMfe?: boolean;
|
|
159
160
|
workerSupport?: boolean;
|
|
161
|
+
tracesExporter?: (data: TraceExporterData) => void;
|
|
160
162
|
}
|
|
161
163
|
export interface CoralogixOtelWebType extends SendLog {
|
|
162
164
|
init: (options: CoralogixBrowserSdkConfig) => void;
|
package/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.
|
|
1
|
+
export declare const SDK_VERSION = "2.13.0";
|