Because
Node.jsSDK

Traces & spans

startTrace, addSpan, addMessage, setOutput, and init.

because.init(options?)

Configure the SDK. Call once at app startup.

import because from '@refactorlabs/because';

because.init({
  apiKey: 'your-api-key', // falls back to BECAUSE_API_KEY env var
  apiUrl: 'https://...' // optional, override the ingest endpoint
});

If no API key is found, the SDK disables itself. All calls become no-ops with no errors thrown.

Options

OptionTypeDescription
apiKeystringYour Because API key
apiUrlstringOverride the default ingest URL
debugbooleanLog SDK operations to stdout

because.startTrace(name, fn)

Wraps an async function in a trace. The trace is sent to Because when fn resolves or throws.

await because.startTrace('Assess claim', async () => {
  // work happens here
});

name must be 5–500 characters. Any characters are accepted, so names like Insurance claim - CLM-2024-03941 work fine.

Pass options as the second argument:

await because.startTrace(
  'Insurance claim - CLM-2024-03941',
  {
    input: because
      .table('Claim submission')
      .fromObject({ claimId: 'CLM-2024-03941', vehicle: '2019 Toyota Camry' })
      .build(),
    metadata: { claimId: 'CLM-2024-03941', policyNumber: 'POL-8821-AU' },
    retentionPeriod: '30d'
  },
  async () => {
    // work happens here
  }
);

Options

OptionTypeDescription
inputJsonObjectInput data attached to the trace
metadataRecord<string, string | number | boolean | null>Filterable key-value metadata
retentionPeriodRetentionPeriodHow long to keep the trace. Default: '7d'

Retention periods

type RetentionPeriod = '1d' | '7d' | '30d' | '90d' | '1y';

because.addSpan(type, name, ...)

Add a span to the currently active trace. Must be called within a startTrace callback. name follows the same 5–500 character rule as trace names.

There are two forms: static and callback.

Static form

Pass an options object to set input, output, durationMs, and other fields manually:

because.addSpan('db', 'Policy lookup', {
  metadata: { table: 'policies', queryType: 'sql' },
  input: {
    query: 'SELECT * FROM policies WHERE number = $1',
    params: ['POL-8821-AU']
  },
  output: { rows: 1 }
});

Callback form

Pass an async callback and Because handles timing and output automatically. The span's durationMs is set from how long the callback takes, and its output is set from the callback's return value.

const policy = await because.addSpan('json', 'Load policy', async () => {
  return await db.policies.findOne({ number: 'POL-8821-AU' });
  //     ^ becomes the span output automatically
});
// policy is typed to the return value

Pass options as the third argument to include input, alerts, redact, or metadata:

await because.addSpan(
  'json',
  'Load policy',
  { input: { policyNumber: 'POL-8821-AU' }, redact: ['holder.name'] },
  async () => {
    return await db.policies.findOne({ number: 'POL-8821-AU' });
  }
);

Overloads

SignatureDescription
addSpan(type, name, options?)Static - set all fields manually
addSpan(type, name, fn)Callback - auto-timing, auto-output
addSpan(type, name, opts, fn)Callback with options

Span types

TypeUse for
messagePlain text output
jsonStructured JSON data
tableTabular data (use because.table())
chartCharts (use because.chart())
httpHTTP requests (usually via because.fetch())
llmLLM calls, see LLM spans
imageImages rendered inline, see Image spans
dbDatabase queries, see Database spans

Options

OptionTypeDescription
inputJsonObjectInput to this step
outputJsonObjectOutput from this step
durationMsnumberHow long this step took
metadataDbSpanMetadataWhen type: 'db', set collection, table, or queryType
alertsSpanAlert[]Threshold rules evaluated at ingest. See Alerts
redactstring[]Fields to redact from input/output. See Redaction

because.addMessage(name, text, opts?)

Shorthand for adding a message span. Useful for log-style checkpoints.

because.addMessage('Validation passed', 'All policy checks cleared', {
  level: 'info'
});
because.addMessage(
  'High-value claim',
  'Claim exceeds $10,000 - flagged for review',
  { level: 'warn' }
);

Options

OptionTypeDescription
level'info' | 'warn' | 'error'Severity. Default: 'info'

because.setOutput(output, redact?)

Set the output on the active trace. Call at the end of a startTrace callback.

await because.startTrace('Insurance claim - CLM-2024-03941', async () => {
  // ... spans ...
  because.setOutput({
    claimId: 'CLM-2024-03941',
    decision: 'approved',
    settlement: 6840
  });
});

Pass a redact array as the second argument to redact fields before the output is stored:

because.setOutput(
  { decision: 'approved', claimant: { name: 'James Okafor', address: '...' } },
  ['claimant.name']
);

See Redaction for the full redaction syntax.

On this page