e-volv
Contents

Ruby

e-volv-logs is the SDK for Ruby 2.6 or later. Standard library only - no runtime dependencies - with rack and faraday as soft, duck-typed integrations and nothing monkeypatched. It speaks the same wire contract as the Node.js, Python, Go and Java SDKs.

Install and initialise

text
gem install e-volv-logs
# or in a Gemfile:
gem "e-volv-logs"
ruby
require "evolve_logs"

EvolveLogs.init(
  key: ENV["EVOLVE_LOGS_KEY"], # project ingest key - a server key, from the environment
  url: "https://api.e-volv.io/api/public/v1/logs",
  service: "orders-api",
  environment: ENV["RACK_ENV"],
  release: ENV["GIT_SHA"]
)

EvolveLogs.info("order created", { "orderId" => "o_1", "total" => 42.5 })
EvolveLogs.error("payment failed", { "orderId" => "o_1" })

begin
  charge
rescue StandardError => err
  EvolveLogs.exception(err, { "orderId" => "o_1" }) # exception.type/message/stack
end

If key or url is empty, init returns a no-op client and warns once on stderr: the SDK never raises into your code. EvolveLogs::Client.new(...) builds a non-default client; the module-level helpers delegate to the client installed by EvolveLogs.init.

Traces and spans

Trace context lives in Thread.current (fiber-local): it flows into fibers under the current thread and never leaks across threads.

ruby
EvolveLogs.span("db.query", { "table" => "orders" }) do
  db.query("SELECT …")
end # an exception inside ends the span as failed and is re-raised

The span end is recorded as an event with span.name and durationMs, carrying the span’s trace and span ids. EvolveLogs.traceparent returns the W3C 00-<traceId>-<spanId>-01 header, or nil outside a trace.

Rack and Rails

ruby
# config.ru - one root span per request; an inbound traceparent is continued
use EvolveLogs::RackMiddleware
ruby
# config/application.rb - every Rails.logger line also ships to Observer;
# Rails.logger.error(err) carries exception.*
config.logger = EvolveLogs::Logger.new($stdout)

An app that raises ends the http.request span as failed and is re-raised, so the server crashes exactly as it would without the SDK.

Queue hops: ActiveJob and Sidekiq

ruby
# producer
MyJob.perform_later(args, traceparent: EvolveLogs.traceparent)

# consumer
EvolveLogs::ActiveJob.perform(
  EvolveLogs::ActiveJob.traceparent_in(arguments),
  self.class.name
) do
  # one trace with the producer
end

EvolveLogs::Sidekiq.perform(traceparent, worker, attrs) { … } is the Sidekiq shape; EvolveLogs::Carriers.wrap(header, span_name, attrs){ … } covers anything else. For raw headers, EvolveLogs.run_with_traceparent(header) { … } runs the block with the next hop of that trace: an absent or malformed header starts a fresh trace.

Outbound HTTP: Net::HTTP and Faraday

Monkeypatch-free: opt in per call site:

ruby
request = Net::HTTP::Post.new(uri)
EvolveLogs::HTTP.inject_traceparent(request) # never overwrites an existing header
http.request(request)
ruby
conn = Faraday.new(url: "https://internal") do |builder|
  builder.use EvolveLogs::FaradayMiddleware
  builder.adapter Faraday.default_adapter
end

Delivery

The shared numbers: flush at 200 events, every 2 seconds or at 512 KB, always gzipped. A 429 honours Retry-After, otherwise exponential backoff from 500 ms (doubling, capped at 10 s), up to three attempts; a 413 halves the batch and counts the excess half. Past twice the batch size the oldest events drop, visible on client.dropped. The SDK installs an at_exit hook and EvolveLogs.flush is safe to call repeatedly.

Already emit OpenTelemetry? The Ruby preset in packages/logs-otel-presets remains a valid route, point the OTel Ruby SDK at the ingest with one file. See OpenTelemetry presets.

Package reference: e-volv-logs on RubyGems. Back to SDK overview.

We use only essential cookies to keep you signed in and the app working. With your consent we may enable optional analytics to help us improve e-volv. See our Privacy Policy and Terms.