What is Sorbet?

Sorbet Logo

Sorbet is a static type checker for Ruby. Static type-checking has many benefits:

  • Catches errors at development time, not at runtime
  • Ensures consistent log structure
  • Provides better IDE documentation and autocompletion

LogStruct is built with Sorbet and provides full type-checking support. We use it to catch errors during development and test and keep the code bug-free.

Adding Sorbet to Your Application

To fully utilize LogStruct's type safety features, you can add Sorbet to your application:

# In your Gemfile
gem "sorbet", group: :development
gem "sorbet-runtime"

Then run:

bundle install
bundle exec srb init

See the Sorbet docs for more details.

Using LogStruct with Sorbet

LogStruct uses predefined log classes with strict typing. This ensures that your logs have a consistent format and that required fields are present and have the right type.

# Create a typed request log entry
request_log = LogStruct::Log::Request.new(
  http_method: "GET",
  path: "/users",
  status: 200,
  duration: 45.2,
  source: LogStruct::Source::Rails
)

# Log the typed struct at info level
LogStruct.info(request_log)

# Create a typed error log entry
error_log = LogStruct::Log::Error.new(
  source: LogStruct::Source::App,
  err_class: StandardError,
  message: "An error occurred during processing"
)

# Log the error at error level
LogStruct.error(error_log)

Error Handling for Type Errors

LogStruct configures Sorbet error handlers to log and report type-checking errors. If you already use Sorbet and you want to keep using your own error handlers, set enable_sorbet_error_handlers to false. This will prevent LogStruct from overriding your handlers.

LogStruct.configure do |config|
  config.integrations.enable_sorbet_error_handlers = false
end

Custom Log Classes

You can create your own typed log classes by inheriting from Sorbet's T::Struct class.

# Define a custom log structure
module TestApp
  class Source < T::Enum
    enums do
      Payments = new
      App = new
    end
  end

  class Event < T::Enum
    enums do
      Processed = new
      Failed = new
    end
  end

  module Log
    class PaymentProcessed < T::Struct
      prop :source, Source
      prop :event, Event
      prop :timestamp, Time, factory: -> { Time.now }

      prop :payment_id, String
      prop :amount, Float
      prop :currency, String
      prop :status, String
      prop :user_id, T.nilable(Integer)
    end
  end
end
It is not currently possible to extend LogStruct's internal logging classes or enums with additional values. We use exhaustiveness checks throughout our code, and we also use them to ensure that our documentation is accurate and up-to-date. You will need to create your own T::Struct subclasses and use Rails.logger.

Built-In Log Classes

Log classes are Typed Structs under the LogStruct:: module.

  • Log::ActionMailer - For email delivery events
  • Log::ActiveJob - For background job execution
  • Log::ActiveStorage - For file storage operations
  • Log::CarrierWave - For CarrierWave upload events
  • Log::Error - For exception details with stack traces
  • Log::GoodJob - For GoodJob background job lifecycle events
  • Log::Plain - For general purpose logging
  • Log::Request - For HTTP request details
  • Log::Security - For security-related events
  • Log::Shrine - For Shrine file upload events
  • Log::Sidekiq - For Sidekiq job processing
  • Log::SQL - For ActiveRecord SQL query events and performance metrics

Built-In Enums

Common values are defined as Typed Enums under the LogStruct:: module.

Level

Log severity levels for different types of log messages

  • Level::Debug - Detailed debugging information
  • Level::Info - General informational messages
  • Level::Warn - Warning conditions that should be noted
  • Level::Error - Error conditions that affect operation
  • Level::Fatal - Severe error conditions that cause the application to terminate
  • Level::Unknown - Used when a log level cannot be determined

Source

Sources of log messages to identify which part of the system generated them

  • Source::TypeChecking - Type checking errors (Sorbet)
  • Source::LogStruct - Errors from LogStruct itself
  • Source::Security - Security-related events and checks
  • Source::Rails - Core Rails framework components
  • Source::Job - Background job processing
  • Source::Storage - ActiveStorage logs and errors
  • Source::Mailer - Email delivery and processing
  • Source::App - Application-specific code
  • Source::Shrine - Shrine file upload logs and errors
  • Source::CarrierWave - CarrierWave file upload logs and errors
  • Source::Sidekiq - Sidekiq background job logs and errors

Event

Event types for different kinds of operations and activities

  • Event::Log - Standard log message
  • Event::Request - HTTP request
  • Event::Enqueue - Job added to queue
  • Event::Schedule - Job scheduled for future processing
  • Event::Start - Job processing started
  • Event::Finish - Job processing completed
  • Event::Upload - File upload operation
  • Event::Download - File download operation
  • Event::Delete - File deletion operation
  • Event::Metadata - File metadata operation
  • Event::Exist - File existence check operation
  • Event::Stream - File streaming operation
  • Event::Url - File URL generation operation
  • Event::Delivery - Email preparation for delivery
  • Event::Delivered - Email successfully delivered
  • Event::IPSpoof - IP spoofing attack attempt
  • Event::CSRFViolation - Cross-Site Request Forgery violation
  • Event::BlockedHost - Access attempt from blocked host
  • Event::Database - Database query event and metrics
  • Event::Error - Error occurrence
  • Event::Unknown - Unclassified event type

ErrorHandlingMode

Error handling strategies for different types of errors

  • ErrorHandlingMode::Ignore - Completely ignore errors
  • ErrorHandlingMode::Log - Log errors but don't report them
  • ErrorHandlingMode::Report - Log and report errors to error service
  • ErrorHandlingMode::LogProduction - Log in production, raise in development
  • ErrorHandlingMode::ReportProduction - Report in production without crashing, raise during dev/test
  • ErrorHandlingMode::Raise - Always raise the error (reported by tracking service)