Skip to the content

API reference

The exported functions, classes and types of @mark1russell7/lag, @mark1russell7/lag/worker, @lag/load and @lag/report.

Note

This page is a draft. The content is not complete and can change.

This page lists the public API of each package. The TSDoc comment of each export gives the details. The links go to the source on GitHub.

Install

npm install @mark1russell7/lag

The package has three entry points:

Entry pointWhat it contains
@mark1russell7/lagThe exports of the sections from Setup to Utilities.
@mark1russell7/lag/workercreateLagWorker() and the worker module that it starts. Refer to the section @mark1russell7/lag/worker.
@mark1russell7/lag/event-line.jsformatEventLine(), which makes the line of each event.

@lag/load and @lag/report are private packages of the repository. They are not on npm.

Setup

setupAllMonitors(deps)

function setupAllMonitors(deps : AllMonitorDeps) : AllMonitorHandles;

The function starts each monitor whose dependencies are in deps, and gives the handles. The necessary dependencies are logger, clock, meter, the four timer functions, document and window. All other dependency groups are optional. Refer to the quick start.

AllMonitorHandles has these members:

MemberWhat it does
registryThe MonitorRegistry with the handle of each monitor. registry.get(name) gives one handle.
stop()Stops all monitors in the reverse sequence of their start.
flush()Records the values that the monitors keep until a checkpoint (the page-view vitals). Connect it to the before-flush hook of the exporter.
conditions, vitals, driftLag, workerMonitor, pageViewContext and the other accessorsThe monitor of one handle, or undefined if the monitor did not start.

createBrowserDeps(window, options)

function createBrowserDeps(globals : BrowserGlobals, options : BrowserDepsOptions) : AllMonitorDeps;

The function gets the dependencies from the browser globals. It examines each optional API and binds each browser function to its object.

OptionDefaultWhat it does
logger, meternecessaryThe diagnostic logger and the OpenTelemetry meter.
eventsnoneThe event sink (createOtelEventSink). Without it, the monitors send no events.
spansnoneThe span sink (createOtelSpanSink). Without it, the monitors make no spans.
workernoneThe worker from createLagWorker(). Without it, the worker monitors do not start.
workerHeartbeatIntervalMs1000The time between two heartbeats of the worker.
workerHangReportnoneThe OTLP logs URL and the resource for the hang reports of the worker.
memoryIntervalMsthe monitor defaultThe time between two memory samples.
pressureSources["cpu"]The Compute Pressure sources.
softNavigationsfalseWhen true, each soft navigation starts a new page view (Chromium 151 and later).
sharedMemorytrueUses shared memory for the liveness watcher in a cross-origin-isolated page.
hangJournaltrueReads the hang journal in IndexedDB, when there is a worker. With false, the worker also writes no records.
crashReportContexttruePuts the page-view ID into window.crashReport (Chrome 145 and later).
peerHangWatchtrueThe open pages of the origin watch each other for hangs, through BroadcastChannel and navigator.locks (peer hang watch).

Factories

Each factory makes one monitor, connects it to its instruments, and gives a MonitorHandle (name, monitor, stop()). Use a factory when you want only some monitors.

FactoryMonitorPage
createInstrumentedLifecycleLifecycleStateMachineLifecycle
createInstrumentedPageViewVitalsPageViewVitalsPage-view vitals
createInstrumentedPageViewContextthe page-view contextPage-view context
createInstrumentedDriftLagDriftLagDriftLag
createInstrumentedMacrotaskLagMacrotaskLagMacrotaskLag
createInstrumentedThrottleDetectorTimerThrottleDetectorTimer throttle
createInstrumentedLoafLongAnimationFrameMonitorLong animation frames
createInstrumentedEventTimingEventTimingMonitorEvent Timing
createInstrumentedLayoutShiftLayoutShiftMonitorLayout shift
createInstrumentedFrameTimingFrameTimingMonitorFrame timing
createInstrumentedIdleAvailabilityIdleAvailabilityMonitorIdle availability
createInstrumentedSchedulingFairnessSchedulingFairnessMonitorScheduling fairness
createInstrumentedMemoryMemoryMonitorMemory
createInstrumentedWorkerLagWorkerLagMonitorWorker lag
createInstrumentedSharedLivenessSharedLivenessMonitorShared liveness
createInstrumentedPeerHangWatchPeerHangWatchPeer hang watch
createInstrumentedComputePressureComputePressureMonitorCompute pressure
createInstrumentedGCSignalGCSignalDetectorGC signal
createInstrumentedClockReliabilityClockReliabilityCheckerClock reliability
createInstrumentedClockDriftClockDriftMonitorClock drift
createInstrumentedBrowserReportsBrowserReportMonitorBrowser reports

