Documentation
¶
Overview ¶
Package langfuse provides observation-centric Langfuse tracing on top of OpenTelemetry.
It exports OTLP/HTTP protobuf traces to Langfuse and can either own an isolated tracer provider or attach a Langfuse processor to an existing OpenTelemetry SDK tracer provider through Config. The package never changes global OpenTelemetry state.
Construct a Client with New, typically from ConfigFromEnv, stamp request-scoped identity with Client.WithTraceAttributes, and record work with Client.Observe:
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
return err
}
defer lf.Shutdown(shutdownCtx)
err = lf.Observe(ctx, "answer-question", langfuse.TypeGeneration,
langfuse.ObservationAttributes{Input: question},
func(ctx context.Context, o *langfuse.Observation) error {
answer, err := callModel(ctx, question)
o.Update(langfuse.ObservationAttributes{Output: answer})
return err
})
Client.StartObservation is the lower-level pair for lifetimes that span functions; the context it returns carries the parent-child relationship, so observations started from it nest under their parent. Client.RecordScore submits evaluations and user feedback through the Langfuse JSON ingestion endpoint, Client.GetPrompt loads prompt-management prompts with client-side caching and an optional local fallback, and Client.Flush and Client.Shutdown control the export lifecycle. Whole traces can be sampled deterministically by trace ID through Config.SampleRate and Client.WithSampleRate, with TraceSampledAt exposing the same decision for correlated application-level sampling. A nil or disabled Client and the zero Observation are safe no-ops.
Index ¶
- Variables
- func TraceSampledAt(traceID string, fraction float64) (bool, error)
- type Client
- func (c *Client) Event(ctx context.Context, name string, values ObservationAttributes)
- func (c *Client) Flush(ctx context.Context) error
- func (c *Client) GetPrompt(ctx context.Context, name string, query PromptQuery) (Prompt, error)
- func (c *Client) Observe(ctx context.Context, name string, observationType ObservationType, ...) error
- func (c *Client) RecordScore(ctx context.Context, score Score) error
- func (c *Client) Shutdown(ctx context.Context) error
- func (c *Client) StartObservation(ctx context.Context, name string, observationType ObservationType, ...) (context.Context, *Observation)
- func (c *Client) WithSampleRate(ctx context.Context, fraction float64) context.Context
- func (c *Client) WithTraceAttributes(ctx context.Context, values TraceAttributes) context.Context
- type Config
- type Level
- type Observation
- type ObservationAttributes
- type ObservationType
- type Prompt
- type PromptFallback
- type PromptMessage
- type PromptQuery
- type PromptRef
- type PromptSource
- type PromptType
- type Score
- type ScoreDataType
- type TraceAttributes
- type Usage
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrPromptNotFound = errors.New("langfuse: prompt not found")
ErrPromptNotFound reports that the requested prompt name, version, or label does not exist in the Langfuse project. Test with errors.Is.
var ErrPromptTypeMismatch = errors.New("langfuse: prompt type mismatch")
ErrPromptTypeMismatch reports that a resolved prompt did not have the type requested by PromptQuery.Type. Test with errors.Is.
Functions ¶
func TraceSampledAt ¶ added in v0.4.0
TraceSampledAt reports whether the trace identified by the 32-character lowercase hex traceID falls inside fraction under the SDK's deterministic threshold scheme, the same scheme the isolated-mode sampler uses, shared with OpenTelemetry's TraceIDRatioBased. A trace selected at a smaller fraction is always selected at any larger one, so work gated at a small fraction (an expensive evaluation on 2% of traces) runs only on traces that a larger export fraction also kept. It returns an error for a malformed trace ID or a fraction that is not finite or not within [0, 1]; it never guesses. It is a pure predicate on the trace ID and does not know what rate the trace was actually sampled at: when gating work on an existing observation, gate on Observation.Sampled and on the returned decision together, after checking the error.
Example ¶
package main
import (
"fmt"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
// TraceSampledAt is deterministic: every caller agrees on the same trace,
// and a trace selected at a smaller fraction is always selected at a
// larger one. Gating an expensive evaluation at 2% therefore evaluates
// only traces that an export fraction of at least 2% also kept.
traceID := "0af7651916cd43dd8448eb211c80319c"
quarter, err := langfuse.TraceSampledAt(traceID, 0.25)
if err != nil {
log.Fatal(err)
}
majority, err := langfuse.TraceSampledAt(traceID, 0.6)
if err != nil {
log.Fatal(err)
}
fmt.Println(quarter, majority)
}
Output: false true
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client owns all Langfuse exporter, processor, and lifecycle state. Its zero value is a safe no-op.
func New ¶
New constructs a client and validates configuration without performing network I/O. A disabled configuration bypasses all other validation.
Example ¶
package main
import (
"context"
"log"
"time"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.Config{
BaseURL: "https://cloud.langfuse.com",
PublicKey: "pk-lf-...",
SecretKey: "sk-lf-...",
Environment: "production",
})
if err != nil {
log.Fatal(err)
}
defer func() {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = lf.Shutdown(shutdownCtx)
}()
_, observation := lf.StartObservation(ctx, "nightly-import", langfuse.TypeSpan,
langfuse.ObservationAttributes{Input: "42 records"})
observation.End()
}
Output:
func (*Client) Event ¶
func (c *Client) Event(ctx context.Context, name string, values ObservationAttributes)
Event records an instantaneous event observation.
func (*Client) Flush ¶
Flush exports all ended observations and delivers every score accepted before the call; scores recorded after Flush begins do not extend the wait. A score mid-retry holds Flush until it is delivered or dropped, bounded by ctx.
Example ¶
package main
import (
"context"
"log"
"time"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
lf.Event(ctx, "job-completed", langfuse.ObservationAttributes{
Metadata: map[string]any{"records": 42},
})
// Short-lived jobs and serverless handlers flush before returning so
// batched observations are exported while the client stays usable.
flushCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := lf.Flush(flushCtx); err != nil {
log.Printf("flush: %v", err)
}
}
Output:
func (*Client) GetPrompt ¶ added in v0.4.0
GetPrompt is safe to call on a nil, disabled, or shut-down client; with a Fallback set it returns that fallback, so callers need no nil guard.
GetPrompt fetches one prompt version from the Langfuse prompts API, serving it from the client-side cache when fresh. An expired entry is returned immediately while one background refresh per prompt runs; a cache miss fetches synchronously, bounded by ctx and a 10-second fetch budget. If the fetch fails for any reason other than ctx ending, query.Fallback is returned when set; otherwise the error carries at most the prompt name and HTTP status, and wraps ErrPromptNotFound for 404. A result whose type does not match query.Type likewise resolves to the fallback or wraps ErrPromptTypeMismatch. A nil ctx or invalid query is always an error.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
// Client setup may be optional in an application. GetPrompt remains safe
// when the client is nil, so the call site needs no separate nil branch.
var lf *langfuse.Client
prompt, err := lf.GetPrompt(context.Background(), "response-template", langfuse.PromptQuery{
Type: langfuse.PromptTypeText,
Fallback: &langfuse.PromptFallback{Text: "Process {{input}}."},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(prompt.Text)
fmt.Println(prompt.Source)
}
Output: Process {{input}}. fallback
func (*Client) Observe ¶
func (c *Client) Observe( ctx context.Context, name string, observationType ObservationType, values ObservationAttributes, fn func(ctx context.Context, observation *Observation) error, ) error
Observe starts an observation, runs fn with the child context and the observation handle, and always ends the observation, including when fn panics. A non-nil error returned by fn is recorded through Observation.RecordError and returned unchanged, so fn does not need to record it itself. When fn panics, the observation is marked failed with the payload-free status "panic", the panic value is never captured, and the panic propagates. On a nil, disabled, or stopped client fn still runs, receiving ctx unchanged and a no-op handle. A nil fn reports a diagnostic and starts no observation.
Example ¶
package main
import (
"context"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
err = lf.Observe(ctx, "retrieve-documents", langfuse.TypeRetriever,
langfuse.ObservationAttributes{Input: "safe api design"},
func(ctx context.Context, observation *langfuse.Observation) error {
// Child observations started from ctx nest under this one. The
// observation always ends, a returned error is recorded on it,
// and a panic is marked as a failure before it propagates.
documents, err := retrieve(ctx, "safe api design")
if err != nil {
return err
}
observation.Update(langfuse.ObservationAttributes{Output: documents})
return nil
})
if err != nil {
log.Printf("retrieve: %v", err)
}
}
func retrieve(ctx context.Context, query string) ([]string, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
return []string{"doc-" + query}, nil
}
Output:
func (*Client) RecordScore ¶
RecordScore submits one score through the Langfuse JSON ingestion endpoint using the client's credentials and environment. The score is validated synchronously, so every returned error marks a score that was not accepted, and then queued for asynchronous delivery with bounded retry (network errors, HTTP 408, 429, and 5xx responses, and per-item ingestion errors with those statuses, using the same backoff defaults as observation export), so transport failures never reach the caller: after the retry budget they are reported as payload-free OpenTelemetry diagnostics and the score is dropped. Client.Flush and Client.Shutdown drain accepted scores. When the queue is full a score is dropped with a diagnostic unless Config.BlockOnQueueFull waits for space, bounded by ctx. A disabled client returns nil without sending, and a shut-down client returns an error. The complete serialized score event is limited to 128 KiB.
Example ¶
package main
import (
"context"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
rating := 4.0
err = lf.RecordScore(ctx, langfuse.Score{
ID: "feedback-42", // idempotent upsert key
Name: "user-feedback",
SessionID: "conversation-456",
NumericValue: &rating,
Comment: "clear and concise answer",
})
if err != nil {
log.Printf("record score: %v", err)
}
}
Output:
func (*Client) Shutdown ¶
Shutdown permanently stops this Client after draining queued observations and scores, bounded by ctx. In borrowed mode it shuts down the Langfuse processor using ctx before unregistering it; the provider and all unrelated processors remain owned by the application.
func (*Client) StartObservation ¶
func (c *Client) StartObservation( ctx context.Context, name string, observationType ObservationType, values ObservationAttributes, ) (context.Context, *Observation)
StartObservation starts an observation. Child work must use the returned context to preserve the parent-child relationship.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
// StartObservation suits lifetimes that span functions, such as ending a
// generation only after a stream is fully consumed.
generationCtx, generation := lf.StartObservation(ctx, "generate-answer",
langfuse.TypeGeneration, langfuse.ObservationAttributes{
Model: "gemini-3.6-flash",
Input: "What is context in Go?",
})
defer generation.End()
answer, usage, err := callModel(generationCtx, "What is context in Go?")
if err != nil {
generation.RecordError(err)
return
}
generation.Update(langfuse.ObservationAttributes{Output: answer, Usage: &usage})
}
func callModel(ctx context.Context, question string) (string, langfuse.Usage, error) {
if err := ctx.Err(); err != nil {
return "", langfuse.Usage{}, err
}
return fmt.Sprintf("answer to %q", question), langfuse.Usage{
InputTokens: 6,
OutputTokens: 8,
}, nil
}
Output:
func (*Client) WithSampleRate ¶ added in v0.4.0
WithSampleRate returns a context that overrides the configured sample rate for the sampling decision made by the first SDK observation subsequently started on this context path. The fraction must be finite and within [0, 1]; 0 exports nothing, 1 exports everything. The decision is inherited by every SDK observation started from that observation's returned context (and inside its Client.Observe callback), so a rate set later on that path has no effect on the already-decided trace. Sibling observations started independently from a context that carries no decision yet re-decide deterministically from the trace ID and their own effective rate: with equal rates they always agree; setting different rates inside one trace makes trace membership subtree-scoped. Set the rate once per request, before the first observation, unless subtree-scoped rates are intended. An invalid fraction is ignored with a diagnostic, as is any call on a borrowed-provider client, where the application's sampler remains authoritative.
Example ¶
package main
import (
"context"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
// Set the rate once per request, before the first observation. The whole
// trace is then kept or dropped together, so a high-volume path can run
// at 2% while other request types keep the configured default.
ctx = lf.WithSampleRate(ctx, 0.02)
observationCtx, observation := lf.StartObservation(ctx, "classify-request",
langfuse.TypeGeneration, langfuse.ObservationAttributes{})
defer observation.End()
if observation.Sampled() {
// Attach expensive payloads only when the trace is kept for export.
observation.Update(langfuse.ObservationAttributes{Input: "large payload"})
}
_ = observationCtx
}
Output:
func (*Client) WithTraceAttributes ¶
WithTraceAttributes returns a context that propagates request-scoped trace fields to observations subsequently started from it. If an SDK observation belonging to this Client is active, it is updated immediately as well.
Example ¶
package main
import (
"context"
"log"
"github.com/fgn/go-langfuse"
)
func main() {
ctx := context.Background()
lf, err := langfuse.New(ctx, langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
// Stamp request-scoped identity once; observations started from the
// returned context share the same trace name, user, session, and tags.
ctx = lf.WithTraceAttributes(ctx, langfuse.TraceAttributes{
Name: "chat-turn",
UserID: "user-123",
SessionID: "conversation-456",
Tags: []string{"chat"},
})
observationCtx, observation := lf.StartObservation(ctx, "chat-turn",
langfuse.TypeAgent, langfuse.ObservationAttributes{})
defer observation.End()
_ = observationCtx
}
Output:
type Config ¶
type Config struct {
// BaseURL is the Langfuse host or OTLP traces endpoint. It defaults to
// https://cloud.langfuse.com.
BaseURL string
// PublicKey identifies the Langfuse project.
PublicKey string
// SecretKey authenticates writes to the Langfuse project.
SecretKey string
// Environment and Release are stamped on every span observed by the
// Langfuse processor.
Environment string
Release string
// SampleRate selects the fraction of traces exported in isolated mode,
// decided once per trace by a deterministic threshold on the trace ID and
// inherited by every SDK observation started on the deciding context
// path. nil selects the default of 1.0 (export everything); a non-nil
// value must be finite and within [0, 1], where 0 exports no traces while
// scores and prompts keep working. Other values are a validation error in
// [New]. It is ignored with a diagnostic when TracerProvider is set,
// where the application's sampler remains authoritative.
// [Client.WithSampleRate] overrides it per context path.
SampleRate *float64
// ServiceName overrides service.name on an SDK-owned provider. When empty,
// the standard OpenTelemetry resource.Default value is retained, including
// OTEL_SERVICE_NAME. It is ignored when TracerProvider is set.
ServiceName string
// TracerProvider attaches the Langfuse processor to a caller-owned provider. The client
// never replaces the global provider or shuts this provider down.
TracerProvider *sdktrace.TracerProvider
// MaxQueueSize bounds how many ended export-eligible spans the client
// buffers in memory while waiting for batch export. Zero selects the
// default of 2048; negative values are a validation error in [New].
MaxQueueSize int
// BlockOnQueueFull makes ending an exported observation, and recording a
// score, wait for buffer space instead of dropping when the
// corresponding queue is full. A sustained export outage can then stall
// goroutines that end observations or record scores, so it defaults to
// false: on a full queue new work is dropped with a diagnostic, matching
// OpenTelemetry defaults.
BlockOnQueueFull bool
// Disabled makes the complete client a safe no-op.
Disabled bool
// DisableContentCapture removes Input and Output supplied through
// ObservationAttributes. It does not remove content emitted by third-party
// OpenTelemetry instrumentation. Identifiers, metadata, model data, and
// usage are still recorded.
DisableContentCapture bool
// Mask applies only to Input, Output, and Metadata supplied through this
// Client. Each metadata map is passed as one complete value and must remain
// a map[string]any to be retained. It does not process identifiers, model
// fields, StatusMessage, [Observation.RecordError] text, or third-party
// spans and events.
// Mask may be called concurrently and therefore must be concurrency-safe.
// A panic is recovered and the affected value is omitted.
Mask func(value any) any
// contains filtered or unexported fields
}
Config configures a Langfuse client.
func ConfigFromEnv ¶
func ConfigFromEnv() Config
ConfigFromEnv returns configuration from the eight documented LANGFUSE_* variables. It intentionally does not read the deprecated LANGFUSE_HOST.
Example ¶
package main
import (
"context"
"log"
"time"
"github.com/fgn/go-langfuse"
)
func main() {
// ConfigFromEnv reads LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY,
// LANGFUSE_BASE_URL, LANGFUSE_TRACING_ENVIRONMENT, LANGFUSE_RELEASE,
// LANGFUSE_SAMPLE_RATE, LANGFUSE_TRACING_ENABLED, and
// LANGFUSE_CONTENT_CAPTURE_ENABLED.
lf, err := langfuse.New(context.Background(), langfuse.ConfigFromEnv())
if err != nil {
log.Fatal(err)
}
defer func() {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = lf.Shutdown(shutdownCtx)
}()
}
Output:
type Observation ¶
type Observation struct {
// contains filtered or unexported fields
}
Observation is a concurrency-safe handle around one OpenTelemetry span. Its zero value is a safe no-op.
func (*Observation) End ¶
func (o *Observation) End()
End ends the observation exactly once at the current time.
func (*Observation) EndAt ¶ added in v0.4.0
func (o *Observation) EndAt(at time.Time)
EndAt ends the observation exactly once at the provided time. It exists for instrumentation that records work after the fact: pair it with ObservationAttributes.StartTime and CompletionStartTime to reproduce the observed timeline. A zero time falls back to the current time with a diagnostic, and an end time before an explicitly supplied StartTime is replaced by that start time with a diagnostic. Only the first End or EndAt call takes effect; later calls are ignored.
func (*Observation) ID ¶
func (o *Observation) ID() string
ID returns the lowercase 16-character OpenTelemetry span ID, or an empty string for a no-op observation.
func (*Observation) RecordError ¶
func (o *Observation) RecordError(err error)
RecordError records an exception and marks the observation as failed. It does not end the observation. At most eight exception events are retained; later calls are omitted with one diagnostic. The error text is explicitly supplied content and is not processed by Config.Mask. Invalid UTF-8 or text over 64 KiB is replaced by the payload-free string "error".
func (*Observation) Sampled ¶ added in v0.4.0
func (o *Observation) Sampled() bool
Sampled reports whether this observation's trace was selected for export by sampling. It reports false on a no-op observation. It is a sampling decision, not a delivery guarantee: exporting still requires End, a live client, and export success. Use it to skip work whose only purpose is enriching an observation that will never be exported, together with TraceSampledAt when gating on a smaller correlated fraction.
func (*Observation) TraceID ¶
func (o *Observation) TraceID() string
TraceID returns the lowercase 32-character OpenTelemetry trace ID, or an empty string for a no-op observation.
func (*Observation) Update ¶
func (o *Observation) Update(values ObservationAttributes)
Update merges non-zero fields into an active observation. Structured model, usage, and cost maps replace their complete serialized attributes when set; metadata merges by top-level key. StartTime cannot be changed after start and is ignored with a diagnostic.
type ObservationAttributes ¶
type ObservationAttributes struct {
// Input and Output are explicit content. They are never inferred by the
// SDK, are subject to Config.DisableContentCapture, and pass through Mask.
Input any
Output any
// Metadata merges by top-level key across Update calls and passes through
// Mask. Empty maps are ignored and cannot clear earlier metadata. At most 32
// distinct keys are retained over an observation's lifetime; keys are
// limited to 200 bytes.
Metadata map[string]any
Level Level
// StatusMessage is explicit telemetry content, is limited to 16 KiB, and
// does not pass through Mask. Sanitize it before calling the SDK.
StatusMessage string
// Version overrides a propagated TraceAttributes.Version on this
// observation only.
Version string
// The remaining fields are honored only by generation and embedding
// observations, except Prompt, which Langfuse links only on generations.
Model string
ModelParameters map[string]any
Usage *Usage
CostDetails map[string]float64
Prompt *PromptRef
CompletionStartTime time.Time
// StartTime is honored only by StartObservation; Event and Update ignore
// it with a diagnostic.
StartTime time.Time
}
ObservationAttributes contains fields that can be set when an observation starts or in a later Update. Zero values are ignored and updates never clear an already recorded value. Each serialized structured value is limited to 1 MiB and the observation-level payload attributes are limited to 2 MiB in aggregate over the observation's current values. Separately bounded trace/client propagation and exception events sit outside that aggregate. Oversized fields are omitted with a payload-free OpenTelemetry diagnostic.
type ObservationType ¶
type ObservationType string
ObservationType identifies how Langfuse presents an observation.
const ( TypeSpan ObservationType = "span" TypeGeneration ObservationType = "generation" TypeEvent ObservationType = "event" TypeEmbedding ObservationType = "embedding" TypeAgent ObservationType = "agent" TypeTool ObservationType = "tool" TypeChain ObservationType = "chain" TypeRetriever ObservationType = "retriever" TypeEvaluator ObservationType = "evaluator" TypeGuardrail ObservationType = "guardrail" )
type Prompt ¶ added in v0.4.0
type Prompt struct {
Name string
Version int
Type PromptType
Text string
Messages []PromptMessage
Config json.RawMessage
Labels []string
Tags []string
CommitMessage string
// Source reports whether this value was fetched, served from fresh or
// stale cache, or produced from PromptQuery.Fallback.
Source PromptSource
}
Prompt is one fetched prompt version. GetPrompt returns an independent deep copy (the SDK's cached master is never exposed), so callers may retain or modify the value freely.
func (Prompt) Compile ¶ added in v0.4.0
Compile substitutes {{variable}} occurrences in the prompt content and returns the compiled copy; the receiver is unchanged. String values substitute verbatim; any other value is JSON-encoded, and a conversion that fails or panics leaves that occurrence unresolved; Compile never fails and never panics. For chat prompts, a variable whose value is []PromptMessage fills the placeholder of that name: an empty slice removes the placeholder, and a slice containing any invalid message leaves the placeholder unchanged (never a partial splice). Unresolved variables and unfilled placeholders stay verbatim, matching the Python SDK; non-string values use JSON rather than Python's str().
Example ¶
package main
import (
"fmt"
"github.com/fgn/go-langfuse"
)
func main() {
prompt := langfuse.Prompt{
Type: langfuse.PromptTypeText,
Text: "Summarize {{topic}} in one line.",
}
compiled := prompt.Compile(map[string]any{"topic": "Go context"})
fmt.Println(compiled.Text)
}
Output: Summarize Go context in one line.
func (Prompt) CompileStrict ¶ added in v0.4.0
CompileStrict compiles the same copy as Compile and also reports missing content variables, values that cannot be stringified, and unfilled chat placeholders. The returned prompt contains every successful substitution even when the error is non-nil.
func (Prompt) DecodeConfig ¶ added in v0.4.0
DecodeConfig decodes Config into v. An absent config is a no-op, allowing callers to set defaults on v before decoding prompt-owned overrides.
The prompt config is server-controlled, so a decode failure is reported through payload-free categories that name only the caller-owned target type: the underlying encoding/json error is never wrapped or surfaced, because its text can echo config values or offending bytes into an error callers routinely log.
func (Prompt) Ref ¶ added in v0.4.0
Ref returns the reference that links observations to this prompt version, for ObservationAttributes.Prompt. It returns nil, safely skipping linking, for a fallback prompt and for any value that cannot form a valid reference (empty Name or Version <= 0, such as a zero Prompt).
type PromptFallback ¶ added in v0.4.0
type PromptFallback struct {
// Type declares the prompt shape. Empty infers chat when Messages is
// non-nil (an empty non-nil slice is a deliberate empty chat prompt) and
// text otherwise. Explicit text requires Messages == nil; explicit chat
// requires Text == "".
Type PromptType
// Text is the text prompt body.
Text string
// Messages is the chat prompt body.
Messages []PromptMessage
// Config is surfaced through Prompt.Config; when non-empty it must be
// valid JSON.
Config json.RawMessage
}
PromptFallback is a locally supplied prompt body used when a fetch cannot resolve a compatible prompt.
type PromptMessage ¶ added in v0.4.0
type PromptMessage struct {
Role string
Content string
// PlaceholderName marks this message as a named placeholder slot; when
// set, Role, Content, and Extra must be empty.
PlaceholderName string
// Extra preserves additional message fields beyond role and content (for
// example tool_calls) verbatim, as one JSON object. Compile never
// substitutes inside Extra.
Extra json.RawMessage
}
PromptMessage is one chat prompt message. A regular message sets Role (required) and Content (optional; tool-call messages may have empty content); a placeholder message sets only PlaceholderName, a named slot filled at Compile time.
type PromptQuery ¶ added in v0.4.0
type PromptQuery struct {
// Version selects an exact prompt version. Zero means "use Label";
// negative values are rejected.
Version int
// Label selects the deployment label; empty means "production".
// Version and Label are mutually exclusive.
Label string
// Type requires the resolved prompt to have this shape. Empty accepts
// either text or chat. A mismatch is resolved through Fallback when set
// and otherwise returns ErrPromptTypeMismatch. Type filters per call: it
// is not part of the cache key and does not suppress the shared entry's
// background refresh, so a differently typed caller still keeps the entry
// fresh.
Type PromptType
// CacheTTL overrides the 60-second default freshness window for this
// call. Zero means the default; negative values are rejected. Freshness
// is judged against the age of the cached entry at call time, so callers
// with different TTLs share one entry (a deliberate divergence from the
// official SDKs, which stamp an expiry when the entry is inserted).
CacheTTL time.Duration
// DisableCache bypasses the cache entirely for this call (no read, no
// write, no shared in-flight fetch), forcing a fresh fetch.
DisableCache bool
// Fallback is returned when a fetch fails without a cached value or the
// resolved prompt does not match Type, so a local prompt can guarantee
// availability. A fallback result is never cached and Ref on it returns
// nil, so it is not linked to observations. Fallback never overrides the
// caller's own context cancellation on a blocking fetch path.
Fallback *PromptFallback
}
PromptQuery selects a prompt version and controls caching. The zero value requests the "production"-labeled version with the default 60-second TTL.
type PromptSource ¶ added in v0.4.0
type PromptSource string
PromptSource reports how GetPrompt resolved a prompt.
const ( PromptSourceServer PromptSource = "server" PromptSourceCache PromptSource = "cache" PromptSourceStale PromptSource = "stale" PromptSourceFallback PromptSource = "fallback" )
type PromptType ¶ added in v0.4.0
type PromptType string
PromptType discriminates text and chat prompts.
const ( PromptTypeText PromptType = "text" PromptTypeChat PromptType = "chat" )
type Score ¶
type Score struct {
// ID makes submissions idempotent: Langfuse upserts scores by ID.
// Optional; the SDK generates a random ID when empty so retried
// deliveries cannot create duplicates.
ID string
// Name identifies the score series, for example "user-feedback".
// Required; at most 200 characters.
Name string
// TraceID, SessionID, and ObservationID select the score target. At
// least one of TraceID or SessionID is required, and ObservationID
// additionally requires TraceID.
TraceID string
SessionID string
ObservationID string
// Exactly one of NumericValue or StringValue must be set. Boolean
// scores use NumericValue 0 or 1 with ScoreTypeBoolean.
NumericValue *float64
StringValue *string
// DataType is optional; when empty, Langfuse infers NUMERIC or
// CATEGORICAL from the value type.
DataType ScoreDataType
// ConfigID references a Langfuse score config by its identifier.
// Optional; at most 200 characters. Langfuse validates the score against
// the config server-side, so a violating score is rejected during
// asynchronous delivery and dropped with a diagnostic rather than
// returned as a RecordScore error.
ConfigID string
// Comment is explicit content supplied by the caller. It is not
// processed by Config.Mask; sanitize it before calling the SDK.
Comment string
// Metadata is serialized as one JSON value.
Metadata map[string]any
// Timestamp records when the scored interaction happened, for example
// when feedback is computed by a batch job hours after the trace. The
// zero value stamps the score with the time RecordScore accepted it. The
// UTC year must stay within the four-digit RFC 3339 range.
Timestamp time.Time
}
Score is one evaluation or feedback value attached to a trace, a session, or an observation. Scores are submitted through the Langfuse JSON ingestion API rather than the OpenTelemetry trace pipeline.
type ScoreDataType ¶
type ScoreDataType string
ScoreDataType identifies how Langfuse stores and aggregates a score value.
const ( ScoreTypeBoolean ScoreDataType = "BOOLEAN" ScoreTypeCategorical ScoreDataType = "CATEGORICAL" ScoreTypeCorrection ScoreDataType = "CORRECTION" ScoreTypeNumeric ScoreDataType = "NUMERIC" ScoreTypeText ScoreDataType = "TEXT" )
type TraceAttributes ¶
type TraceAttributes struct {
Name string
UserID string
SessionID string
// Tags merge in caller order, de-duplicate, and retain at most 64 values
// and 16 KiB of UTF-8 data over one trace context.
Tags []string
// Metadata merges by top-level key and retains at most 32 distinct keys in
// one trace context so required observation fields remain within default
// OpenTelemetry span limits. Keys are limited to 200 bytes.
Metadata map[string]any
Version string
}
TraceAttributes are request-scoped fields copied to an active SDK observation and to spans subsequently started from the returned context.
type Usage ¶
type Usage struct {
InputTokens int64
OutputTokens int64
CacheReadInputTokens int64
CacheCreationInputTokens int64
ReasoningOutputTokens int64
// Details contains additional provider-specific subsets. Keys prefixed
// input_ or output_ are subtracted from the corresponding base bucket.
// Such buckets must be mutually exclusive, must not overlap the typed
// cache/reasoning fields, and must be subsets of their inclusive total. The
// canonical input, output, total, cache, and reasoning keys are reserved.
// At most 64 provider-specific detail buckets are retained, with keys
// limited to 200 bytes.
Details map[string]int64
}
Usage records inclusive provider token counts. InputTokens includes cache tokens, and OutputTokens includes reasoning tokens. The SDK normalizes these values to Langfuse's exclusive usage_details representation while total remains the checked sum of the inclusive input and output totals.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
contrib
|
|
|
googlegenai
module
|
|
|
openai
module
|
|
|
examples
|
|
|
existingotel
command
|
|
|
prompts
command
|
|
|
quickstart
command
|
|
|
sampling
command
|
|
|
scores
command
|
|
|
shortlived
command
|
|
|
streaming
command
|
|
|
internal
|
|
|
attributes
Package attributes owns Langfuse's OpenTelemetry attribute contract.
|
Package attributes owns Langfuse's OpenTelemetry attribute contract. |
|
diagnostic
Package diagnostic reports payload-free SDK diagnostics through OpenTelemetry.
|
Package diagnostic reports payload-free SDK diagnostics through OpenTelemetry. |
|
otlpreceiver
Package otlpreceiver provides a local OTLP/HTTP protobuf receiver for tests.
|
Package otlpreceiver provides a local OTLP/HTTP protobuf receiver for tests. |
|
processor
Package processor contains the Langfuse OpenTelemetry span processor.
|
Package processor contains the Langfuse OpenTelemetry span processor. |