CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-langfuse--langfuse-java

Java client for the Langfuse API providing access to observability and analytics features for LLM applications

Overview
Eval results
Files

traces-observations.mddocs/

Traces and Observations

The Traces and Observations APIs provide retrieval and management of tracing data. Traces represent complete workflows or requests, while observations (spans, events, generations) represent individual operations within traces. For creating traces and observations, use the Ingestion API.

Capabilities

TraceClient

Client for retrieving and deleting traces.

/**
 * Get a specific trace with full details
 * Includes observations and scores
 *
 * @param traceId Unique trace identifier
 * @param requestOptions Optional request configuration
 */
TraceWithFullDetails get(String traceId);
TraceWithFullDetails get(String traceId, RequestOptions requestOptions);

/**
 * List traces with filters and pagination
 *
 * @param request Optional filters (userId, name, sessionId, tags, dates, etc.)
 * @param requestOptions Optional request configuration
 */
Traces list();
Traces list(GetTracesRequest request);
Traces list(GetTracesRequest request, RequestOptions requestOptions);

/**
 * Delete a specific trace
 * Irreversible operation
 *
 * @param traceId Unique trace identifier
 * @param requestOptions Optional request configuration
 */
DeleteTraceResponse delete(String traceId);
DeleteTraceResponse delete(String traceId, RequestOptions requestOptions);

/**
 * Delete multiple traces at once
 * Irreversible operation
 *
 * @param request List of trace IDs to delete
 * @param requestOptions Optional request configuration
 */
DeleteTraceResponse deleteMultiple(DeleteTracesRequest request);
DeleteTraceResponse deleteMultiple(DeleteTracesRequest request, RequestOptions requestOptions);

Usage Examples:

import com.langfuse.client.LangfuseClient;
import com.langfuse.client.resources.trace.requests.*;
import com.langfuse.client.resources.trace.types.*;
import com.langfuse.client.resources.commons.types.*;
import java.time.OffsetDateTime;
import java.util.List;

LangfuseClient client = LangfuseClient.builder()
    .url("https://cloud.langfuse.com")
    .credentials("pk-lf-...", "sk-lf-...")
    .build();

// Get a specific trace
TraceWithFullDetails trace = client.trace().get("trace-123");
System.out.println("Trace: " + trace.getName());
System.out.println("Observations: " + trace.getObservations().size());
System.out.println("Scores: " + trace.getScores().size());

// List traces for a user
GetTracesRequest request = GetTracesRequest.builder()
    .userId("user-456")
    .limit(10)
    .orderBy("timestamp.desc")  // String format: "field.direction"
    .build();

Traces traces = client.trace().list(request);
for (Trace t : traces.getData()) {
    System.out.println(t.getName() + " - " + t.getTimestamp());
}

// Filter by tags and environment (tags is comma-separated string)
GetTracesRequest prodRequest = GetTracesRequest.builder()
    .tags("production,critical")  // Comma-separated string, not List
    .environment("production")
    .build();

Traces prodTraces = client.trace().list(prodRequest);

// Delete a trace
DeleteTraceResponse deleteResp = client.trace().delete("trace-123");
System.out.println("Deleted: " + deleteResp.getDeletedTraceIds());

// Delete multiple traces
DeleteTracesRequest deleteMultiple = DeleteTracesRequest.builder()
    .traceIds(List.of("trace-1", "trace-2", "trace-3"))
    .build();

DeleteTraceResponse batchDelete = client.trace().deleteMultiple(deleteMultiple);

ObservationsClient

Client for retrieving observations (spans, events, generations).

/**
 * Get a specific observation
 *
 * @param observationId Unique observation identifier
 * @param requestOptions Optional request configuration
 */
ObservationsView get(String observationId);
ObservationsView get(String observationId, RequestOptions requestOptions);

/**
 * Get a list of observations with filters
 *
 * @param request Optional filters (name, userId, type, traceId, dates, etc.)
 * @param requestOptions Optional request configuration
 */
ObservationsViews getMany();
ObservationsViews getMany(GetObservationsRequest request);
ObservationsViews getMany(GetObservationsRequest request, RequestOptions requestOptions);

Usage Examples:

import com.langfuse.client.resources.observations.types.*;
import com.langfuse.client.resources.observations.requests.GetObservationsRequest;
import com.langfuse.client.resources.ingestion.types.ObservationType;
import java.time.OffsetDateTime;

