Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion e2e/core/node-integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TrackJS, timestamp } from "@trackjs/core";
import { TrackJS, timestamp, userAgent } from "@trackjs/core";
import { test, expect, beforeEach } from "vitest";
import { MockTransport } from "./mocks/transport";
import type { NetworkTelemetry, Transport, TransportRequest, TransportResponse } from "@trackjs/core";
Expand Down Expand Up @@ -49,6 +49,35 @@ test('TrackJS.track() can track errors after install', async () => {
});
});

test('TrackJS.track() with environment', async () => {
const transport = new MockTransport();

TrackJS.initialize({
token: 'test token',
transport,
dependencies: {
"foo": "1.2.3"
},
originalUrl: "original-url",
referrerUrl: "referrer-url",
userAgent: userAgent("Node", "12.1", "windows", "x64", "11.2"),
});

await TrackJS.track(new Error('Oops'));

expect(transport.sentRequests).toHaveLength(1);
expect(JSON.parse(transport.sentRequests[0]?.data as string)).toMatchObject({
environment: expect.objectContaining({
originalUrl: "original-url",
referrer: "referrer-url",
dependencies: {
"foo": "1.2.3"
},
userAgent: "Node/12.1 (windows x64 11.2)"
})
});
})

test('TrackJS.track() with custom metadata', async () => {
const transport = new MockTransport();

Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@
"clean": "rimraf dist",
"prepublishOnly": "npm run build",
"test": "vitest run",
"test:watch": "vitest"
"dev": "vitest"
}
}
19 changes: 8 additions & 11 deletions packages/core/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Metadata } from "./metadata";
import { TelemetryLog } from "./telemetryLog";
import { timestamp, serialize, isError } from "./utils";