The building blocks of a factory are createHandle (an error boundary) and validatedRecorder (a sample validator for a record function).

Measurement conditions

ExportWhat it does
createMeasurementConditions(options)Makes the shared conditions: a ReliabilityTracker, createValidator(), pauseWhileHidden(monitor) and dispose(). The conditions report the stall samples whose windows overlap as one stall episode.
ReliabilityTrackerKeeps the intervals in which samples are not valid (hidden, frozen, suspend). findOverlap(start, end, reason?) gives an interval that overlaps a window, optionally only of one cause.
SampleValidatorDiscards a sample that overlaps such an interval, and holds a very long sample until it knows if it was a hang or a suspend.

Refer to measurement validity.

Metrics and events

ExportWhat it does
METRICS, METRIC_CATALOGEvery metric: name, type, unit, monitor, description and permitted attribute values.
EVENTS, EVENT_CATALOGEvery event: name, monitor, description and attributes.
createHistogram(meter, definition), createCounter(meter, definition)Make an instrument from a catalog definition. They fail if the type does not agree. A histogram gets the bucket boundaries of its definition as advice (HISTOGRAM_BOUNDARIES, by unit). An SDK with explicit-bucket histograms uses them.
Meter, Histogram, Counter, AttributesThe meter port. An OpenTelemetry Meter fits it.
createNoopMeter()A meter that records nothing.
EventSink, EventOptions, createNoopEventSink(), withEventContext(sink, context)The event port, the options of an event (time, the time of the occurrence in Unix milliseconds), a sink that sends nothing, and a sink that adds context attributes to each event.
createOtelEventSink(logger, options?)Sends each event as an OpenTelemetry log record with an event name. The body is the line of the event: the name and the sorted key=value pairs (formatEventLine in @mark1russell7/lag/event-line.js). The time of the occurrence becomes the time of the record. The options are maxTimeOffsetMs (refer to MAX_EVENT_TIME_OFFSET_MS) and now.
placeEventTime(time, now, maxOffsetMs?), MAX_EVENT_TIME_OFFSET_MS, EVENT_TIME_ATTRIBUTEThe rule for the time of a record: the time of the occurrence when it is no more than 30 minutes from the time of the call, else the time of the call and the attribute lag.event.time.
SPANS, SPAN_CATALOGEvery span: name, monitor, description and attributes.
SpanSink, SpanIdentity, SpanOptions, OpenSpan, createNoopSpanSink()The span port: a span that stays open until end() (a page view), or a span that ended already (a hang). A span has a parent and links. The times are Unix milliseconds.
createOtelSpanSink(tracer, api)Sends each span through an OpenTelemetry tracer. api is the module @opentelemetry/api. A span that the sampler did not sample gets the identity sampled: false, and the spans in it are not sampled either.
createPageViewSpans(spans, clock), PageViewSpansThe span of each page view. setupAllMonitors() makes it when the dependencies have spans.
createOtelLoggerAdapter(logger), createTeeLogger(...loggers)Send the diagnostic messages to OpenTelemetry logs, or to more than one logger.
encodeOtlpLogs(...)Makes the OTLP/HTTP JSON body of log records. The worker uses it for its hang reports.

Page views and Web Vitals

ExportWhat it does
PageViewVitalsThe Web Vitals of each page view. getView(), getValues(), subscribe(listener), flush(), stop().
ViewCollectorThe vitals of one page view, with the rules of web-vitals.
describeNode(node)The short CSS selector of a DOM node, as web-vitals makes it.
rateVital(name, value), VITAL_THRESHOLDSThe rating good, needs-improvement or poor.
PageSource, createPageSource(document, performance)The navigation entry, the prerender state, the hidden times and the URL of the document.

Clocks