// Get a specific observation
ObservationsView observation = client.observations().get("obs-123");
System.out.println("Observation: " + observation.getName());
System.out.println("Type: " + observation.getType());

// List observations for a trace
GetObservationsRequest request = GetObservationsRequest.builder()
    .traceId("trace-123")
    .build();

ObservationsViews observations = client.observations().getMany(request);
for (ObservationsView obs : observations.getData()) {
    System.out.println(obs.getName() + " (" + obs.getType() + ")");
}

// Filter by type and date range
GetObservationsRequest genRequest = GetObservationsRequest.builder()
    .type("GENERATION")  // String, not enum
    .fromStartTime(OffsetDateTime.parse("2025-10-01T00:00:00Z"))
    .toStartTime(OffsetDateTime.parse("2025-10-14T23:59:59Z"))
    .limit(50)
    .build();

ObservationsViews generations = client.observations().getMany(genRequest);

Request Types

GetTracesRequest

Import: import com.langfuse.client.resources.trace.requests.GetTracesRequest;

/**
 * Request parameters for listing traces
 * Located in requests package (not types)
 */
public final class GetTracesRequest {
    Optional<Integer> getPage();               // Page number (default: 1)
    Optional<Integer> getLimit();              // Items per page (default: 50)
    Optional<String> getUserId();              // Filter by user ID
    Optional<String> getName();                // Filter by trace name
    Optional<String> getSessionId();           // Filter by session ID
    Optional<OffsetDateTime> getFromTimestamp(); // Filter by start date
    Optional<OffsetDateTime> getToTimestamp(); // Filter by end date
    Optional<String> getOrderBy();             // Sort order as string (e.g., "timestamp.desc")
    Optional<String> getTags();                // Comma-separated tags (must match all)
    Optional<String> getVersion();             // Filter by version
    Optional<String> getRelease();             // Filter by release
    Optional<String> getEnvironment();         // Filter by environment
    Optional<String> getFields();              // Comma-separated field groups (core, io, scores, observations, metrics)

    static Builder builder();
}

DeleteTracesRequest

/**
 * Request for deleting multiple traces
 */
public final class DeleteTracesRequest {
    List<String> getTraceIds();  // List of trace IDs to delete

    static Builder builder();
}

GetObservationsRequest

Import: import com.langfuse.client.resources.observations.requests.GetObservationsRequest;

/**
 * Request parameters for listing observations
 * Located in requests package (not types)
 */
public final class GetObservationsRequest {
    Optional<Integer> getPage();               // Page number (default: 1)
    Optional<Integer> getLimit();              // Items per page (default: 50)
    Optional<String> getName();                // Filter by observation name
    Optional<String> getUserId();              // Filter by user ID
    Optional<String> getType();                // Filter by type as string ("SPAN", "EVENT", "GENERATION")
    Optional<String> getTraceId();             // Filter by trace ID
    Optional<String> getParentObservationId(); // Filter by parent observation ID
    Optional<String> getEnvironment();         // Filter by environment
    Optional<OffsetDateTime> getFromStartTime(); // Filter by start date
    Optional<OffsetDateTime> getToStartTime(); // Filter by end date
    Optional<String> getVersion();             // Filter by version

    static Builder builder();
}

Response Types

TraceWithFullDetails

/**
 * Trace with complete details including observations and scores
 */
public final class TraceWithFullDetails {
    String getId();
    OffsetDateTime getTimestamp();      // Timestamp as OffsetDateTime
    Optional<String> getName();
    Optional<String> getUserId();
    Optional<Object> getMetadata();
    Optional<String> getRelease();
    Optional<String> getVersion();
    Optional<String> getProjectId();
    Optional<Boolean> getPublic();
    Optional<Boolean> getBookmarked();
    Optional<List<String>> getTags();
    Optional<Object> getInput();
    Optional<Object> getOutput();
    Optional<String> getSessionId();
    List<Observation> getObservations(); // All observations in trace
    List<ScoreV1> getScores();          // All scores for trace

    static Builder builder();
}

Traces

/**
 * Paginated list of traces
 */
public final class Traces {
    List<Trace> getData();
    MetaResponse getMeta();  // Pagination metadata

    static Builder builder();
}

Trace

Basic trace object (see Common Types for full definition).

DeleteTraceResponse

/**
 * Response after deleting trace(s)
 */
public final class DeleteTraceResponse {
    List<String> getDeletedTraceIds();  // IDs of deleted traces

    static Builder builder();
}

ObservationsView

