Solid Errors Documentation

repository·main·Indexed 19 days ago

https://github.com/fractaledmind/solid_errors

A DB-based, app-internal exception tracker for Rails applications. Solid Errors leverages the Rails error reporting API to store uncaught exceptions in a dedicated database and provides a built-in UI for management. It includes features for custom context recording, email notifications, dashboard security, and data sanitization via SolidErrors::Sanitizer to prevent report bloating.

Tokens
6.1K
Snippets
23
Records
25
Agent score
67%

What's inside Solid Errors

  1. Backfill fingerprints for existing errors

    main

    Immediately after running the UpgradeSolidErrors migration, you must run a script to generate SHA256 fingerprints for all existing records in the solid_errors table. This ensures that existing errors are compatible with the new indexing logic before new errors (which will have pre-generated fingerprints) are recorded.

    SolidErrors::Error.where(fingerprint: nil).find_each do |error|
      error_attributes = error.attributes.slice('exception_class', 'message', 'severity', 'source')
      fingerprint = Digest::SHA256.hexdigest(error_attributes.values.join)
      error.update_attribute(:fingerprint, fingerprint)
    end
  2. Upgrade to Solid Errors 0.4.0

    main

    Upgrading to version 0.4.0 requires a multi-step process to transition from a composite unique index to a single fingerprint column. This change allows exception_class, message, severity, and source to be limitless text columns.

    Warning: This is a breaking change that requires a schema migration and a data backfill script to be run in a specific order to avoid errors with new incoming records.

    # This is a multi-step upgrade process involving:
    # 1. Schema migration to add fingerprint and change column types
    # 2. Data backfill to generate fingerprints for existing errors
    # 3. Schema migration to enforce non-nullability on fingerprint
  3. Configure the Solid Errors database

    main

    You can use a separate database for Solid Errors to avoid impacting your primary application database. Use config.solid_errors.connects_to to pass a custom database configuration hash.

    Using a separate DB for Solid Errors:

    config.solid_errors.connects_to = { database: { writing: :solid_errors, reading: :solid_errors } }

    Using a separate primary/replica pair:

    config.solid_errors.connects_to = { database: { writing: :solid_errors_primary, reading: :solid_errors_replica } }

    Single Database Configuration: If you want to use your primary database instead of a separate one:

    1. Copy the contents of db/errors_schema.rb into a standard migration and delete db/errors_schema.rb.
    2. Remove config.solid_errors.connects_to from your configuration.
    3. Run your migrations.
    # Example: Separate DB
    config.solid_errors.connects_to = { database: { writing: :solid_errors, reading: :solid_errors } }
  4. Mount the Solid Errors engine in routes.rb

    main

    To access the Solid Errors dashboard, you must mount the engine in your config/routes.rb file. It is highly recommended to wrap the mounting in an authentication block to secure the dashboard in production.

    authenticate :user, -> (user) { user.admin? } do
      mount SolidErrors::Engine, at: "/solid_errors"
    end
  5. Migrate schema for Solid Errors 0.4.0

    main

    To prepare the database for version 0.4.0, generate a migration for your specific error database and update it to change column types to limitless text and add the fingerprint column with a unique index.

    rails generate migration UpgradeSolidErrors --database {name_of_errors_database}
    class UpgradeSolidErrors < ActiveRecord::Migration[7.1]
      def up
        change_column :solid_errors, :exception_class, :text, null: false, limit: nil
        change_column :solid_errors, :message, :text, null: false, limit: nil
        change_column :solid_errors, :severity, :text, null: false, limit: nil
        change_column :solid_errors, :source, :text, null: true, limit: nil
        add_column :solid_errors, :fingerprint, :string, limit: 64
        add_index :solid_errors, :fingerprint, unique: true
        remove_index :solid_errors, [:exception_class, :message, :severity, :source], unique: true
      end
    
      def down
        change_column :solid_errors, :exception_class, :string, null: false, limit: 200
        change_column :solid_errors, :message, :string, null: false, limit: nil
        change_column :solid_errors, :severity, :string, null: false, limit: 25
        change_column :solid_errors, :source, :string, null: true, limit: nil
        remove_index :solid_errors, [:fingerprint], unique: true
        remove_column :solid_errors, :fingerprint, :string, limit: 64
        add_index :solid_errors, [:exception_class, :message, :severity, :source], unique: true
      end
    end

    Then run the migration:

    rails db:migrate:{name_of_errors_database}
  6. Enable Solid Errors in non-production environments

    main

    The rails generate solid_errors:install command automatically adds config.solid_errors.connects_to = { database: { writing: :errors } } to config/environments/production.rb.

    If you want to use Solid Errors in other environments (such as staging or development), you must manually add this configuration line to the respective environment file (e.g., config/environments/staging.rb). Ensure the symbol used (e.g., :errors) matches the database key defined in config/database.yml.

    config.solid_errors.connects_to = { database: { writing: :errors } }
  7. Overwrite Solid Errors views

    main

    You can customize the appearance of the dashboard by creating your own views or partials in your application's app/views directory. The paths follow the structure of the gem's internal views. For example, to overwrite the main application layout, create: app/views/layouts/solid_errors/application.html.erb.

    View Directory Structure for Overwrites:

    • layouts/solid_errors/
    • solid_errors/error_mailer/
    • solid_errors/errors/
    • solid_errors/occurrences/
  8. Enforce non-nullable fingerprint column

    main

    Once all existing errors have been backfilled with fingerprints, run a final migration to mark the fingerprint column as NOT NULL.

    rails generate migration SolidErrorFingerprintNonNullable --database {name_of_errors_database}
    class SolidErrorFingerprintNonNullable < ActiveRecord::Migration[7.1]
      def change
        change_column_null :solid_errors, :fingerprint, false
      end
    end
  9. Install Solid Errors

    main

    To install Solid Errors, add the gem to your Gemfile using Bundler and then run the provided installer to set up the necessary database schema files.

    1. Add the gem:
      bundle add solid_errors
    2. Run the installer:
      rails generate solid_errors:install

    This creates the db/errors_schema.rb file.

    $ bundle add solid_errors
    $ rails generate solid_errors:install
  10. Secure the Solid Errors dashboard

    main

    Solid Errors does not restrict access by default. You can secure the dashboard using one of these methods:

    1. Basic HTTP Authentication via Environment Variables: Set SOLIDERRORS_USERNAME and SOLIDERRORS_PASSWORD in your environment.

    2. Basic HTTP Authentication via Initializer:

    config.solid_errors.username = Rails.application.credentials.solid_errors.username
    config.solid_errors.password = Rails.application.credentials.solid_errors.password

    3. Devise/Custom Authentication via Routes: If using Devise, wrap the engine mount in an authenticate block in config/routes.rb:

    authenticate :user, -> (user) { user.admin? } do
      mount SolidErrors::Engine, at: "/solid_errors"
    end

    4. Custom Base Controller: To use a specific controller class for the dashboard (e.g., for custom filters or logic):

    config.solid_errors.base_controller_class = "YourAdminController"
    # Example: Devise integration
    authenticate :user, -> (user) { user.admin? } do
      mount SolidErrors::Engine, at: "/solid_errors"
    end
  11. Add custom context to recorded errors

    main

    By default, all exceptions are recorded automatically. To include additional metadata (like request URLs, parameters, or session data) in the error details page, add a before_action to your application controller that sets the context using Rails.error.set_context.

    before_action { Rails.error.set_context(request_url: request.original_url, params: params, session: session.inspect) }
  12. Enable the dashboard in API-only Rails applications

    main

    If your application was generated with rails new --api, the dashboard UI will not work because the necessary middleware is missing. Add these to your config/application.rb to enable the dashboard:

    # /config/application.rb
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore
    config.middleware.use ActionDispatch::Flash