quonfig

Ruby SDK for Quonfig — Feature Flags, Live Config, and Dynamic Log Levels.

Note: This SDK is pre-1.0 and the API is not yet stable.

Installation

Add the gem to your Gemfile:

gem 'quonfig'

Or install directly:

gem install quonfig

Quickstart

require 'quonfig'

client = Quonfig::Client.new(sdk_key: ENV['QUONFIG_BACKEND_SDK_KEY'])

# Feature flags
if client.enabled?('new-dashboard')
  # show new dashboard
end

# Typed config values
limit   = client.get_int('rate-limit')
name    = client.get_string('app.display-name')
regions = client.get_string_list('allowed-regions')

# Context-aware evaluation — pass a context hash as the last argument
value = client.get_string('homepage-hero', user: { key: 'user-123', country: 'US' })

Context

Contexts are hashes grouped by scope (user, team, device, etc.). You can attach a context in three ways:

1. Per-call context

client.get_bool('beta-feature', user: { key: 'user-123', plan: 'pro' })

2. in_context block

Everything evaluated inside the block sees the supplied context. The block's return value is returned from in_context.

result = client.in_context(user: { key: 'user-123', plan: 'pro' }) do |bound|
  {
    hero:   bound.get_string('homepage-hero'),
    limit:  bound.get_int('rate-limit'),
    beta?:  bound.enabled?('beta-feature')
  }
end

3. with_context — BoundClient for repeated lookups

with_context returns an immutable BoundClient that carries the context on every call. Useful when you want to pass a context-bound handle down the stack.

bound = client.with_context(user: { key: 'user-123', plan: 'pro' })

bound.get_string('homepage-hero')
bound.enabled?('beta-feature')
bound.get_int('rate-limit')

Datadir / offline mode

For tests, CI, or air-gapped environments, point the client at a local workspace directory instead of the Quonfig API. In datadir mode the SDK loads JSON config files from disk and performs no network I/O.

client = Quonfig::Client.new(
  datadir:     '/path/to/workspace',
  environment: 'production'
)

client.get_bool('feature-x')

You can also set QUONFIG_DIR in the environment and omit the datadir: option; when QUONFIG_DIR is set the SDK switches to datadir mode automatically. environment is required in datadir mode — it can be provided via the option or via QUONFIG_ENVIRONMENT.

export QUONFIG_DIR=/path/to/workspace
export QUONFIG_ENVIRONMENT=production
client = Quonfig::Client.new  # reads QUONFIG_DIR + QUONFIG_ENVIRONMENT

Environment variables

Variable Purpose
QUONFIG_BACKEND_SDK_KEY SDK key used to authenticate against the Quonfig API. Used when sdk_key: is omitted.
QUONFIG_DIR Path to a workspace directory. When set, the SDK runs in datadir/offline mode.
QUONFIG_ENVIRONMENT Environment name (production, staging, development) evaluated in datadir mode.
QUONFIG_TELEMETRY_URL Overrides the telemetry endpoint. Defaults to https://telemetry.quonfig.com.

Constructor options

Quonfig::Client.new(
  sdk_key:         '...',                          # required unless QUONFIG_BACKEND_SDK_KEY is set
  api_urls:        ['https://primary.quonfig.com'],
  telemetry_url:   'https://telemetry.quonfig.com',
  enable_sse:      true,
  enable_polling:  false,
  poll_interval:   60,
  init_timeout:    10,
  on_no_default:   :error,
  global_context:  {},
  datadir:         '/path/to/workspace',
  environment:     'production'
)
Option Type Default Description
sdk_key String ENV['QUONFIG_BACKEND_SDK_KEY'] SDK key for API authentication.
api_urls Array<String> ['https://primary.quonfig.com'] Ordered list of API base URLs to try. SSE stream URLs are derived by prepending stream. to each hostname.
telemetry_url String https://telemetry.quonfig.com (or ENV['QUONFIG_TELEMETRY_URL']) Base URL for the telemetry service.
enable_sse Boolean true Receive real-time updates over Server-Sent Events.
enable_polling Boolean false Poll the API on an interval as a fallback.
poll_interval Integer (seconds) 60 Polling interval when enable_polling is true.
init_timeout Integer (seconds) 10 Maximum time to wait for the initial config load.
on_no_default Symbol :error Behavior when a key has no value and no default: :error, :warn, or :ignore.
global_context Hash {} Context applied to every evaluation.
datadir String ENV['QUONFIG_DIR'] Path to a local workspace. When set, the SDK runs offline from disk.
environment String ENV['QUONFIG_ENVIRONMENT'] Environment to evaluate in datadir mode. Required when datadir is set.

Typed getters

Each typed getter takes a config key and an optional context hash. If the key is missing or the stored value does not match the requested type, the getter returns nil.

Method Returns
get_string(key, contexts = nil) String or nil
get_int(key, contexts = nil) Integer or nil
get_float(key, contexts = nil) Float or nil
get_bool(key, contexts = nil) true, false, or nil
get_string_list(key, contexts = nil) Array<String> or nil
get_duration(key, contexts = nil) Float (seconds) or nil
get_json(key, contexts = nil) Hash, Array, or nil
enabled?(feature_name, contexts = nil) true or false

Example:

client.get_string('app.display-name')
client.get_int('rate-limit', user: { key: 'user-123' })
client.get_float('pricing.multiplier')
client.get_bool('flags.new-checkout')
client.get_string_list('allowed-regions')
client.get_duration('request-timeout')
client.get_json('homepage.layout')
client.enabled?('beta-feature', user: { key: 'user-123' })

Dynamic log levels (SemanticLogger)

Quonfig can drive per-class log levels at runtime. Set config keys like log-levels.my_app.foo.bar to one of trace, debug, info, warn, error, fatal and wire the filter into SemanticLogger:

require 'quonfig'
require 'semantic_logger'

client = Quonfig::Client.new(sdk_key: ENV['QUONFIG_BACKEND_SDK_KEY'])
SemanticLogger.add_appender(io: $stdout, filter: client.semantic_logger_filter)

Lookup is exact-match only: logger name MyApp::Foo::Bar normalizes to log-levels.my_app.foo.bar. If no key is set the log is allowed through and SemanticLogger's static level decides. There is no hierarchy walk — a value on log-levels.my_app does not affect log-levels.my_app.foo.bar.

Pass key_prefix: to use a prefix other than log-levels.:

client.semantic_logger_filter(key_prefix: 'debug.')

Documentation

Full documentation, including SPEC, SDK reference, and operational guides, is available at https://quonfig.com/docs.

License

MIT