This guide provides step-by-step instructions on how to send logs from a Ruby on Rails application to Axiom using the Faraday library. By following this guide, you configure your Rails app to send logs to Axiom, allowing you to monitor and analyze your application logs effectively.

Prerequisites

Set up the Ruby on Rails application

  1. Create a new Rails app using the rails new myapp command.

  2. Navigate to the app directory: cd myapp

Setting up the Gemfile

Open the Gemfile in your Rails app, and then add the following gems:

gem 'faraday'
gem 'dotenv-rails', groups: [:development, :test]

Install the dependencies by running bundle install.

Create and configure the Axiom logger

  1. Create a new file named axiom_logger.rb in the app/services directory of your Rails app.

  2. Add the following code to axiom_logger.rb:

# app/services/axiom_logger.rb
require 'faraday'
require 'json'

class AxiomLogger
  def self.send_log(log_data)
    dataset_name = "DATASET_NAME"
    axiom_ingest_api_url = "https://api.axiom.co/v1/datasets/#{dataset_name}/ingest"
    ingest_token = "API_TOKEN"

    conn = Faraday.new(url: axiom_ingest_api_url) do |faraday|
      faraday.request :url_encoded
      faraday.adapter Faraday.default_adapter
    end

    wrapped_log_data = [log_data]

    response = conn.post do |req|
      req.headers['Content-Type'] = 'application/json'
      req.headers['Authorization'] = "Bearer #{ingest_token}"
      req.body = wrapped_log_data.to_json
    end

    puts "AxiomLogger Response status: #{response.status}, body: #{response.body}"

    if response.status != 200
      Rails.logger.error "Failed to send log to Axiom: #{response.body}"
    end
  end
end

In the code above, make the following changes:

  • Replace API_TOKEN with your Axiom API key.
  • Replace DATASET_NAME with the name of the Axiom dataset where you want to send data.

Test with the Axiom logger

  1. Create a new file named axiom_logger_test.rb in the config/initializers directory.

  2. Add the following code to axiom_logger_test.rb:

# config/initializers/axiom_logger_test.rb
Rails.application.config.after_initialize do
  puts "Sending test logs to Axiom using Ruby on Rails Faraday..."

  # Info logs
  AxiomLogger.send_log({ message: "Application started successfully", level: "info", service: "initializer" })
  AxiomLogger.send_log({ message: "User authentication successful", level: "info", service: "auth" })
  AxiomLogger.send_log({ message: "Data fetched from external API", level: "info", service: "external_api" })
  AxiomLogger.send_log({ message: "Email notification sent", level: "info", service: "email" })

  # Warn logs
  AxiomLogger.send_log({ message: "API request took longer than expected", level: "warn", service: "external_api", duration: 1500 })
  AxiomLogger.send_log({ message: "User authentication token expiring soon", level: "warn", service: "auth", user_id: 123 })
  AxiomLogger.send_log({ message: "Low disk space warning", level: "warn", service: "system", disk_usage: "85%" })
  AxiomLogger.send_log({ message: "Non-critical configuration issue detected", level: "warn", service: "config" })

  # Error logs
  AxiomLogger.send_log({ message: "Database connection error", level: "error", service: "database", error: "Timeout" })
  AxiomLogger.send_log({ message: "Failed to process payment", level: "error", service: "payment", user_id: 456, error: "Invalid card" })
  AxiomLogger.send_log({ message: "Unhandled exception occurred", level: "error", service: "application", exception: "NoMethodError" })
  AxiomLogger.send_log({ message: "Third-party API returned an error", level: "error", service: "integration", status_code: 500 })

  # Debug logs
  AxiomLogger.send_log({ message: "Request parameters", level: "debug", service: "api", params: { page: 1, limit: 20 } })
  AxiomLogger.send_log({ message: "Response headers", level: "debug", service: "api", headers: { "Content-Type" => "application/json" } })
  AxiomLogger.send_log({ message: "User object details", level: "debug", service: "user", user: { id: 789, name: "Axiom Observability", email: "support@axiom.co" } })
  AxiomLogger.send_log({ message: "Cache hit for key", level: "debug", service: "cache", key: "popular_products" })
end

Each log entry includes a message, level, service, and additional relevant data.

  • Info logs:

    • Application started successfully
    • User authentication successful
    • Data fetched from external API
    • Email notification sent
  • Warn logs:

    • API request took longer than expected (including duration)
    • User authentication token expiring soon (including user ID)
    • Low disk space warning (including disk usage percentage)
    • Non-critical configuration issue detected
  • Error logs:

    • Database connection error (including error message)
    • Failed to process payment (including user ID and error message)
    • Unhandled exception occurred (including exception type)
    • Third-party API returned an error (including status code)
  • Debug logs:

    • Request parameters (including parameter values)
    • Response headers (including header key-value pairs)
    • User object details (including user attributes)
    • Cache hit for key (including cache key)

Adjust the log messages, services, and additional data according to your application’s specific requirements and context.

Create the log.rake tasks

  1. Create a new directory named tasks in the lib directory of your Rails app.
  2. Create a new file named log.rake in the lib/tasks directory.
  3. Add the following code to log.rake:
# lib/tasks/log.rake
namespace :log do
  desc "Send a test log to Axiom"
  task send_test_log: :environment do
    log_data = { message: "Hello, Axiom from Rake!", level: "info", service: "rake_task" }
    AxiomLogger.send_log(log_data)
    puts "Test log sent to Axiom."
  end
end

This code defines a Rake task that sends a test log to Axiom when invoked.

View logs in Axiom

  1. Start your Rails server by running rails server.

  2. Go to http://localhost:3000 to trigger the test log from the initializer.

  3. Run the Rake task to send another test log by executing rails log:send_test_log in your terminal.

  4. In Axiom, go to the Stream tab, and then select the dataset where you send the logs.

  5. You see the test logs appear allowing you to view and analyze your event data coming from your Ruby on Rails application.

Conclusion

You have successfully set up your Ruby on Rails application to send logs to Axiom using the Faraday library. With this configuration, you can centralize your application logs and use Axiom’s powerful features like APL for log querying, monitoring, and observing various log levels and types effectively.