Class: Errsight::Railtie

Inherits:
Rails::Railtie
  • Object
show all
Defined in:
lib/errsight/railtie.rb

Constant Summary collapse

HOSTNAME =

Captured once at boot — Socket.gethostname does a DNS lookup on some platforms and is called on the hot exception-capture path.

begin
  Socket.gethostname
rescue StandardError
  nil
end.freeze

Class Method Summary collapse

Class Method Details

.build_tags(payload, request) ⇒ Object

Top-level tags the UI uses for filtering. Rails env info is free at capture time and makes “errors on this controller/action/host” filters work without any app-side setup.



118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/errsight/railtie.rb', line 118

def self.build_tags(payload, request)
  tags = {
    "controller"     => payload[:controller],
    "action"         => payload[:action],
    "request_method" => request&.request_method,
    "status"         => payload[:status]&.to_s,
    "ruby_version"   => RUBY_VERSION,
    "rails_version"  => Rails.version
  }
  tags["hostname"] = HOSTNAME if HOSTNAME
  tags.compact.reject { |_, v| v.to_s.strip.empty? }
end

.build_user_context(request) ⇒ Object

Extracts a top-level user context the API stores in user_context / user_identifier. Falls through to just the request IP when no user is signed in so anonymous errors still carry some identity.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/errsight/railtie.rb', line 82

def self.build_user_context(request)
  ctx = {}

  # Warden-backed auth (Devise, ActiveAdmin, etc.). Walks every authenticated
  # scope in the session rather than hard-coding :user.
  begin
    warden = request&.env&.fetch("warden", nil)
    if warden
      session = request.env["rack.session"] || {}
      scopes  = session.keys
                       .grep(/\Awarden\.user\.(.+)\.key\z/) { $1.to_sym }
                       .then { |s| s.any? ? s : [ :user ] }

      user = scopes.lazy.filter_map { |scope| warden.user(scope) rescue nil }.first

      if user
        ctx[:id]       = user.id.to_s       if user.respond_to?(:id)       && !user.id.to_s.strip.empty?
        ctx[:email]    = user.email.to_s    if user.respond_to?(:email)    && !user.email.to_s.strip.empty?
        ctx[:username] = user.username.to_s if user.respond_to?(:username) && !user.username.to_s.strip.empty?
      end
    end
  rescue StandardError
    # never let user-lookup failures suppress the event
  end

  if request.respond_to?(:remote_ip)
    ip = request.remote_ip.to_s
    ctx[:ip_address] = ip unless ip.empty?
  end

  ctx.empty? ? nil : ctx
end