ExportWhat it does
createAbsoluteClock(performance)The absolute time of the context. It reads timeOrigin one time.
ClockDriftMonitorFinds suspends and clock steps from the wall clock and the absolute clock.
WorkerClockSyncThe NTP-style clock sync with the worker.
ClockReliabilityCheckerThe resolution of performance.now().

Worker

ExportWhat it does
WorkerLagMonitorThe main-thread half of the worker monitor: acknowledgements, the clock sync, the context, the watchdog. stop() keeps the listener for hang-ended, and dispose() removes it.
createWorkerHandler(deps)The worker half: the heartbeats, the hang detection and the hang journal. @mark1russell7/lag/worker operates it.
MainToWorkerMessage, WorkerToMainMessage and the message typesThe worker protocol. Refer to architecture.
HangJournal, createIndexedDbHangJournal(indexedDB), createMemoryHangJournal()The storage of hangs in progress: put(), remove(), list() and take(). take() removes and gives a stale record in one atomic operation.
HangReportMarks, createStorageHangReportMarks(localStorage), HANG_REPORT_MARK_PREFIX, StorageLikeThe marks of the hangs that a page reported itself or for another page. The journal reader skips the record of a marked hang. The marks are synchronous, thus a closing page can write them.
PEER_CLAIM_HOLD_MS, AbortControllerLike, AbortSignalLike, AbortControllerConstructorThe time for which the peer hang watch holds the claim of a report (60 s), and the parts of AbortController with which it cancels its waiting lock requests.
findAbandonedHangs(records, now, ownPageId)The records of pages that did not survive their hang. now is a wall-clock time, as the times of the records are.
SharedLivenessMonitor, LivenessWatcher, createLivenessBeacon, beatingSetTimeoutThe shared-memory liveness watcher.
createForwardingMeter, createMeterReceiverSend the records of a meter from one context to another context, in batches. Each batch has the ID of its sender (senderId) and the definitions of its new instruments. Thus one receiver can get the records of many senders, also when its listener starts late.

Utilities

ExportWhat it does
createMessageTaskQueue(MessageChannel)Starts each callback in a new message task.
RateLimiter, stripUrlParameters(url)Limit the number of events, and remove the query and the fragment of a URL.
createRandomId()A random ID of 32 hexadecimal digits.
MonitorRegistry, MonitorHandleThe registry of handles.
LagMonitor, LagLoggerThe base class of the timer monitors, and the logger of sustained lag. LagLogger measures its periods in time: the sum of the intervals of the measurements (LagMeasurement.intervalMs).

@mark1russell7/lag/worker

This entry point is separate from the main entry point, because only this module starts a Worker. The worker module uses relative imports only. Thus the bundler of the app makes one file for the worker (refer to the quick start).

ExportWhat it does
createLagWorker()Starts the module worker and gives a LagWorker.
LagWorkerA WorkerLike with terminate(). The caller owns the worker.

@lag/load

ExportWhat it does
createRng(seed)A seeded random number generator, so that a workload is the same at each run.
uniform, constant, normal, exponential, powerLaw, bimodal, mixture, evolutionary, burst, sampleDistributions of durations.
syncBusyWait, syncCompute, gcPressure, microtaskFlood, macrotaskFlood, promiseChain, layoutThrash, longAnimationFrame, sleepGenerators of main-thread load.
runWorkload(options)Operates a workload and gives a WorkloadResult.
lightLoad, moderateLoad, heavyLoad, burstyLoad, evolutionaryLoad, kitchenSinkReady workload profiles.

@lag/report

ExportWhat it does
RunReport, SuiteResult, TestCaseResult, CoverageReport, MutationReport, Measurement, BudgetResult, RunIndex, RunSummaryThe data format of a test run. SCHEMA_VERSION gives its version.
fromVitestJson, fromIstanbulSummary, fromStrykerReportConvert the reports of Vitest, Istanbul and Stryker.
countStatuses, summarizeRunSummaries for the results viewer.

lag: Main-thread responsiveness monitoring for browser apps, exported as OpenTelemetry metrics.

To change a page, edit its file in packages/site/content/. The writing style guide tells you how.

An AI model (Claude, from Anthropic) wrote most of the text and the code of this site and of the library, under the direction of the author. The tests and the STE linter examine them. The writing standard gives the reason for this note.