Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- `Client#list_observations`, `Client#query_metrics`, and `Client#list_scores` expose the current v2 observations and metrics APIs and the v3 scores API.
- Text and correction score types are available through the score creation and read APIs.
- `ScoreClient#create!`, `Client#create_score!`, and `Langfuse.create_score!` create scores through the synchronous Scores API, return the created score ID, and raise API errors. The existing `create` methods retain fire-and-forget ingestion batching.
- `Langfuse.configured?` checks locally whether the global client can be constructed without accessing the network.
- `Config#metrics_reporter` forwards OpenTelemetry batch span processor metrics to an application-owned reporter without allowing reporter failures to interrupt tracing.
- `Config#span_exporter` lets applications inject an OpenTelemetry span exporter into Langfuse's existing tracing pipeline.
- `TextPromptClient#variables` and `ChatPromptClient#variables` expose referenced Mustache variables in source order.
- `Config#tracing_enabled` and `LANGFUSE_TRACING_ENABLED` provide an application-wide tracing and scoring kill switch.

### Changed
- Trace export uses direct Langfuse v4 OTLP ingestion so current observation and metric reads can see new spans without the legacy ingestion delay.
- `LANGFUSE_TIMEOUT`, `LANGFUSE_FLUSH_AT`, `LANGFUSE_FLUSH_INTERVAL`, and `LANGFUSE_DEBUG` now configure their corresponding defaults.
- The asynchronous score queue is bounded. Score flushes split batches before a multi-score JSON payload exceeds 2.5 MB.
- Client construction now rejects invalid `batch_size` and `flush_interval` values before score batching can fail later.
- Configuration validation now requires `public_key` and `secret_key` to be non-empty Strings and `base_url` to be an absolute HTTP or HTTPS URL.
- Assigning `nil` to `Config#logger` now selects a null logger so SDK logger calls remain safe.
- Implicit observations warn once and use a no-op tracer when tracing configuration is invalid. Explicit `Langfuse.tracer_provider` access still raises `ConfigurationError`.

