Skip to content

Ingestion

Tycho Engberink edited this page Feb 19, 2026 · 2 revisions

The Ingestion resource lets you send traces, spans, and generations to Langfuse. Every call sends immediately to the API -- no buffering or flushing required.

Access

$ingestion = $langfuse->ingestion();

The environment is set on the Langfuse constructor and applied to all ingestion events automatically.

Concepts

Object Description Created from
Trace Root of an observation tree. Represents a single request or workflow. $ingestion->trace()
Span Groups related work within a trace. Can be nested. $trace->span() or $span->span()
Generation Represents an LLM call. $trace->generation() or $span->generation()

All objects expose an $id property and their $traceId. Context IDs (traceId, parentObservationId) are threaded automatically when using the fluent API.

Traces

A trace is the root of every observation tree.

Create a trace

$trace = $ingestion->trace(
    name: 'handle-request',
    userId: 'user-456',
    sessionId: 'session-789',
    input: 'What is the weather?',
    metadata: ['source' => 'api'],
    tags: ['production'],
);

echo $trace->id; // auto-generated UUID

$traceId is optional. If omitted, a UUID v4 is generated automatically. You can also provide your own:

$trace = $ingestion->trace(
    name: 'handle-request',
    traceId: 'my-custom-trace-id',
);

Update a trace

$trace->update(
    output: 'It is 22 degrees and sunny.',
    metadata: ['duration_ms' => 1234],
);

Parameters

Parameter Type Required Description
name string Yes Name of the trace
traceId ?string No Custom ID, auto-generated if omitted
sessionId ?string No Group traces by session
userId ?string No Associate with a user
input array|string|null No Input data
output array|string|null No Output data
metadata ?array No Arbitrary metadata
tags ?array No List of tags

Spans

Spans group related work within a trace. They can be nested to any depth.

Create a span from a trace

$span = $trace->span(name: 'web-search-batch');

Nest spans

$childSpan = $span->span(name: 'single-search');

traceId and parentObservationId are set automatically.

Update a span

$span->update(
    output: ['results' => 3],
    endTime: date('c'),
);

Create a generation from a span

$generation = $span->generation(
    name: 'summarize',
    input: 'Summarize the search results',
    output: 'Here is a summary...',
    model: 'gpt-4o',
);

Parameters

Parameter Type Required Description
name string Yes Name of the span
spanId ?string No Custom ID, auto-generated if omitted
input array|string|null No Input data
output array|string|null No Output data
startTime ?string No ISO 8601 timestamp, defaults to now
endTime ?string No ISO 8601 timestamp
metadata ?array No Arbitrary metadata

Generations

Generations represent LLM calls. Create them from a trace or a span.

From a trace

$generation = $trace->generation(
    name: 'llm-call',
    input: ['messages' => [['role' => 'user', 'content' => 'Hello']]],
    output: 'Hi there!',
    model: 'gpt-4o',
    modelParameters: ['temperature' => 0.7],
    promptName: 'greeting',
    promptVersion: 1,
);

From a span

$generation = $span->generation(
    name: 'summarize-call',
    input: 'Summarize this text',
    output: 'Summary text here.',
    model: 'gpt-4o',
);

Update a generation

$generation->update(
    output: 'Updated response',
    metadata: ['tokens' => 150],
    endTime: date('c'),
);

Parameters

Parameter Type Required Description
name string Yes Name of the generation
input array|string Yes Input sent to the LLM
output array|string Yes Output from the LLM
generationId ?string No Custom ID, auto-generated if omitted
model ?string No Model name (e.g. gpt-4o)
modelParameters ?array No Parameters like temperature, max_tokens
promptName ?string No Link to a Langfuse prompt
promptVersion ?int No Version of the linked prompt
metadata ?array No Arbitrary metadata
startTime ?string No ISO 8601 timestamp, defaults to now
endTime ?string No ISO 8601 timestamp

Full example

$ingestion = $langfuse->ingestion();

// 1. Create the trace
$trace = $ingestion->trace(
    name: 'handle-request',
    userId: 'user-789',
    input: 'What is the weather?',
);

// 2. Create a span for a batch of work
$span = $trace->span(name: 'search-batch');

    // 3. Nested child span
    $child = $span->span(name: 'weather-api-call');
    $child->update(output: ['temp' => 22], endTime: date('c'));

    // 4. LLM generation nested under the span
    $span->generation(
        name: 'summarize',
        input: 'Summarize weather data',
        output: 'It is 22 degrees and sunny.',
        model: 'gpt-4o',
    );

// 5. Close the span
$span->update(output: ['answer' => 'It is 22 degrees.'], endTime: date('c'));

// 6. Update the trace with the final output
$trace->update(output: 'It is 22 degrees and sunny.');

This produces the following observation tree in Langfuse:

handle-request (trace)
└── search-batch (span)
    ├── weather-api-call (span)
    └── summarize (generation)

Low-level API

You can also use Ingestion directly without the fluent objects:

// Send any event type
$ingestion->send('trace-create', [
    'id' => 'my-trace-id',
    'name' => 'my-trace',
    'timestamp' => Ingestion::now(),
    'environment' => 'production',
]);

Utility methods

Method Returns Description
Ingestion::uuid() string Generate a UUID v4
Ingestion::now() string Current UTC timestamp with milliseconds