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_size | 100 | Entries per HTTP batch |
flush_interval | 5 | Seconds between automatic flushes |
max_buffer_size | 10_000 | Bounded buffer cap before drop policy applies |
max_retries | 3 | Retry attempts for retryable statuses |
retry_delay | 1 | Base backoff seconds (exponential, with jitter) |
circuit_breaker_threshold | 5 | Consecutive failures before the breaker opens |
circuit_breaker_reset | 30 | Seconds before the breaker half-opens |
flush_timeout | 10 | Seconds to wait for a flush to complete |
max_breadcrumbs | 100 | Breadcrumbs retained per scope |
sample_rate | 1.0 | Fraction of log entries sent |
traces_sample_rate | 1.0 | Fraction of spans sent |
attach_stacktrace | true | Attach stack frames to captured exceptions |
send_default_pii | false | Include potentially personal data (e.g. request bodies) |
debug | false | Log 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
at_exit hook, but for
short-lived scripts, workers, and rake tasks call Logtide.flush
(or Logtide.close) explicitly so buffered entries are delivered.
Logtide.with_scope
so tags, user, and breadcrumbs stay isolated. The Rails Railtie does this for web requests automatically.
Logtide.capture_exception(e) instead of
Logtide.error(e.message) to keep the cause chain and
stack frames for grouping and debugging.
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.