import type {
CapturePayload,
Options,
Expand Down Expand Up @@ -75,14 +74,12 @@ export class Client {

environment: {
age: 0,
dependencies: {
"foo": "bar"
},
originalUrl: "",
referrer: "",
userAgent: 'node/22.0 (osx x64 123)',
viewportHeight: -1,
viewportWidth: -1
dependencies: structuredClone(this.options.dependencies),
originalUrl: this.options.originalUrl,
referrer: this.options.referrerUrl,
userAgent: this.options.userAgent,
viewportHeight: this.options.viewportHeight,
viewportWidth: this.options.viewportWidth
},

metadata: payloadMetadata.get(),
Expand All @@ -92,8 +89,8 @@ export class Client {
network: this.telemetry.get("net"),
visitor: this.telemetry.get("vis"),

agentPlatform: "",
version: '0.0.0',
agentPlatform: this.options.agent,
version: this.options.agentVersion,
throttled: 0,
};
}
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const MAX_METADATA_LENGTH = 500;
export const MAX_TELEMETRY_LOG_SIZE = 30;
export const MAX_TELEMETRY_MESSAGE_LENGTH = 10_000;
export const MAX_TELEMETRY_URI_LENGTH = 1_000;
export const MAX_TELEMETRY_ATTRIBUTES = 20;
export const MAX_TELEMETRY_ATTRIBUTE_VALUE = 500;
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * as TrackJS from './trackjs';
export { timestamp, uuid } from './utils/';
export { timestamp, userAgent, uuid } from './utils/';

export type * from './types/';
7 changes: 2 additions & 5 deletions packages/core/src/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { MAX_METADATA_LENGTH } from "./constants";
import { truncate } from "./utils";

const MAX_METADATA_LENGTH = 500;

export class Metadata {

private store: Map<string, string> = new Map();
Expand Down Expand Up @@ -30,9 +29,7 @@ export class Metadata {

public clone(): Metadata {
const cloned = new Metadata();
for (const [key, value] of this.store.entries()) {
cloned.store.set(key, value);
}
cloned.store = structuredClone(this.store);
return cloned;
}

Expand Down
40 changes: 25 additions & 15 deletions packages/core/src/telemetryLog.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import type { ConsoleTelemetry, NavigationTelemetry, NetworkTelemetry, Telemetry, TelemetryType, VisitorTelemetry } from "./types";
import { truncate } from "./utils";
import {
MAX_TELEMETRY_ATTRIBUTE_VALUE,
MAX_TELEMETRY_ATTRIBUTES,
MAX_TELEMETRY_LOG_SIZE,
MAX_TELEMETRY_MESSAGE_LENGTH,
MAX_TELEMETRY_URI_LENGTH
} from "./constants";

import type {
ConsoleTelemetry,
NavigationTelemetry,
NetworkTelemetry,
Telemetry,
TelemetryType,
VisitorTelemetry
} from "./types";

const MAX_LOG_SIZE = 30;
const MAX_MESSAGE_LENGTH = 10_000;
const MAX_URI_LENGTH = 1_000;
const MAX_ATTRIBUTES = 20;
const MAX_ATTRIBUTE_VALUE = 500;

export class TelemetryLog {

Expand Down Expand Up @@ -36,8 +46,8 @@ export class TelemetryLog {
}
this.store.push({ type, telemetry});

if (this.store.length > MAX_LOG_SIZE) {
this.store = this.store.slice(this.store.length - MAX_LOG_SIZE);
if (this.store.length > MAX_TELEMETRY_LOG_SIZE) {
this.store = this.store.slice(this.store.length - MAX_TELEMETRY_LOG_SIZE);
}
}

Expand All @@ -47,7 +57,7 @@ export class TelemetryLog {

public clone(): TelemetryLog {
const cloned = new TelemetryLog();
cloned.store = this.store.slice(0);
cloned.store = structuredClone(this.store);
return cloned;
}

Expand All @@ -64,18 +74,18 @@ export class TelemetryLog {
}

export function _normalizeConsoleTelemetry(telemetry: any) : ConsoleTelemetry {
telemetry.message = truncate(telemetry.message, MAX_MESSAGE_LENGTH);
telemetry.message = truncate(telemetry.message, MAX_TELEMETRY_MESSAGE_LENGTH);
return telemetry;
}

export function _normalizeNavigationTelemetry(telemetry: any) : NavigationTelemetry {
telemetry.from = truncate(telemetry.from, MAX_URI_LENGTH);
telemetry.to = truncate(telemetry.to, MAX_URI_LENGTH);
telemetry.from = truncate(telemetry.from, MAX_TELEMETRY_URI_LENGTH);
telemetry.to = truncate(telemetry.to, MAX_TELEMETRY_URI_LENGTH);
return telemetry;
}

export function _normalizeNetworkTelemetry(telemetry: any) : NetworkTelemetry {
telemetry.url = truncate(telemetry.url, MAX_URI_LENGTH);
telemetry.url = truncate(telemetry.url, MAX_TELEMETRY_URI_LENGTH);
return telemetry;
}

Expand All @@ -84,10 +94,10 @@ export function _normalizeVisitorTelemetry(telemetry: any) : VisitorTelemetry {
const currentAttributes: attributes = telemetry.element?.attributes || {};
let normalizedAttributes: attributes = {};

const limitedAttributes = Object.entries(currentAttributes).slice(0, MAX_ATTRIBUTES);
const limitedAttributes = Object.entries(currentAttributes).slice(0, MAX_TELEMETRY_ATTRIBUTES);

for (const [key, value] of limitedAttributes) {
normalizedAttributes[key] = truncate(value, MAX_ATTRIBUTE_VALUE);
normalizedAttributes[key] = truncate(value, MAX_TELEMETRY_ATTRIBUTE_VALUE);
}

(telemetry.element || {}).attributes = normalizedAttributes;
Expand Down
26 changes: 15 additions & 11 deletions packages/core/src/trackjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,25 @@ let config: Options | null = null;
let client: Client | null = null;

const defaultOptions: Options = {
application: '',
agent: "core",
agentVersion: "{{AGENT_VERSION}}",
application: "",
dependencies: {},
correlationId: uuid(),
errorURL: 'https://capture.trackjs.com/capture/node',
errorURL: "https://capture.trackjs.com/capture/node",
metadata: {},
onError: () => true,
originalUrl: "",
referrerUrl: "",
serializer: [],
sessionId: '',
token: '',
sessionId: "",
token: "",
transport: new FetchTransport(),
userId: '',
version: ''
userAgent: "",
userId: "",
version: "",
viewportHeight: -1,
viewportWidth: -1
};

/**
Expand Down Expand Up @@ -74,7 +82,7 @@ export function initialize(options: Partial<Options> & { token: string }): void
}

/**
* Adds a object set of key-value pairs to metadata for any future errors.
* Adds a object map of key-value pairs to metadata for any future errors.
* Keys and values will be truncated to 500 characters.
*
* @param metadata - object with string values to be added as metadata.
Expand Down Expand Up @@ -163,10 +171,6 @@ export function addTelemetry(type: TelemetryType, telemetry: Telemetry): void {
return client!.addTelemetry(type, telemetry);
}

export function addDependencies(...args: [dependencies: Record<string, string>]): void {
throw new Error("not implemented");
}

/**
* Track and error or error-like object to the TrackJS error monitoring service.
*
Expand Down
71 changes: 68 additions & 3 deletions packages/core/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ export interface TrackOptions {

export interface Options {

/**
* The name of the TrackJS agent package
*
* @default "core"
*/
agent: string,

/**
* The version of the TrackJS agent package
*
* @default "{{AGENT_VERSION}}"
*/
agentVersion: string,

/**
* TrackJS Application key.
*
Expand All @@ -53,6 +67,14 @@ export interface Options {
*/
correlationId: string;

/**
* Dependency package names and version for the current environment.
*
* @default {}
* @example { "node": "22.12.0" }
*/
dependencies: { [name: string]: string };

/**
* URL destination override for capturing errors.
*
Expand All @@ -69,15 +91,32 @@ export interface Options {

/**
* Custom handler to manipulate or suppress errors captured by the agent.
*
* @param payload error payload to be sent to TrackJS.
* @returns false will suppress the error from being sent.
*
* @default (payload) => true
*/
onError: (payload: CapturePayload) => boolean;

/**
* Custom functions for serializing objects to strings. Will execute before the default serializer.
* When environment has a user interface, the URI location where the application
* was started, or the URL of the page when it was first loaded.
*
* @default ""
*/
originalUrl: string

/**
* When environment has a user interface, the URI location where the user came
* from before landing on this page or screen.
*
* @default ""
*/
referrerUrl: string

/**
* Custom functions for serializing objects to strings. Will execute before the
* default serializer.
*
* @default []
*/
Expand All @@ -96,12 +135,23 @@ export interface Options {
token: string;

/**
* Custom transport function for sending data. Required if the current environment does not support `fetch`.
* Custom transport function for sending data. Required if the current
* environment does not support `fetch`.
*
* @default FetchTransport
*/
transport: Transport;

/**
* User-Agent string describing the user's running environment, browser, process,
* operating system, arch, and version. For non-browser environments, this can
* be constructed with the userAgent() util function.
*
* @see {@link userAgent}
* @defaults ""
*/
userAgent: string

/**
* Customer-generated Id representing the current user.
*
Expand All @@ -116,4 +166,19 @@ export interface Options {
*/
version: string;

/**
* When environment has a user interface, the height of the user viewport in
* pixels.
*
* @default -1
*/
viewportHeight: number

/**
* When environment has a user interface, the width of the user viewport in
* pixels.
*
* @default -1
*/
viewportWidth: number
}
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './isType';
export * from './serialize';
export * from './timestamp';
export * from './truncate';
export * from './userAgent';
export * from './uuid';
Loading