Skip to main content

Flux - Custom Events & Metrics

Flux lets you track custom events and metrics in your Rails application, with support for dashboards and anomaly detection.

Configuration

config/initializers/brainzlab.rb
BrainzLab.configure do |config|
  config.secret_key = ENV['BRAINZLAB_SECRET_KEY']

  # Enable Flux
  config.flux_enabled = true

  # Batch settings for performance
  config.flux_batch_size = 100       # Send after 100 items
  config.flux_flush_interval = 10    # Or every 10 seconds

  # Default tags added to all events/metrics
  config.flux_default_tags = {
    environment: Rails.env,
    version: MyApp::VERSION
  }
end

Events

Track discrete occurrences in your application.

Basic Event

BrainzLab::Flux.track("user.signup")

Event with Properties

BrainzLab::Flux.track("order.placed", {
  properties: {
    product_id: "prod_123",
    product_name: "Widget Pro",
    quantity: 3
  }
})

Event with Tags

Tags are indexed for fast filtering:
BrainzLab::Flux.track("api.request", {
  tags: {
    endpoint: "/users",
    method: "POST",
    status: "success"
  }
})

Event with Value

Values enable aggregations:
BrainzLab::Flux.track("purchase.completed", {
  user_id: user.id,
  value: order.total,
  properties: { order_id: order.id }
})

Full Event

BrainzLab::Flux.track("subscription.upgraded", {
  timestamp: Time.current,
  user_id: user.id,
  value: plan.price,
  properties: {
    from_plan: old_plan.name,
    to_plan: new_plan.name
  },
  tags: {
    plan_type: new_plan.type,
    source: "upsell_modal"
  }
})

Metrics

Track numeric values over time with four metric types.

Gauge

Current value that can go up or down:
# Current users online
BrainzLab::Flux.gauge("users.online", 234)

# Queue depth
BrainzLab::Flux.gauge("jobs.queue_depth", Sidekiq::Queue.new.size)

# With tags
BrainzLab::Flux.gauge("cache.size", cache.size, tags: {
  cache_name: "sessions"
})

Counter

Incrementing values:
# Increment by 1
BrainzLab::Flux.increment("api.requests")

# Increment by N
BrainzLab::Flux.increment("emails.sent", 5)

# With tags
BrainzLab::Flux.increment("api.requests", tags: {
  endpoint: "/users",
  status: 200
})

Distribution

Statistical values (avg, p95, etc.):
# Response time
BrainzLab::Flux.distribution("response_time", 145.2)

# Order value
BrainzLab::Flux.distribution("order.value", order.total)

# With tags
BrainzLab::Flux.distribution("query.duration_ms", query_time, tags: {
  query_type: "search"
})

Set

Unique counts:
# Daily active users
BrainzLab::Flux.set("daily_active_users", user.id)

# Unique products viewed
BrainzLab::Flux.set("products.viewed", product.id)

Timing Operations

Automatically measure execution time:
# Basic timing
BrainzLab::Flux.measure("pdf.generate") do
  generate_pdf(document)
end

# With tags
BrainzLab::Flux.measure("api.external_call", tags: { service: "stripe" }) do
  Stripe::Charge.create(params)
end

# Returns the block's result
result = BrainzLab::Flux.measure("heavy.computation") do
  compute_something_expensive
end

Batching

The SDK automatically batches for performance. Manual control:
# Explicit batch block
BrainzLab::Flux.batch do
  users.each do |user|
    BrainzLab::Flux.track("user.migrated", user_id: user.id)
  end
end

# Force immediate send (use sparingly)
BrainzLab::Flux.track("critical.event", flush: true)

# Manual flush
BrainzLab::Flux.flush!

Rails Integration

Controller Events

class OrdersController < ApplicationController
  after_action :track_order, only: :create

  def create
    @order = Order.create!(order_params)
    redirect_to @order
  end

  private

  def track_order
    BrainzLab::Flux.track("order.placed", {
      user_id: current_user.id,
      value: @order.total,
      properties: {
        order_id: @order.id,
        items: @order.items.count
      },
      tags: {
        payment_method: @order.payment_method
      }
    })

    BrainzLab::Flux.increment("orders.count")
    BrainzLab::Flux.set("customers.active", current_user.id)
  end
end

Model Callbacks

class User < ApplicationRecord
  after_create :track_signup

  private

  def track_signup
    BrainzLab::Flux.track("user.signup", {
      user_id: id,
      properties: {
        email_domain: email.split("@").last,
        signup_source: signup_source
      },
      tags: { plan: plan.name }
    })
  end
end

Background Jobs

class DailyMetricsJob < ApplicationJob
  def perform
    # Gauge metrics
    BrainzLab::Flux.gauge("users.total", User.count)
    BrainzLab::Flux.gauge("users.active_today", User.active_today.count)
    BrainzLab::Flux.gauge("orders.pending", Order.pending.count)

    # Distribution for batch stats
    User.find_each do |user|
      BrainzLab::Flux.distribution("user.orders_count", user.orders.count)
    end
  end
end

Periodic Gauges

# config/initializers/flux_gauges.rb
if defined?(Sidekiq) && Sidekiq.server?
  Thread.new do
    loop do
      sleep 30

      BrainzLab::Flux.gauge("sidekiq.queued", Sidekiq::Stats.new.enqueued)
      BrainzLab::Flux.gauge("sidekiq.workers", Sidekiq::Workers.new.size)
      BrainzLab::Flux.gauge("redis.memory_mb",
        Redis.current.info["used_memory"].to_i / 1_000_000)
    end
  end
end

Use Cases

Funnel Tracking

class SignupController < ApplicationController
  def landing
    BrainzLab::Flux.track("funnel.landing_page", user_id: visitor_id)
  end

  def form
    BrainzLab::Flux.track("funnel.signup_started", user_id: visitor_id)
  end

  def create
    @user = User.create!(user_params)
    BrainzLab::Flux.track("funnel.signup_completed", user_id: @user.id)
  end
end

Feature Usage

class FeaturesController < ApplicationController
  def export_pdf
    BrainzLab::Flux.track("feature.used", {
      user_id: current_user.id,
      properties: { feature: "export_pdf" },
      tags: { plan: current_user.plan.name }
    })

    generate_pdf
  end
end

Business Events

class Invoice < ApplicationRecord
  after_create :track_revenue

  def track_revenue
    BrainzLab::Flux.track("revenue.recognized", {
      value: amount,
      properties: {
        invoice_id: id,
        customer_id: customer_id
      },
      tags: {
        currency: currency,
        region: customer.region,
        product: product.name
      }
    })
  end
end

Testing

Disable Flux in tests:
# config/environments/test.rb
BrainzLab.configure do |config|
  config.flux_enabled = false
end
Or use test mode:
# spec/rails_helper.rb
BrainzLab.configure do |config|
  config.test_mode = true
end

# In tests
expect(BrainzLab::Flux).to have_tracked("user.signup")
expect(BrainzLab::Flux).to have_gauged("users.online", 234)

Environment Variables

VariableDescription
FLUX_URLCustom Flux endpoint (self-hosting)
FLUX_BATCH_SIZEOverride batch size
FLUX_FLUSH_INTERVALOverride flush interval
BRAINZLAB_DEBUGEnable debug logging