Skip to content

Commit

Permalink
feat: Add browser-telemetry API types. (#669)
Browse files Browse the repository at this point in the history
Add API surface for browser telemetry.

Review after: #659
  • Loading branch information
kinyoklion authored Nov 7, 2024
1 parent 37920e5 commit 89967ee
Show file tree
Hide file tree
Showing 8 changed files with 479 additions and 0 deletions.
163 changes: 163 additions & 0 deletions packages/telemetry/browser-telemetry/src/api/Breadcrumb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/**
* Defines the 'class' of the breadcrumb.
*/
export type BreadcrumbClass =
| 'custom'
| 'log'
| 'navigation'
| 'feature-management'
| 'ui'
| 'http';

/**
* Indicates the severity of the breadcrumb.
*/
export type BreadcrumbLevel = 'error' | 'warning' | 'info' | 'debug';

/**
* Types of data support with breadcrumbs.
*/
export type BreadcrumbDataValue = boolean | number | string;

/**
* Defines arbitrary data that may be associated with a breadcrumb.
*/
export type BreadcrumbData = Record<string, BreadcrumbDataValue>;

/**
* Interface which defines a breadcrumb.
*/
export interface Breadcrumb {
/**
* The class of the breadcrumb. This is the top level categorization of breadcrumbs.
*/
class: BreadcrumbClass;

/**
* When the event associated with the breadcrumb happened. The timestamp is in milliseconds since January 1, 1970
* Universal Coordinated Time (UTC)
*
* For most breadcrumbs this will not be different than the time of breadcrumb creation, but if there is a delay
* between the event and breadcrumb capture, then the time of the event should be used instead.
*/
timestamp: number;

/**
* The level of severity of the breadcrumb. The default choice of level should be `info` if there isn't a clear
* reason to use a different level.
*/
level: BreadcrumbLevel;

/**
* The type of the breadcrumb. Each class may be split into multiple types with the type more specifically
* categorizing the type of event.
*/
type?: string;

/**
* A message associated with the breadcrumb.
*/
message?: string;

/**
* Any data associated with the breadcrumb.
*/
data?: BreadcrumbData;
}

/**
* Utility type which allows for easy extension of base breadcrumb type.
*/
type ImplementsCrumb<U extends Breadcrumb> = U;

/**
* Type for custom breadcrumbs.
*/
export type CustomBreadcrumb = ImplementsCrumb<{
class: 'custom';
timestamp: number;
level: BreadcrumbLevel;
type?: string;
message?: string;
data?: BreadcrumbData;
}>;

/**
* Type for log breadcrumbs.
*/
export type LogBreadcrumb = ImplementsCrumb<{
class: 'log';
timestamp: number;
level: BreadcrumbLevel;
message: string;
data?: BreadcrumbData;
}>;

/**
* Type for navigation breadcrumbs.
*/
export type NavigationBreadcrumb = ImplementsCrumb<{
class: 'navigation';
timestamp: number;
level: 'info';
type?: string;
data?: {
/**
* The location being navigated from. In a web application this would typically be a URL.
*/
from?: string;
/**
* The location being navigated to. In a web application this would typically be a URL.
*/
to?: string;
};
}>;

/**
* Type for feature management breadcrumbs.
*/
export type FeatureManagementBreadcrumb = ImplementsCrumb<{
class: 'feature-management';
timestamp: number;
level: 'info';
type: 'flag-evaluated' | 'flag-detail-changed';
data?: {
/**
* The flag key.
*/
key?: string;
// Not supporting JSON flags in breadcrumbs. As noted in design we may want to eventually support none of the
// values in the breadcrumb.
/**
* The evaluated value for simple types.
*/
value?: boolean | string | number;
};
}>;

/**
* Type for UI breadcrumbs.
*/
export type UiBreadcrumb = ImplementsCrumb<{
class: 'ui';
timestamp: number;
level: 'info';
type: 'click' | 'input';
message: string;
}>;

/**
* Type for HTTP breadcrumbs.
*/
export type HttpBreadcrumb = ImplementsCrumb<{
class: 'http';
timestamp: number;
level: 'error' | 'info'; // Error if an error status code?
type: 'xhr' | 'fetch';
data?: {
url?: string;
method?: string;
statusCode: number;
statusText: string;
};
}>;
28 changes: 28 additions & 0 deletions packages/telemetry/browser-telemetry/src/api/BrowserTelemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { LDClient, LDInspection } from 'launchdarkly-js-client-sdk';

import { Recorder } from './Recorder';

/**
* Interface LaunchDarkly browser telemetry.
*/
export interface BrowserTelemetry extends Recorder {
/**
* Get inspectors to use with the LaunchDarkly client.
*/
inspectors(): LDInspection[];

// TODO: Consider hooks as well. Hooks will allow registration to happen in a
// single step.

/**
* Register the telemetry instance with the LaunchDarkly client.
*
* @param client The LaunchDarkly client.
*/
register(client: LDClient): void;

/**
* Close the telemetry client.
*/
close(): void;
}
25 changes: 25 additions & 0 deletions packages/telemetry/browser-telemetry/src/api/Collector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Recorder } from './Recorder';

