e-volv
Contents

Ruby

e-volv-logs is the e-volv Launch SDK for Ruby 2.6 and later, standard library only, no runtime dependencies. It is a server SDK: with a server key (evk_…) it receives the environment’s full ruleset and evaluates flags locally, so a flag check never performs I/O, never blocks and never raises. Delivery is a stream of change notifications (SSE) with a polling fallback, run on its own e-volv-flags thread so a held-open stream never stalls log flushing; a last-known cache on disk and exposure tracking ride the same key and transport as your logs. The behaviour is pinned by the Launch SDK contract, and both conformance suites - the kernel fixture and the delivery driver - run in CI.

Install

shell
gem install e-volv-logs
# or in a Gemfile:
gem "e-volv-logs"

Native API

ruby
require "evolve_logs"

EvolveLogs.init(
  key: ENV["EVOLVE_KEY"], # a server key (evk_…) from the environment
  url: "https://api.e-volv.io/api/public/v1/logs",
  service: "orders-api",
  flags: { mode: "stream" } # optional; see the options table
)

EvolveLogs.flags.ready(timeout: 5) # optional: true once the first ruleset arrived

if EvolveLogs.flags.bool("checkout.new", false, { "targetingKey" => user.id, "plan" => user.plan })
  render_new_checkout
end

# The full detail when you need the variant and the reason:
d = EvolveLogs.flags.detail("checkout.banner", "default", { "targetingKey" => user.id })
# d.value, d.variant ("on" | "off" | "control" | …), d.reason
# ("RULE:0" | "ROLLOUT" | "TARGET_MATCH" | "DEFAULT" | "FLAG_NOT_FOUND" | …)

Evaluation methods: bool, string, number, json and detail - all synchronous, all safe. detail returns an Evaluation struct with value, variant and reason readers. A flag whose served value is not of the requested type returns your default with reason TYPE_MISMATCH; a flag absent from the ruleset returns your default with FLAG_NOT_FOUND. The handle is EvolveLogs.flags on the default client, or client.flags on an EvolveLogs::Client.new instance.

Options

Flags are configured under the flags keyword of the existing EvolveLogs.init - a Hash (string or symbol keys) or an EvolveLogs::Flags::Options:

OptionDefaultMeaning
enabledtrueStart the flags client. False gives a defaults-only stub with no threads.
mode'stream'stream | poll | offline. Offline never contacts the control plane (bootstrap snapshot or defaults only).
poll_interval_seconds30 (min 15)Poll period once streaming has fallen back.
urlderivedBase URL ending in /api/public/v1/flags; defaults to the origin of the Observer url option, else the e-volv cloud.
cacheplatform tmp dirWhere the last-known ruleset is kept (one file per key, sha1-hashed name, atomic write). False disables.
bootstrapnoneA bundled ruleset served before the first fetch completes.
stale_after_seconds300Log a one-line staleness warning after this long without a confirmation from the control plane.
exposures.enabledtrueRecord an exposure on each evaluation of a flag present in the ruleset.
exposures.sample_rate1.0Probability an evaluation is recorded; sent as sampleRate.
exposures.dedupe_window_seconds60Suppress repeats of the same (flag, variant, kind, subject) within the window; suppressed counts ride the next exposure.
exposures.send_attributesfalseSend context attributes with exposures (private attributes are always removed).
private_attributes[]Attribute names never sent anywhere.

Install check and lifecycle

ruby
# Install check: is this key bound, and to which environment?
ping = EvolveLogs.flags.verify
# { "environment" => "production", "keyKind" => "server", "flags" => 42, "etag" => "3f2a…" }
# nil when the control plane did not answer.

flags.ready(timeout: 5) waits for the first ruleset (only if you choose to), flags.last_updated_at reports the last confirmed update in epoch seconds, and flags.on_change { |keys| } notifies with the keys whose values changed, returning an unsubscribe proc. flags.flush_exposures drains the exposure buffer; it also runs from EvolveLogs.flush.

ruby
# On shutdown (e.g. before a deploy, or in a Rake task's ensure block):
client = EvolveLogs.init(key: ENV["EVOLVE_KEY"], url: "https://api.e-volv.io/api/public/v1/logs")
# …
client.close # stops the e-volv-flags threads, then flushes pending exposures

Troubleshooting by status code

Evaluation never breaks because of the control plane: it degrades. Conditions are logged once on stderr, not once per evaluation. What each response means for the SDK (contract §2.6):

ResponseSDK behaviour
401Key invalid or revoked. The SDK keeps serving held values or defaults, logs once on stderr, and retries bootstrap every 5 minutes.
403: lacks the scope flags:readFlags are disabled for this key with one warning; telemetry is unaffected. No retry until re-init.
404Launch is not enabled for the workspace, or the key is not bound to an environment. Same handling as 401.
429Honours Retry-After (seconds, minimum 1 s); a stream 429 falls back to polling. The delivery rate limit is 3,000 requests/min per key.
5xx, timeout, network errorRetries with full-jitter exponential backoff (random(0, min(60, 2^attempt)) seconds), while serving the last held values.

Guarantees

  • A flag check is local and synchronous, bounded by CPU, not the network; ready(timeout:) is the only call that waits, and only when you ask it to.
  • An unreachable or slow control plane never changes an answer mid-flag: the last held ruleset (or a valid cache, or your defaults) keeps serving while the SDK backs off and reconnects.
  • Cold start reads the on-disk cache instantly and swaps to a fresh ruleset without a flicker for unchanged flags; corrupt, oversized or other-environment caches are ignored and overwritten.
  • Delivery threads survive fork - they relaunch on the first evaluation in a forked child (Puma, Unicorn, Resque, Sidekiq), and a held-open stream never stalls log flushing.
  • Exposures are sampled, de-duplicated, capped (a 10,000-row buffer drops oldest first) and retried with the same policy as your logs - telemetry you can trust as much as the flag answers themselves.
  • Evaluation is byte-for-byte identical to every other e-volv SDK: the Ruby kernel is a port held to packages/flags-kernel/fixture.json.

Back to e-volv Launch, the HTTP API page documents the wire format the SDK speaks, and the SDKs index lists every platform.

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.