@zendesk/retrace
Version:
define and capture Product Operation Traces along with computed metrics with an optional friendly React beacon API
109 lines (103 loc) • 3.98 kB
text/typescript
/* eslint-disable @typescript-eslint/consistent-indexed-object-style */
import type { SpanMatch } from './matchSpan'
import type { Span, SpanUpdateFunction } from './spanTypes'
import type { TraceStates } from './Trace'
import type { RelationSchemasBase } from './types'
export interface SpanAnnotation {
/**
* The ID of the operation the event belongs to.
*/
id: string
/**
* The occurrence of the span with the same name and type within the operation.
* Usually 1 (first span)
*/
occurrence: number
/**
* Offset from the start of the operation to the start of the event.
* aka operationStartOffset or operationStartToEventStart
*/
operationRelativeStartTime: number
/**
* Relative end time of the event within the operation.
*/
operationRelativeEndTime: number
/**
* The state the event was recorded in.
*/
recordedInState: TraceStates
/**
* If true, this is the first required span after having met all the required span criteria of the operation.
* e.g. if the operation requires 3 spans, this will be true for that 3rd span.
*/
markedRequirementsMet?: boolean
/**
* After all the required span criteria are met, and we completed debouncing.
* If true, this is the last span of the operation (before page interactive capturing).
* This span is used to calculate the duration of the entire trace.
*/
markedComplete?: boolean
/**
* If true, this is the span was used to calculate the point at which the page became interactive.
*/
markedPageInteractive?: boolean
/**
* Labels for the span based on label definitions from the Tracer. Empty if the span didn't match any of the label match definitions.
*/
labels: string[]
/**
* If true, this span is a "ghost" span - it's only present because it is a parent of another span.
* It is not part of the trace.
*/
isGhost?: boolean
}
export interface SpanAnnotationRecord {
[operationName: string]: SpanAnnotation
}
export interface SpanAndAnnotation<
RelationSchemasT extends RelationSchemasBase<RelationSchemasT>,
> {
span: Span<RelationSchemasT>
annotation: SpanAnnotation
}
export interface ProcessedSpan<
RelationSchemasT extends RelationSchemasBase<RelationSchemasT>,
SpanT extends Span<RelationSchemasT>,
> {
readonly span: SpanT
/**
* Only present if the span was processed by at least one active trace.
*/
readonly annotations: SpanAnnotationRecord | undefined
/**
* Resolves the parent span of the current span, based on the parent span matcher.
* This will work even if the span wasn't processed by any active trace.
*/
readonly resolveParent: (
recursiveAncestors?: boolean,
) => Span<RelationSchemasT> | undefined
/**
* While not usually needed, you can use this function
* to update some of the span's attributes AFTER it has been processed.
* Note that this will only work if the trace is still in progress.
* Object properties (such as attributes) are merged onto the original span,
* so if you want to remove a property, set it to `undefined`.
*
* This will re-process the span, so if, for example,
* your trace has a `requiredToEndSpan` matcher on an attribute
* that wasn't present in the span when it was processed, and you update the span
* to include that attribute, calling this function will trigger re-evaluation of the matchers.
*/
readonly updateSpan: SpanUpdateFunction<RelationSchemasT, SpanT>
/**
* Finds an ancestor of the span that matches the given SpanMatch.
* This will traverse the parent hierarchy of the span,
* starting with the span itself and moving up through its parents,
* resolving them if necessary.
* If no matching ancestor is found, returns undefined.
*/
readonly findAncestor: (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
spanMatch: SpanMatch<keyof RelationSchemasT, RelationSchemasT, any>,
) => Span<RelationSchemasT> | undefined
}