Skip to main content

Basic Example

Create an instance of the logger:

import { logger, http } from '@elliemae/pui-diagnostics';

const appLogger = logger({
transport: http('https://int.api.ellielabs.com/diagnostics/v2/logging'),
index: 'myapp',
team: 'my team',
appName: 'Hello World App',
});

Log messages with different log levels:

appLogger.debug('Detailed debug info');
appLogger.info('My application log message');
appLogger.audit('User performed action');
appLogger.warn('Something unexpected');
appLogger.error('Something went wrong');
appLogger.fatal('Application crashed');

Logging Exceptions

try {
// ...
} catch (ex) {
appLogger.error({
code: 'puiweb002',
message: 'Unable to send message',
exception: ex as Error,
});
}

Changing Default Log Level

The default log level is INFO. Messages below this level (e.g. DEBUG) are not logged.

import { LogLevels } from '@elliemae/pui-diagnostics';

appLogger.setLogLevel(LogLevels.DEBUG);

Updating Logger Options at Runtime

appLogger.setOptions({
environment: 'prod',
instanceId: 'new-instance',
customerId: 'cust-456',
userId: 'user-789',
appVersion: '2.0.0',
loanId: 'loan-guid',
});

Logging Unhandled Errors

Automatically captures unhandled promise rejections and uncaught errors:

import { logUnhandledErrors } from '@elliemae/pui-diagnostics';

logUnhandledErrors(appLogger);

Logging Web Vitals

Logs Core Web Vitals (LCP, INP, CLS) metrics automatically:

import { webvitals } from '@elliemae/pui-diagnostics';

webvitals(appLogger);

Controlling Log Volume with HTTP Transport Options

The http transport accepts an optional second argument to control batching, rate limiting, and sampling. These options help reduce API load from high-volume applications.

const transport = http('https://api.ellielabs.com/diagnostics/v2/logging', {
flushInterval: 15000, // flush every 15 seconds (default: 10000)
maxBatchSize: 50, // flush early at 50 buffered logs (default: 50)
maxLogsPerInterval: 200, // drop non-critical logs beyond 200 per window (default: 0 = unlimited)
samplingRate: 0.5, // send ~50% of non-critical logs (default: 1 = all)
});

const appLogger = logger({
transport,
index: 'myapp',
team: 'my team',
appName: 'Hello World App',
});

Options Reference

OptionTypeDefaultDescription
flushIntervalnumber10000Milliseconds between batch flushes for non-critical logs
maxBatchSizenumber50Flush the batch early when it reaches this size
maxLogsPerIntervalnumber0Max non-critical logs per interval window. 0 = unlimited
samplingRatenumber1Sampling rate for non-critical logs (0–1). 1 = send all, 0.1 = send ~10%

Note: WARN, ERROR, and FATAL logs are always sent immediately and are never subject to batching, rate limiting, or sampling.

How batched logs are delivered (HTTP)

For batched payloads (non-critical logs flushed together), the transport prefers navigator.sendBeacon, which is well suited to page hide / unload because it does not block navigation.

If sendBeacon returns false (for example when the serialized batch exceeds the browser’s typical beacon size limit), the transport splits the batch in half and retries sendBeacon on each half, recursively, until each sub-batch is accepted or only one log row remains. A single row that still cannot be sent via beacon is sent with fetch (keepalive: true, with retries). If sendBeacon is missing or throws, the transport uses fetch for that payload.

Immediate (critical) logs use the same pattern for a single message: try sendBeacon, then fetch on failure.

Implications for your app:

  • Prefer a maxBatchSize that keeps each batch reasonably small so beacons succeed more often during unload.
  • Individual log payloads that are extremely large may still fail limits even as a single row; keep messages and attached context compact.

Using the Console Transport

For development or debugging, use the console transport instead of HTTP:

import { logger, Console } from '@elliemae/pui-diagnostics';

const appLogger = logger({
transport: Console(),
index: 'myapp',
team: 'my team',
appName: 'Hello World App',
});

Mirroring All Logs to Console

Send logs to your transport and the browser console:

const appLogger = logger({
transport: http('https://api.ellielabs.com/diagnostics/v2/logging'),
index: 'myapp',
team: 'my team',
appName: 'Hello World App',
logEverythingToConsole: true,
});

By default, only ERROR and FATAL logs are mirrored to the console.