LogTide

Official Ruby SDK for LogTide with automatic batching, retry with backoff, a circuit breaker, Hub/Scope context isolation, distributed tracing, and Rack middleware plus a Rails Railtie. It implements the LogTide SDK spec v1.0 and uses the standard library only — no runtime dependencies.

Installation

Add the gem to your Gemfile:

# Gemfile
gem "logtide"
bundle install

Requires Ruby 3.1 or later and a LogTide instance with a DSN.

Quick Start

Initialise with a DSN (recommended)

require "logtide"

Logtide.init(
  dsn: "https://[email protected]",
  service: "checkout",
  environment: "production"
)

Logtide.info("order placed", { order_id: 42 })

begin
  charge_card!
rescue => e
  Logtide.capture_exception(e)
end

Logtide.flush

Explicit endpoint options

Instead of a DSN you can pass the endpoint and key separately:

Logtide.init(
  api_url: "https://logs.example.com",
  api_key: "lp_your_key",
  service: "checkout"
)

Configuration

All options can be passed to Logtide.init. Defaults follow the LogTide SDK spec exactly (durations are in seconds):

Option Default Description
environment"production"Deployment environment tag
batch_size100Entries per HTTP batch
flush_interval5Seconds between automatic flushes
max_buffer_size10_000Bounded buffer cap before drop policy applies
max_retries3Retry attempts for retryable statuses
retry_delay1Base backoff seconds (exponential, with jitter)
circuit_breaker_threshold5Consecutive failures before the breaker opens
circuit_breaker_reset30Seconds before the breaker half-opens
flush_timeout10Seconds to wait for a flush to complete
max_breadcrumbs100Breadcrumbs retained per scope
sample_rate1.0Fraction of log entries sent
traces_sample_rate1.0Fraction of spans sent
attach_stacktracetrueAttach stack frames to captured exceptions
send_default_piifalseInclude potentially personal data (e.g. request bodies)
debugfalseLog SDK internals to stderr

Logging Methods

Five leveled methods take a message and an optional metadata hash. capture_exception records a structured exception with its cause chain.

Logtide.debug("cache miss", { key: "user:42" })
Logtide.info("request handled", { status: 200, ms: 12 })
Logtide.warn("rate limit approaching")
Logtide.error("db query failed", { query: "SELECT ..." })
Logtide.critical("out of memory")

begin
  risky!
rescue => e
  Logtide.capture_exception(e, { order_id: 42 })
end

Scope & Breadcrumbs

The Hub/Scope model attaches tags, user info, and breadcrumbs to every entry within a logical unit of work — without threading extra parameters through your code.

Global scope

Logtide.configure_scope do |scope|
  scope.set_user(id: "u_123", email: "[email protected]")
  scope.set_tag("region", "eu")
end

Logtide.add_breadcrumb(
  Logtide::Breadcrumb.new(type: "query", message: "SELECT * FROM carts")
)

Per-request isolation

with_scope pushes a temporary scope that is popped automatically when the block returns.

Logtide.with_scope do |scope|
  scope.set_tag("step", "payment")
  Logtide.error("payment failed") # carries step: payment
end

Error Capture

capture_exception serialises the exception, its cause chain, and (when attach_stacktrace is enabled) its stack frames, then attaches the current scope's tags, user, and breadcrumbs.

begin
  charge_card!
rescue StandardError => e
  Logtide.capture_exception(e, { user_id: current_user.id })
  raise
end

Tracing

Spans

Logs emitted inside a span automatically carry its trace_id and span_id for log/trace correlation. Spans are exported via OTLP.

Logtide.start_span("checkout", kind: :server) do |span|
  span.set_attribute("cart.size", 3)
  Logtide.info("processing") # carries the span's trace_id / span_id
end

Distributed propagation

The Rack middleware reads inbound W3C traceparent headers automatically. To propagate the active trace to a downstream service, attach the outbound headers:

headers = Logtide.trace_propagation_headers
# => { "traceparent" => "00-..." }

Net::HTTP.post(uri, body, headers)

Rails & Rack

Rails

The Railtie installs the Rack middleware automatically — it isolates scope per request, sets HTTP tags, parses traceparent, and adds request/response breadcrumbs. Just initialise the SDK in an initializer:

# config/initializers/logtide.rb
Logtide.init(
  dsn: ENV["LOGTIDE_DSN"],
  service: "my-app",
  release: ENV["GIT_SHA"]
)

Plain Rack

# config.ru
require "logtide"

Logtide.init(dsn: ENV["LOGTIDE_DSN"], service: "rack-app")

use Logtide::Rack::Middleware

run ->(_env) { [200, { "content-type" => "text/plain" }, ["ok"]] }

Logger Bridge

Logtide::LoggerBridge is a drop-in replacement for the stdlib Logger. Calls are delivered as LogTide entries with the current scope context; fatal maps to a critical entry.

logger = Logtide::LoggerBridge.new

logger.info("AuthService") { "user signed in" }
logger.warn("disk almost full")
logger.fatal("out of memory") # delivered as a critical entry

Best Practices

1. Flush before exit
The SDK installs a best-effort at_exit hook, but for short-lived scripts, workers, and rake tasks call Logtide.flush (or Logtide.close) explicitly so buffered entries are delivered.
2. Use with_scope per unit of work
Wrap requests and background jobs in Logtide.with_scope so tags, user, and breadcrumbs stay isolated. The Rails Railtie does this for web requests automatically.
3. Capture exceptions, don't stringify them
Use Logtide.capture_exception(e) instead of Logtide.error(e.message) to keep the cause chain and stack frames for grouping and debugging.
4. Watch the self-metrics
Logtide.get_metrics exposes logs_sent, logs_dropped, errors, retries, and circuit_breaker_trips — a rising logs_dropped means you've hit max_buffer_size.
Esc

Type to search across all documentation pages