/**
 * Observation with additional computed fields
 */
public final class ObservationsView {
    String getId();
    String getTraceId();
    String getProjectId();
    Optional<ObservationType> getType();        // SPAN, EVENT, GENERATION
    Optional<String> getParentObservationId();
    Optional<String> getName();
    Optional<Object> getMetadata();
    Optional<String> getModel();
    Optional<Object> getModelParameters();
    Optional<String> getStartTime();            // ISO 8601 timestamp
    Optional<String> getEndTime();              // ISO 8601 timestamp
    Optional<String> getCompletionStartTime();  // ISO 8601 timestamp
    Optional<Object> getInput();
    Optional<Object> getOutput();
    Optional<Usage> getUsage();                 // Token usage
    Optional<ObservationLevel> getLevel();      // DEBUG, DEFAULT, WARNING, ERROR
    Optional<String> getStatusMessage();
    Optional<String> getVersion();
    Optional<String> getEnvironment();
    Optional<String> getPromptId();
    Optional<String> getPromptName();
    Optional<Integer> getPromptVersion();
    Optional<ModelPrice> getModelPrice();       // Computed pricing
    Optional<Double> getTotalCost();            // Computed cost
    Optional<Double> getLatency();              // Computed latency in seconds

    static Builder builder();
}

ObservationsViews

/**
 * Paginated list of observations
 */
public final class ObservationsViews {
    List<ObservationsView> getData();
    MetaResponse getMeta();  // Pagination metadata

    static Builder builder();
}

Observation

Core observation object (see Common Types for full definition).

Enums

Sort

/**
 * Sort order for traces
 */
public enum Sort {
    TIMESTAMP_ASC,
    TIMESTAMP_DESC
}

ObservationType

/**
 * Type of observation
 */
public enum ObservationType {
    SPAN,       // Operation or sub-process
    EVENT,      // Point-in-time occurrence
    GENERATION  // LLM generation call
}

ObservationLevel

/**
 * Log level for observations
 */
public enum ObservationLevel {
    DEBUG,
    DEFAULT,
    WARNING,
    ERROR
}

Complete Trace Analysis Example

import com.langfuse.client.LangfuseClient;
import com.langfuse.client.resources.trace.requests.*;
import com.langfuse.client.resources.trace.types.*;
import com.langfuse.client.resources.observations.requests.*;
import com.langfuse.client.resources.observations.types.*;
import com.langfuse.client.resources.commons.types.*;
import com.langfuse.client.resources.ingestion.types.ObservationType;

public class TraceAnalysisExample {
    public static void main(String[] args) {
        LangfuseClient client = LangfuseClient.builder()
            .url("https://cloud.langfuse.com")
            .credentials("pk-lf-...", "sk-lf-...")
            .build();

        // 1. List recent traces for a user
        GetTracesRequest request = GetTracesRequest.builder()
            .userId("user-123")
            .fromTimestamp(OffsetDateTime.parse("2025-10-14T00:00:00Z"))
            .orderBy("timestamp.desc")  // String format, not Sort enum
            .limit(10)
            .build();

        Traces traces = client.trace().list(request);

        System.out.println("Found " + traces.getMeta().getTotalItems() + " traces");

        // 2. Analyze each trace
        for (Trace trace : traces.getData()) {
            System.out.println("\nTrace: " + trace.getName());
            System.out.println("ID: " + trace.getId());
            System.out.println("User: " + trace.getUserId());
            System.out.println("Session: " + trace.getSessionId().orElse("none"));

            // Get full trace details
            TraceWithFullDetails fullTrace = client.trace().get(trace.getId());

            // Analyze observations
            System.out.println("Observations: " + fullTrace.getObservations().size());

            for (Observation obs : fullTrace.getObservations()) {
                System.out.println("  - " + obs.getName().orElse("unnamed") +
                                 " (" + obs.getType().orElse(null) + ")");
            }

            // Analyze scores
            System.out.println("Scores: " + fullTrace.getScores().size());
            for (ScoreV1 score : fullTrace.getScores()) {
                System.out.println("  - " + score.getName() + ": " + score.getValue());
            }

            // Calculate trace metrics
            if (!fullTrace.getObservations().isEmpty()) {
                double totalCost = 0.0;
                int totalTokens = 0;

                for (Observation obs : fullTrace.getObservations()) {
                    // Get observation details for computed metrics
                    GetObservationsRequest obsReq = GetObservationsRequest.builder()
                        .traceId(trace.getId())
                        .build();

                    ObservationsViews obsViews = client.observations().getMany(obsReq);

                    for (ObservationsView view : obsViews.getData()) {
                        if (view.getTotalCost().isPresent()) {
                            totalCost += view.getTotalCost().get();
                        }
                        if (view.getUsage().isPresent()) {
                            Usage usage = view.getUsage().get();
                            if (usage.getTotal().isPresent()) {
                                totalTokens += usage.getTotal().get();
                            }
                        }
                    }
                }

                System.out.println("Total cost: $" + totalCost);
                System.out.println("Total tokens: " + totalTokens);
            }
        }

        // 3. Find all generations with errors
        GetObservationsRequest errorRequest = GetObservationsRequest.builder()
            .type("GENERATION")  // String, not enum
            .fromStartTime(OffsetDateTime.parse("2025-10-14T00:00:00Z"))
            .limit(100)
            .build();

        ObservationsViews observations = client.observations().getMany(errorRequest);

        System.out.println("\n\nGenerations with errors:");
        for (ObservationsView obs : observations.getData()) {
            if (obs.getLevel().isPresent() && obs.getLevel().get() == ObservationLevel.ERROR) {
                System.out.println("Error in trace " + obs.getTraceId() + ": " +
                                 obs.getStatusMessage().orElse("no message"));
            }
        }

        // 4. Analyze high-cost traces
        System.out.println("\n\nHigh-cost observations:");
        for (ObservationsView obs : observations.getData()) {
            if (obs.getTotalCost().isPresent() && obs.getTotalCost().get() > 0.01) {
                System.out.println("Trace " + obs.getTraceId() +
                                 " - Model: " + obs.getModel().orElse("unknown") +
                                 " - Cost: $" + obs.getTotalCost().get());
            }
        }

        // 5. Clean up old test traces
        GetTracesRequest oldTestsRequest = GetTracesRequest.builder()
            .tags("test")  // String, not List
            .toTimestamp(OffsetDateTime.parse("2025-10-01T00:00:00Z"))
            .limit(100)
            .build();

        Traces oldTests = client.trace().list(oldTestsRequest);

        if (!oldTests.getData().isEmpty()) {
            List<String> traceIds = oldTests.getData().stream()
                .map(Trace::getId)
                .collect(java.util.stream.Collectors.toList());

            DeleteTracesRequest deleteRequest = DeleteTracesRequest.builder()
                .traceIds(traceIds)
                .build();

            DeleteTraceResponse deleteResponse = client.trace().deleteMultiple(deleteRequest);
            System.out.println("\nDeleted " + deleteResponse.getDeletedTraceIds().size() +
                             " old test traces");
        }
    }
}

Query Patterns

Finding Traces by Session

GetTracesRequest sessionRequest = GetTracesRequest.builder()
    .sessionId("session-123")
    .orderBy("timestamp.asc")  // String format, not Sort enum
    .build();

Traces sessionTraces = client.trace().list(sessionRequest);

Finding Observations by Parent

GetObservationsRequest childRequest = GetObservationsRequest.builder()
    .parentObservationId("parent-obs-123")
    .build();

ObservationsViews children = client.observations().getMany(childRequest);

Filtering by Environment and Version

GetTracesRequest prodRequest = GetTracesRequest.builder()
    .environment("production")
    .version("v2.1.0")
    .build();

Traces prodTraces = client.trace().list(prodRequest);

Best Practices

  1. Use Pagination: Always set appropriate page size limits for large result sets
  2. Filter by Date: Use date range filters to limit query scope and improve performance
  3. Index on Tags: Use tags for efficient filtering of traces by feature or category
  4. Session Grouping: Group related traces using sessionId for workflow analysis
  5. Environment Separation: Use environment field to separate production/staging/development data
  6. Cost Monitoring: Regularly query ObservationsView to monitor LLM costs
  7. Error Tracking: Filter by ObservationLevel.ERROR to find and analyze failures
  8. Deletion Caution: Trace deletion is irreversible - use with care

Related Documentation

Install with Tessl CLI

npx tessl i tessl/maven-com-langfuse--langfuse-java

docs

client-configuration.md

comments-annotations.md

common-types.md

datasets.md

exceptions.md

health.md

index.md

ingestion.md

media.md

metrics.md

models.md

pagination.md

projects-organizations.md

prompts.md

scim.md

scores.md

sessions.md

traces-observations.md

tile.json