Skip to content

FEATURE: add Config#valid? and Langfuse.configured? - #98

Open
Alan-Marx wants to merge 7 commits into
simplepractice:mainfrom
Alan-Marx:add-config-valid-predicate
Open

FEATURE: add Config#valid? and Langfuse.configured?#98
Alan-Marx wants to merge 7 commits into
simplepractice:mainfrom
Alan-Marx:add-config-valid-predicate

Conversation

@Alan-Marx

@Alan-Marx Alan-Marx commented Jul 23, 2026

Copy link
Copy Markdown

TL;DR

Introduces non-raising Langfuse.configured? and Langfuse::Config#valid? methods.

Why

Langfuse might not be configured in all application environments. Application code therefore needs a way to check whether an operation should be wrapped in a Langfuse observation or not. The only way to do that at the moment is to manually check ENV vars or call Langfuse.configuration.validate! and rescue the call.

This PR adds some new convenience methods to make these guards easier to write:

  • Adds Config#valid? — a non-raising predicate that returns true/false instead of raising ConfigurationError
  • Adds Langfuse.configured? — a module-level convenience method delegating to configuration.valid?
  • Replaces the internal tracing_config_ready? helper (which only checked three fields) with direct calls to configuration.valid?, so tracing readiness now requires a fully valid config. This is technically a stricter guard, however given that most Langfuse operations will trigger a full configuration validation via Langfuse::Client I think this is justified.
  • Updates the error message in tracer_provider to reflect the broader validation

Checklist

  • Tests added for new behavior
  • Docs updated (if user-facing)

Note

Medium Risk
Changes when tracing starts vs when the API client validates, and alters failure modes for misconfigured export settings; behavior is covered by new specs but affects observability in production.

Overview
Adds Config#valid? and Langfuse.configured? so apps can guard Langfuse usage without rescuing ConfigurationError. These reflect client config validity (credentials, cache, timeouts, etc.), not whether tracing can start.

Validation is split and tightened: validate! now uses shared type-aware helpers so bad types (e.g. string timeouts, non-string keys, bogus cache_stale_ttl) raise ConfigurationError instead of ArgumentError/NoMethodError. validate_tracing! is a separate, narrower check (credentials, should_export_span, batch_size, flush_interval) used when OTel setup runs; invalid client-only settings no longer block tracing, and invalid batch_size/flush_interval no longer fail full client validation.

Tracing behavior: lazy setup calls validate_tracing! via OtelSetup; failures on observe/start_observation emit a one-time warning naming the bad setting and use a no-op tracer (safe with nil logger). Langfuse.tracer_provider still raises, with messages prefixed by “Langfuse tracing is disabled: …”. Docs and changelog updated to describe the distinction between configured vs tracing-ready.

Reviewed by Cursor Bugbot for commit 15911b7. Bugbot is set up for automated code reviews on this repo. Configure here.

Alan Marx and others added 3 commits July 23, 2026 14:58
Adds a non-raising Config#valid? predicate that delegates to validate!,
and a top-level Langfuse.configured? convenience method. Replaces the
internal tracing_config_ready? helper with direct calls to
configuration.valid? now that Config owns that logic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update CHANGELOG and CONFIGURATION docs for Config#valid? and
Langfuse.configured?.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…OR_HANDLING

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread lib/langfuse.rb
Alan Marx and others added 2 commits July 23, 2026 15:22
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restore tracing-specific gating via Config#validate_tracing! so invalid
cache/client settings can never disable tracing (parity with the Python
and JS SDKs). Type-safe validators stop ArgumentError/NoMethodError
leaking through Config#valid?, and batch_size/flush_interval are now
validated before SpanProcessor consumes them. Reverts the in-PR version
bump to keep the release flow with the release tooling.

AAI-338
@kxzk

kxzk commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Pushed a revision (d887e03) implementing AAI-338 — keeps the new Config#valid? / Langfuse.configured? predicates but decouples tracing readiness from full config validity:

  • Tracing gating restored: internal readiness now uses a new Config#validate_tracing! (credentials, base_url, should_export_span, batch_size, flush_interval) instead of configuration.valid?, so an invalid cache setting (e.g. bad cache_backend) can no longer silently disable tracing. This matches the Python/JS SDKs, where tracing and client config are orthogonal.
  • valid? can't leak non-ConfigurationError exceptions: validate! now uses type-safe helpers, so string/symbol numerics and non-string credentials raise ConfigurationError instead of ArgumentError/NoMethodError.
  • SpanProcessor crash surface closed: batch_size/flush_interval are validated before tracing setup (previously batch_size = nil crashed with NoMethodError inside SpanProcessor). Tracing-disabled warnings and Langfuse.tracer_provider errors now name the specific offending setting.
  • Release flow restored: version reverted to 0.10.1 and changelog entries moved back under [Unreleased] — version bumps happen via the release tooling, not feature PRs.

Verified: 1369 specs green (96.91% coverage), rubocop clean, and a live end-to-end check — with valid credentials plus cache_backend = :bogus, an observation was created, flushed, and read back from Langfuse (configured? correctly returns false while tracing stays fully functional).

kxzk added 2 commits July 27, 2026 11:00
Deduplicate the public_key/secret_key/base_url trio shared by validate!
and validate_tracing!, drop the redundant pre-validation in
setup_tracing_if_ready (OtelSetup.setup already validates), and note the
configured?-vs-tracing-readiness contract in YARD.
OtelSetup's setup/reuse logging now uses safe navigation, matching the
guard in warn_tracing_disabled_once, so a nil logger can never crash
tracing initialization or its degradation warning.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 15911b7. Configure here.

return if config.should_export_span.nil? || config.should_export_span.respond_to?(:call)

raise ConfigurationError, "should_export_span must respond to #call"
config.logger&.info("Langfuse tracing initialized with OpenTelemetry (#{mode} mode)")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete nil logger hardening

Medium Severity

Safe-navigation on config.logger lets OtelSetup.setup succeed when logger is nil, but SpanProcessor still calls @logger.error without nil-safety when should_export_span raises. That turns the intended span-drop path into a NoMethodError during finish. This is easy to hit because Config#default_logger can return a nil Rails.logger.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 15911b7. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants