Module: LogStruct::Integrations::Lograge

Extended by:
IntegrationInterface, T::Sig
Defined in:
lib/log_struct/integrations/lograge.rb

Overview

Lograge integration for structured request logging

Class Method Summary collapse

Methods included from IntegrationInterface

setup

Class Method Details

.apply_custom_options(event, options) ⇒ void

This method returns an undefined value.

Apply custom options from the application's configuration

Parameters:

  • event (ActiveSupport::Notifications::Event)
  • options (Hash{Symbol => T.untyped})


109
110
111
112
113
114
115
116
# File 'lib/log_struct/integrations/lograge.rb', line 109

def apply_custom_options(event, options)
  custom_options_proc = LogStruct.config.integrations.lograge_custom_options
  return unless custom_options_proc&.respond_to?(:call)

  # Call the proc with the event and options
  # The proc can modify the options hash directly
  custom_options_proc.call(event, options)
end

.configure_lograge(logstruct_config) ⇒ void

This method returns an undefined value.

Parameters:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/log_struct/integrations/lograge.rb', line 34

def configure_lograge(logstruct_config)
  ::Rails.application.configure do
    config.lograge.enabled = true
    # Use a raw formatter that just returns the log struct.
    # The struct is converted to JSON by our Formatter (after filtering, etc.)
    config.lograge.formatter = T.let(
      lambda do |data|
        # Coerce common fields to expected types
        status = ((s = data[:status]) && s.respond_to?(:to_i)) ? s.to_i : s
        duration_ms = ((d = data[:duration]) && d.respond_to?(:to_f)) ? d.to_f : d
        view = ((v = data[:view]) && v.respond_to?(:to_f)) ? v.to_f : v
        db = ((b = data[:db]) && b.respond_to?(:to_f)) ? b.to_f : b

        params = data[:params]
        params = params.deep_symbolize_keys if params&.respond_to?(:deep_symbolize_keys)

        Log::Request.new(
          http_method: data[:method]&.to_s,
          path: data[:path]&.to_s,
          format: data[:format]&.to_sym,
          controller: data[:controller]&.to_s,
          action: data[:action]&.to_s,
          status: status,
          duration_ms: duration_ms,
          view: view,
          database: db,
          params: params,
          timestamp: Time.now
        )
      end,
      T.proc.params(hash: T::Hash[Symbol, T.untyped]).returns(Log::Request)
    )

    # Add custom options to lograge
    config.lograge.custom_options = lambda do |event|
      Integrations::Lograge.lograge_default_options(event)
    end
  end
end

.lograge_default_options(event) ⇒ Hash{Symbol => T.untyped}

Parameters:

  • event (ActiveSupport::Notifications::Event)

Returns:

  • (Hash{Symbol => T.untyped})


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/log_struct/integrations/lograge.rb', line 75

def lograge_default_options(event)
  # Extract essential fields from the payload
  options = event.payload.slice(
    :request_id,
    :host,
    :source_ip
  ).compact

  if event.payload[:params].present?
    options[:params] = event.payload[:params].except("controller", "action")
  end

  # Process headers if available
  process_headers(event, options)

  # Apply custom options from application if provided
  apply_custom_options(event, options)

  options
end

.process_headers(event, options) ⇒ void

This method returns an undefined value.

Process headers from the event payload

Parameters:

  • event (ActiveSupport::Notifications::Event)
  • options (Hash{Symbol => T.untyped})


98
99
100
101
102
103
104
105
# File 'lib/log_struct/integrations/lograge.rb', line 98

def process_headers(event, options)
  headers = event.payload[:headers]
  return if headers.blank?

  options[:user_agent] = headers["HTTP_USER_AGENT"]
  options[:content_type] = headers["CONTENT_TYPE"]
  options[:accept] = headers["HTTP_ACCEPT"]
end

.setup(logstruct_config) ⇒ Boolean?

Set up lograge for structured request logging

Parameters:

Returns:

  • (Boolean, nil)


21
22
23
24
25
26
27
28
29
# File 'lib/log_struct/integrations/lograge.rb', line 21

def setup(logstruct_config)
  return nil unless defined?(::Lograge)
  return nil unless logstruct_config.enabled
  return nil unless logstruct_config.integrations.enable_lograge

  configure_lograge(logstruct_config)

  true
end