Skip to content

Send StructuredOutput telemetry to Langfuse

Overview

This example shows the Langfuse connection inline, using the actual Langfuse environment variables already present in this repository. It wires the existing event bus into the telemetry projectors and then runs one small structured extraction.

Key concepts: - explicit LangfuseConfig / LangfuseHttpTransport / LangfuseExporter setup - RuntimeEventBridge: attaches telemetry projection to the runtime event bus - LangfuseExporter: sends canonical telemetry to Langfuse over HTTP - InstructorTelemetryProjector: maps structured output lifecycle events - PolyglotTelemetryProjector: captures the nested LLM inference spans - HttpClientTelemetryProjector: captures outbound HTTP spans

Example

<?php
require 'examples/boot.php';

use Cognesy\Config\Env;
use Cognesy\Events\Dispatchers\EventDispatcher;
use Cognesy\Http\Telemetry\HttpClientTelemetryProjector;
use Cognesy\Instructor\StructuredOutput;
use Cognesy\Instructor\StructuredOutputRuntime;
use Cognesy\Instructor\Telemetry\InstructorTelemetryProjector;
use Cognesy\Polyglot\Inference\LLMProvider;
use Cognesy\Polyglot\Telemetry\PolyglotTelemetryProjector;
use Cognesy\Telemetry\Adapters\Langfuse\LangfuseConfig;
use Cognesy\Telemetry\Adapters\Langfuse\LangfuseExporter;
use Cognesy\Telemetry\Adapters\Langfuse\LangfuseHttpTransport;
use Cognesy\Telemetry\Application\Registry\TraceRegistry;
use Cognesy\Telemetry\Application\Telemetry;
use Cognesy\Telemetry\Application\Projector\CompositeTelemetryProjector;
use Cognesy\Telemetry\Application\Projector\RuntimeEventBridge;

class SupportTicket
{
    public string $priority;
    public string $summary;
}

$serviceName = 'examples.a03.telemetry-langfuse';
$baseUrl = (string) Env::get('LANGFUSE_BASE_URL', '');
if ($baseUrl === '') {
    throw new RuntimeException('Set LANGFUSE_BASE_URL in .env to run this example.');
}
$publicKey = (string) Env::get('LANGFUSE_PUBLIC_KEY', '');
if ($publicKey === '') {
    throw new RuntimeException('Set LANGFUSE_PUBLIC_KEY in .env to run this example.');
}
$secretKey = (string) Env::get('LANGFUSE_SECRET_KEY', '');
if ($secretKey === '') {
    throw new RuntimeException('Set LANGFUSE_SECRET_KEY in .env to run this example.');
}

$events = new EventDispatcher($serviceName);
$hub = new Telemetry(
    registry: new TraceRegistry(),
    exporter: new LangfuseExporter(
        transport: new LangfuseHttpTransport(new LangfuseConfig(
            baseUrl: $baseUrl,
            publicKey: $publicKey,
            secretKey: $secretKey,
        )),
    ),
);

(new RuntimeEventBridge(new CompositeTelemetryProjector([
    new InstructorTelemetryProjector($hub),
    new PolyglotTelemetryProjector($hub),
    new HttpClientTelemetryProjector($hub),
])))->attachTo($events);

$runtime = StructuredOutputRuntime::fromProvider(
    provider: LLMProvider::using('openai'),
    events: $events,
);

$ticket = (new StructuredOutput($runtime))
    ->with(
        messages: 'Customer report: The checkout page returns a 500 error after payment. Treat this as urgent and summarize it in one sentence.',
        responseModel: SupportTicket::class,
    )
    ->get();

$hub->flush();

echo "Priority: {$ticket->priority}\n";
echo "Summary: {$ticket->summary}\n";
echo "Telemetry: flushed to Langfuse\n";

assert($ticket->priority !== '');
assert($ticket->summary !== '');
?>