### Fixed
- Export-stage masking can transform third-party OpenTelemetry spans while preserving the original span for other exporters.
- SDK-owned queues and workers reset after Ruby `fork` so parent work is not duplicated in child processes.
- Pending spans and scores flush once during normal process exit.
- Score creation now uses the configured client environment when a score does not provide an environment override.
- Configuration validation now reports invalid numeric types, stale cache settings, and tracing callables as `ConfigurationError`.
- Tracing validates batching and sampling settings before it creates an OpenTelemetry span processor.
Expand Down
72 changes: 59 additions & 13 deletions docs/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Complete method reference for the Langfuse Ruby SDK.
- [Prompt Management](#prompt-management)
- [Trace ID Generation](#trace-id-generation)
- [Tracing & Observability](#tracing--observability)
- [Traces](#traces)
- [Data Access](#data-access)
- [Scoring](#scoring)
- [Datasets](#datasets)
- [Experiments](#experiments)
Expand Down Expand Up @@ -50,11 +50,13 @@ Block receives a `Langfuse::Config` object with these properties:
| `prompt_cache_observer` | Callable | No | `nil` | Prompt cache event hook |
| `batch_size` | Integer | No | `50` | Score + trace export batch size |
| `flush_interval` | Integer | No | `10` | Score + trace export interval (s) |
| `score_queue_capacity` | Integer | No | `100000` | Maximum pending asynchronous scores |
| `sample_rate` | Float | No | `1.0` | Trace + trace-linked score sampling rate (`0.0..1.0`) |
| `logger` | Logger | No | Auto-detected | Logger instance |
| `tracing_async` | Boolean | No | `true` | ⚠️ Experimental (OTel batch scheduling) |
| `tracing_async` | Boolean | No | `true` | Experimental OTel batch scheduling |
| `tracing_enabled` | Boolean | No | `true` | Langfuse tracing and scoring kill switch |
| `job_queue` | Symbol | No | `:default` | Reserved/no-op for future job integration |
| `environment` | String | No | `nil` (or `ENV["LANGFUSE_TRACING_ENVIRONMENT"]`) | Default trace environment |
| `environment` | String | No | `nil` (or `ENV["LANGFUSE_TRACING_ENVIRONMENT"]`) | Default trace, observation, and score environment |
| `release` | String | No | `nil` (or `ENV["LANGFUSE_RELEASE"]` / common CI commit SHA env) | Default release identifier |
| `should_export_span` | `#call` | No | `nil` | Span export filter callback |
| `mask` | `#call` | No | `nil` | Mask callable for input/output/metadata (receives `data:` keyword) |
Expand Down Expand Up @@ -126,6 +128,23 @@ This method does not access the network. A `true` result does not prove that cre

Tracing does not require this guard. `Langfuse.observe` warns once and uses a no-op tracer when tracing configuration is invalid, so application code can use the same observation wrapper in every environment.

### `Config#valid?`

Check whether a configuration object can construct a client:

```ruby
config = Langfuse::Config.new do |candidate|
candidate.public_key = "pk-lf-..."
candidate.secret_key = "sk-lf-..."
end

config.valid? # => true or false
```

The check is local and does not raise an error.
It does not validate credentials, network access, or backend ingestion.
Use `Langfuse.configured?` for the global configuration.

### `Langfuse.tracer_provider`

Return Langfuse's internal tracer provider so you can explicitly install it as the global OpenTelemetry provider.
Expand Down Expand Up @@ -249,7 +268,7 @@ get_prompt(name, version: nil, label: nil, fallback: nil, type: nil, cache_ttl:

**Raises:**

- `NotFoundError` if prompt doesn't exist (unless `fallback` provided)
- `NotFoundError` if the prompt does not exist and no `fallback` is present
- `UnauthorizedError` if credentials invalid
- `ApiError` on network/server errors

Expand Down Expand Up @@ -498,10 +517,11 @@ Returned by `get_prompt` for text prompts.
| `commit_message` | String, nil | Commit message for the prompt version |
| `resolution_graph` | Hash, nil | Dependency resolution graph for composed prompts when returned by Langfuse |
| `is_fallback` | Boolean | Whether the client uses caller-provided fallback content |
| `variables` | Array<String> | Referenced Mustache variables in source order |

**Methods:**

#### `compile`
#### `TextPromptClient#compile`

```ruby
compile(**variables) # => String
Expand All @@ -516,6 +536,16 @@ prompt = client.get_prompt("greeting")
message = prompt.compile(name: "Alice", time: "morning")
```

#### `TextPromptClient#variables`

```ruby
variables # => Array<String>
```

Returns unique Mustache variable and section names in source order.
Dotted paths do not change.
Invalid Mustache syntax raises `Mustache::Parser::SyntaxError`.

### `ChatPromptClient`

Returned by `get_prompt` for chat prompts.
Expand All @@ -524,7 +554,7 @@ Returned by `get_prompt` for chat prompts.

**Methods:**

#### `compile`
#### `ChatPromptClient#compile`

```ruby
compile(**variables) # => Array<Hash>
Expand Down Expand Up @@ -556,6 +586,15 @@ messages = prompt.compile(
# ]
```

#### `ChatPromptClient#variables`

```ruby
variables # => Array<String>
```

Returns unique Mustache variables from message content in message order.
The result does not include Langfuse message placeholders.

## Trace ID Generation

### `Langfuse.create_trace_id`
Expand Down Expand Up @@ -838,7 +877,10 @@ obs.update(
)
```

## Traces
## Data Access

Use [DATA_ACCESS.md](DATA_ACCESS.md) to select a read API.
The guide also explains cursor pagination and SDK and CLI verification.

### `Client#list_traces`

Expand Down Expand Up @@ -913,7 +955,7 @@ get_trace(id) # => Hash

**Raises:**

- `NotFoundError` if the trace doesn't exist
- `NotFoundError` if the trace does not exist
- `UnauthorizedError` if authentication fails
- `ApiError` for other API errors

Expand Down Expand Up @@ -1159,10 +1201,12 @@ flush_scores
**Example:**

```ruby
# Before shutdown
# Before an immediate verification read
Langfuse.client.flush_scores
```

Normal process exit flushes pending scores automatically.

### Module-Level Scoring

Convenience methods delegating to `Langfuse.client`:
Expand Down Expand Up @@ -1283,7 +1327,7 @@ get_dataset(name) # => DatasetClient

**Returns:** `DatasetClient`

**Raises:** `NotFoundError` if the dataset doesn't exist
**Raises:** `NotFoundError` if the dataset does not exist

### `Client#list_datasets`

Expand Down Expand Up @@ -1351,7 +1395,7 @@ Fetch a dataset item by ID.
get_dataset_item(id) # => DatasetItemClient
```

**Raises:** `NotFoundError` if the item doesn't exist
**Raises:** `NotFoundError` if the item does not exist

### `Client#list_dataset_items`

Expand Down Expand Up @@ -1679,7 +1723,7 @@ Extends `ApiError`. Resource not found (404).

**Raised when:**

- Prompt doesn't exist
- Prompt does not exist
- Invalid version/label

### `Langfuse::CacheWarmingError`
Expand Down Expand Up @@ -1769,10 +1813,12 @@ Langfuse.shutdown(timeout: 30)
**Example:**

```ruby
# Before process exit
# At an earlier application-owned shutdown boundary
Langfuse.shutdown
```

The SDK invokes shutdown automatically during normal process exit.

### `Langfuse.force_flush`

Force flush all pending data.
Expand Down
Loading
Loading