/**
* Interface to be implemented by collectors.
*
* Collectors collect data and inform the client of events.
*
* For instance a collector may notify the telemetry instance of HTTP navigation
* or of UI events. A collector can be created independently of a {@link Recorder}
* and can begin collecting immediately. It may queue information until it can
* be registered with a recorder.
*/
export interface Collector {
/**
* Register the collector with a recorder.
* @param recorder Recorder to report events or breadcrumbs to.
* @param sessionId The current session ID.
*/
register(recorder: Recorder, sessionId: string): void;

/**
* Unregister the collector. It will stop sending events to the recorder.
*/
unregister(): void;
}
32 changes: 32 additions & 0 deletions packages/telemetry/browser-telemetry/src/api/ErrorData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Breadcrumb } from './Breadcrumb';
import StackTrace from './stack/StackTrace';

/**
* Interface representing error data.
*/
export interface ErrorData {
/**
* The type of the error.
*/

type: string;
/**
* A message associated with the error.
*/

message: string;
/**
* The stack trace for the error.
*/

stack: StackTrace;
/**
* Breadcrumbs leading up to the error.
*/

breadcrumbs: Breadcrumb[];
/**
* The ID of the session during which the error occurred.
*/
sessionId: string;
}
146 changes: 146 additions & 0 deletions packages/telemetry/browser-telemetry/src/api/Options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { Collector } from './Collector';

/**
* Interface for URL filters.
*
* Given a URL the filter may return a different string to represent that URL.
* This string will be included in the telemetry events instead of the original.
*
* The URL will be filtered by SDK internal filters before this function is called.
*
* To redact a URL entirely return an empty string.
*
* Example:
* customUrlFilter: (url) => {
* if (url.includes('secret')) {
* return ''
* }
* return url;
* }
*/
export interface UrlFilter {
(url: string): string;
}

export interface HttpBreadCrumbOptions {
/**
* If fetch should be instrumented and breadcrumbs included for fetch requests.
*
* Defaults to true.
*/
instrumentFetch?: boolean;

/**
* If XMLHttpRequests should be instrumented and breadcrumbs included for XMLHttpRequests.
*
* Defaults to true.
*/
instrumentXhr?: boolean;

/**
* Customize URL filtering. This will be applied in addition to some baseline filtering included
* which redacts components of LaunchDarkly URLs.
*/
customUrlFilter?: UrlFilter;
}

export interface StackOptions {
/**
* Configuration that controls how source is captured.
*/
source?: {
/**
* The number of lines captured before the originating line.
*
* Defaults to 3.
*/
beforeLines?: number;
/**
* The number of lines captured after the originating line.
*
* Defaults to 3.
*/
afterLines?: number;

/**
* The maximum length of source line to include. Lines longer than this will be
* trimmed.
*
* Defaults to 280.
*/
maxLineLength?: number;
};
}

/**
* Options for configuring browser telemetry.
*/
export interface Options {
/**
* The maximum number of pending events. Events may be captured before the LaunchDarkly
* SDK is initialized and these are stored until they can be sent. This only affects the
* events captured during initialization.
*/
maxPendingEvents?: number;
/**
* Properties related to automatic breadcrumb collection.
*/
breadcrumbs?: {
/**
* Set the maximum number of breadcrumbs. Defaults to 50.
*/
maxBreadcrumbs?: number;

/**
* True to enable automatic evaluation breadcrumbs. Defaults to true.
*/
evaluations?: boolean;

/**
* True to enable flag change breadcrumbs. Defaults to true.
*/
flagChange?: boolean;

/**
* True to enable click breadcrumbs. Defaults to true.
*/
click?: boolean;

/**
* True to enable input breadcrumbs for keypresses. Defaults to true.
*
* Input breadcrumbs do not include entered text, just that text was entered.
*/
keyboardInput?: boolean;

/**
* Controls instrumentation and breadcrumbs for HTTP requests.
* The default is to instrument XMLHttpRequests and fetch requests.
*
* `false` to disable all HTTP breadcrumbs and instrumentation.
*
* Example:
* ```
* // This would instrument only XmlHttpRequests
* http: {
* instrumentFetch: false
* instrumentXhr: true
* }
*
* // Disable all HTTP instrumentation:
* http: false
* ```
*/
http?: HttpBreadCrumbOptions | false;
};

/**
* Additional, or custom, collectors.
*/
collectors?: Collector[];

/**
* Configuration that controls the capture of the stack trace.
*/
stack?: StackOptions;
}
Loading

0 comments on commit 89967ee

Please sign in to comment.