Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Langfuse Langfuse Observations Converters

From Leeroopedia
Knowledge Sources
Domains Tracing, Data Transformation, ClickHouse
Last Updated 2026-02-14 00:00 GMT

Overview

Converter functions that transform raw ClickHouse observation records into typed domain models, supporting both complete (V1 API) and partial (V2 API) observation output formats with model pricing enrichment.

Description

This module provides the data transformation layer between ClickHouse observation record types and Langfuse domain model types. It handles the conversion of ClickHouse-specific formats (UTC datetime strings, string-typed int64 values, map-based usage/cost details) into JavaScript-native domain objects.

Key functions:

  • convertObservation -- Converts a complete ObservationRecordReadType to an Observation domain object. This is the primary converter for V1 API responses where all fields must be present with sensible defaults.
  • convertObservationPartial -- Overloaded function supporting both complete and partial conversion modes:
    • With complete: true: Returns a full Observation with all missing fields filled with defaults (null, 0, empty objects).
    • With complete: false: Returns a PartialObservation containing only the fields present in the input record. This is used by the V2 API to return only requested field groups for better performance.
  • convertEventsObservation -- Events-specific converter that extends the base conversion with userId, sessionId, and traceName fields that are only available in the events table. Also supports complete/partial overloads.
  • enrichObservationWithModelData -- Takes a Model with Price records and returns an object with modelId, inputPrice, outputPrice, and totalPrice fields for merging into observation responses.
  • reduceUsageOrCostDetails -- Aggregates a usage/cost details map into { input, output, total } by matching key prefixes ("input*", "output*", "total").

Internal helpers:

  • convertNumericRecord -- Ensures all values in a Record<string, number> are actual numbers (handles ClickHouse's string-typed int64s).
  • ensureObservationCoreFields -- Validates that required core fields (id, trace_id, start_time, project_id) are present, throwing descriptive errors if missing.

The module uses parseClickhouseUTCDateTimeFormat for date conversion, parseMetadataCHRecordToDomain for metadata transformation, and applyInputOutputRendering for optional JSON parsing and truncation of I/O fields.

Usage

Use convertObservation in repository functions that return complete observation objects (single lookups, trace detail views). Use convertObservationPartial with complete: false for V2 API endpoints that support selective field groups. Use convertEventsObservation when working with the events table. Use enrichObservationWithModelData to add pricing information from PostgreSQL model records.

Code Reference

Source Location

Signature

export function convertObservation(
  record: ObservationRecordReadType,
  renderingProps?: RenderingProps,
): Observation;

export function convertObservationPartial(
  record: ObservationRecordReadType,
  renderingProps: RenderingProps,
  complete: true,
): Observation;
export function convertObservationPartial(
  record: Partial<ObservationRecordReadType>,
  renderingProps: RenderingProps,
  complete: false,
): PartialObservation;

export function convertEventsObservation(
  record: EventsObservationRecordReadType,
  renderingProps: RenderingProps,
  complete: true,
): EventsObservation;
export function convertEventsObservation(
  record: Partial<EventsObservationRecordReadType>,
  renderingProps: RenderingProps,
  complete: false,
): PartialEventsObservation;

export const enrichObservationWithModelData = (
  model: (Model & { Price: Price[] }) | null | undefined,
) => {
  modelId: string | null;
  inputPrice: Decimal | null;
  outputPrice: Decimal | null;
  totalPrice: Decimal | null;
};

export const reduceUsageOrCostDetails = (
  details: Record<string, number> | null | undefined,
) => { input: number | null; output: number | null; total: number | null };

Import

import {
  convertObservation,
  convertObservationPartial,
  convertEventsObservation,
  enrichObservationWithModelData,
  reduceUsageOrCostDetails,
} from "@langfuse/shared/src/server/repositories/observations_converters";

I/O Contract

Inputs

Name Type Required Description
record ObservationRecordReadType Yes Raw ClickHouse observation record with string dates and map-based usage
record (events) EventsObservationRecordReadType Yes (for events) Events table record with additional user_id, session_id, trace_name
renderingProps RenderingProps No Controls JSON parsing and truncation of input/output fields
complete boolean Yes (for partial) true = V1 complete output; false = V2 partial output
model Model & { Price: Price[] } No Prisma model record with pricing for enrichment
details Record<string, number> No Usage or cost details map to reduce

Outputs

Name Type Description
Observation Observation Complete domain object with all fields populated (defaults for missing)
PartialObservation PartialObservation Domain object with only present fields (for V2 API)
EventsObservation EventsObservation Observation with userId, sessionId, traceName
PartialEventsObservation PartialEventsObservation Partial events observation for V2 API
Price enrichment { modelId, inputPrice, outputPrice, totalPrice } Model pricing data for merging
Reduced details { input, output, total } Aggregated usage/cost by prefix

Usage Examples

import {
  convertObservation,
  convertObservationPartial,
  enrichObservationWithModelData,
  reduceUsageOrCostDetails,
} from "@langfuse/shared/src/server/repositories/observations_converters";

// Convert a complete observation (V1 API)
const observation = convertObservation(clickhouseRecord);
console.log(observation.startTime); // JavaScript Date
console.log(observation.usageDetails); // { input: 100, output: 50 }

// Convert partial observation (V2 API - only requested fields)
const partial = convertObservationPartial(partialRecord, { shouldJsonParse: true, truncated: false }, false);
// partial.input exists only if it was in the record

// Enrich with model pricing
const pricing = enrichObservationWithModelData(modelWithPrices);
const enriched = { ...observation, ...pricing };

// Reduce usage details
const reduced = reduceUsageOrCostDetails({ input: 100, "input:cached": 20, output: 50, total: 170 });
// { input: 120, output: 50, total: 170 }

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment