Class: CustomLogger

Inherits:
Object
  • Object
show all
Defined in:
app/my_lib/custom_logger.rb

Constant Summary collapse

LEVELS =
[:debug, :info, :warn, :error].freeze
CATEGORIES =

these categories are used to categorize/filter the logs for VendorHub LogViewer

{
  request: 'request',          # Incoming API call from vendor
  response: 'response',        # Our response to the vendor API
  webhook_in: 'webhook_in',    # Webhook received from vendor
  webhook_out: 'webhook_out',  # Webhook sent to vendor
  internal: 'internal',        # Internal service logs
}.freeze
CATEGORY_MESSAGES =
{
  request: 'Incoming vendor API request',
  response: 'Outgoing response to vendor',
  webhook_in: 'Incoming webhook from vendor',
  webhook_out: 'Outgoing webhook to vendor',
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(log_file) ⇒ CustomLogger

Returns a new instance of CustomLogger.

Examples:

CustomLogger.new('log/faraday.log')

Parameters:

  • log_file (String)

    The path to the log file.



23
24
25
26
# File 'app/my_lib/custom_logger.rb', line 23

def initialize(log_file)
  @logger = LogStashLogger.new(type: :file, path: log_file)
  @scope = {}
end

Instance Method Details

#flushObject



131
132
133
# File 'app/my_lib/custom_logger.rb', line 131

def flush
  @logger.flush
end

#log(level, *args) ⇒ Object



81
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
# File 'app/my_lib/custom_logger.rb', line 81

def log(level, *args)
  message, options = extract_message_and_options(args)
  data = @scope.dup # Make sure to preserve scope during logging
  data[:message] = message if message.is_a?(String)
  data[:exception] = format_exception(message) if message.is_a?(Exception)
  data[:timestamp] = Time.zone.now.iso8601
  data[:payload] = options || {}
  data[:business_context] = RequestStore.store[BUSINESS_CONTEXT] || {}
  data[:request_context] = RequestStore.store[REQUEST_CONTEXT] || {}

  begin
    # Log the data
    @logger.send(level, data.to_json)
  rescue JSON::GeneratorError
    body = 'Response body is too large to log or invalid Unicode issue'
    data[:payload] = {
      body: body,
    }
    data[:request_context] = {
      body: body,
    }
    data[:business_context] = {
      body: body,
    }
    begin
      @logger.send(level, data.to_json)
    rescue StandardError => e
      APMErrorHandler.report(e)
    end
  end
end

#scope(new_scope = {}) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/my_lib/custom_logger.rb', line 113

def scope(new_scope = {})
  old_scope = @scope
  @scope = old_scope.merge(new_scope)
  if block_given?
    begin
      yield
    ensure
      @scope = old_scope
    end
  else
    self
  end
end

#scoped(new_scope, &block) ⇒ Object



127
128
129
# File 'app/my_lib/custom_logger.rb', line 127

def scoped(new_scope, &block)
  scope(new_scope, &block)
end

#set_business_context(context) ⇒ Object

Business context is a context that is related to the business logic of the application. This is useful for tracking the flow of the business logic. So we can track the flow of the business logic in the log.

logger.set_business_context({ voucher_transaction_id: voucher_transaction.id })

Parameters:

  • context (Hash)

    The context to be logged.



48
49
50
51
52
53
54
55
# File 'app/my_lib/custom_logger.rb', line 48

def set_business_context(context)
  previous_custom_logger_business_context = RequestStore.store[BUSINESS_CONTEXT] || {}
  custom_logger_business_context = previous_custom_logger_business_context.merge(context || {})

  RequestStore.store[BUSINESS_CONTEXT] = custom_logger_business_context
rescue StandardError => e
  APMErrorHandler.report(e)
end

#set_context(context) ⇒ Object

deprecated use set_business_context and set_request_context instead



75
76
77
78
79
# File 'app/my_lib/custom_logger.rb', line 75

def set_context(context)
  APMErrorHandler.report('set_context is deprecated. Use set_business_context and set_request_context instead.', caller: caller)
  set_business_context(context[:business_context]) if context[:business_context]
  set_request_context(context[:request_context]) if context[:request_context]
end

#set_request_context(context) ⇒ Object

Request context is a context that is related to the request that is being processed. This is useful for tracking the flow of the request. So we can track the flow of the request in the log.

logger.set_request_context({ request_id: request_id })

Parameters:

  • context (Hash)

    The context to be logged.



64
65
66
67
68
69
70
71
# File 'app/my_lib/custom_logger.rb', line 64

def set_request_context(context)
  previous_custom_logger_request_context = RequestStore.store[REQUEST_CONTEXT] || {}
  custom_logger_request_context = previous_custom_logger_request_context.merge(context || {})

  RequestStore.store[REQUEST_CONTEXT] = custom_logger_request_context
rescue StandardError => e
  APMErrorHandler.report(e)
end