Class: SemanticLoggerEcsAddon::Formatters::Base

Inherits:
SemanticLogger::Formatters::Base
  • Object
show all
Defined in:
lib/semantic_logger_ecs_addon/formatters/base.rb

Direct Known Subclasses

Raw

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(time_key: :time, **args) ⇒ Base

Parameters

time_format: [String|Symbol|nil]
  See Time#strftime for the format of this string.
  :iso_8601 Outputs an ISO8601 Formatted timestamp.
  :ms       Output in miliseconds since epoch.
  nil:      Returns Empty string for time ( no time is output ).
  Default: '%Y-%m-%d %H:%M:%S.%<precision>N'
log_host: [Boolean]
  Whether or not to include hostname in logs
  Default: true
precision: [Integer]
  How many fractional digits to log times with.
  Default: PRECISION (6, except on older JRuby, where 3)


24
25
26
27
28
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 24

def initialize time_key: :time, **args
  @time_key = time_key
  @log_application = true
  super(**args)
end

Instance Attribute Details

#formatted_payloadObject

Fields are added by populating this hash.



9
10
11
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 9

def formatted_payload
  @formatted_payload
end

#hashObject

Fields are added by populating this hash.



9
10
11
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 9

def hash
  @hash
end

#log_labelsObject

Fields are added by populating this hash.



9
10
11
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 9

def log_labels
  @log_labels
end

#time_keyObject

Fields are added by populating this hash.



9
10
11
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 9

def time_key
  @time_key
end

Instance Method Details

#apm_agent_present_and_running?Boolean

ElasticAPM

Returns:

  • (Boolean)


205
206
207
208
209
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 205

def apm_agent_present_and_running?
  return false unless defined?(::ElasticAPM)

  ::ElasticAPM.running?
end

#applicationObject

Application name



36
37
38
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 36

def application
  log_labels[:application] = logger.application if logger && logger.application
end

#calculated_log_levelObject



198
199
200
201
202
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 198

def calculated_log_level
  return log.level if log.level_index > 2

  (formatted_payload.dig(:response, :status) || 0) >= 500 ? "error" : log.level
end

#each_exception(exception) ⇒ Object

Call the block for exception and any nested exception



99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 99

def each_exception exception
  # With thanks to https://github.com/bugsnag/bugsnag-ruby/blob/6348306e44323eee347896843d16c690cd7c4362/lib/bugsnag/notification.rb#L81
  depth      = 0
  exceptions = []
  e = exception
  while !e.nil? && !exceptions.include?(e) && exceptions.length < 5
    exceptions << e
    yield e, depth

    depth += 1
    e = inner_exception e
  end
end

#environmentObject

Environment



41
42
43
44
45
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 41

def environment
  if log_environment && logger && logger.environment
    log_labels[:environment] = logger.environment
  end
end

#error_log?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 121

def error_log?
  !hash[:"error.type"].nil?
end

#exceptionObject

Exception



78
79
80
81
82
83
84
85
86
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 78

def exception
  return log.exception if log.exception

  unless log.payload.respond_to?(:empty?) && log.payload[:exception].class.ancestors.include?(StandardError)
    return
  end

  log.payload[:exception]
end

#exception_hash(exception) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 113

def exception_hash exception
  {
    "error.type": exception.class.name,
    "error.message": exception.message,
    "error.stack_trace": BacktraceCleaner.clean(exception.backtrace)
  }
end

#file_name_and_lineObject

Ruby file name and line number that logged the message.



190
191
192
193
194
195
196
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 190

def file_name_and_line
  file, line = log.file_name_and_line
  return unless file

  hash[:"log.origin.file.name"] = file
  hash[:"log.origin.file.line"] = line.to_i
end

#format_payloadObject



166
167
168
169
170
171
172
173
174
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 166

def format_payload
  if log.payload.respond_to?(:empty?) && !log.payload.empty? && log.payload.respond_to?(:has_key?)
    self.formatted_payload = Utils::Hash[**log.payload]

    rack_extract
  else
    self.formatted_payload = {}
  end
end

#hostObject

Host name



31
32
33
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 31

def host
  log_labels[:host] = logger.host if log_host && logger.host
end

#initialize_rack_keysObject



125
126
127
128
129
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 125

def initialize_rack_keys
  formatted_payload[:request] ||= {}
  formatted_payload[:response] ||= {}
  formatted_payload[:metrics] ||= {}
end

#inner_exception(exception) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 88

def inner_exception exception
  if exception.respond_to?(:cause) && exception.cause
    exception.cause
  elsif exception.respond_to?(:continued_exception) && exception.continued_exception
    exception.continued_exception
  elsif exception.respond_to?(:original_exception) && exception.original_exception
    exception.original_exception
  end
end

#labelsObject



57
58
59
60
61
62
63
64
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 57

def labels
  self.log_labels ||= {}
  host
  application
  environment
  named_tags
  hash[:labels] = log_labels unless log_labels.empty?
end

#messageObject

Log message



67
68
69
70
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 67

def message
  hash[:message] = "#{log.name} -- #{log.cleansed_message}" if log.message
  hash[:message] = "#{log.metric} -- #{log.metric_amount}" if log.metric && log.metric_amount
end

#named_tagsObject

Named Tags



48
49
50
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 48

def named_tags
  log_labels[:named_tags] = log.named_tags if log.named_tags && !log.named_tags.empty?
end

#rack_extractObject



156
157
158
159
160
161
162
163
164
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 156

def rack_extract
  return unless formatted_payload.key? :controller

  initialize_rack_keys
  rack_request
  rack_response
  rack_metrics
  formatted_payload.delete :format
end

#rack_metricsObject



147
148
149
150
151
152
153
154
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 147

def rack_metrics
  metrics_keys = formatted_payload.keys.select do |k|
    k.to_s.end_with? "_runtime", "_count"
  end
  formatted_payload[:metrics].merge! formatted_payload.extract!(:allocations, *metrics_keys)
  formatted_payload[:metrics][:object_allocations] =
    formatted_payload[:metrics].delete :allocations
end

#rack_requestObject



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 131

def rack_request
  formatted_payload[:request].merge! formatted_payload.extract!(
    :controller,
    :action,
    :params,
    :method,
    :path,
    :request_id
  )
  formatted_payload[:request][:body] = formatted_payload[:request].delete :params
end

#rack_responseObject



143
144
145
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 143

def rack_response
  formatted_payload[:response].merge! formatted_payload.extract!(:status, :status_message)
end

#requestObject



176
177
178
179
180
181
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 176

def request
  hash[:"http.request.id"] = formatted_payload.dig :request, :request_id
  hash[:"http.request.body.content"] = formatted_payload.dig :request, :body
  hash[:"http.request.body.content"] = hash[:"http.request.body.content"].to_json if hash[:"http.request.body.content"].respond_to?(:to_json)
  hash[:"http.request.method"] = formatted_payload.dig :request, :method
end

#responseObject



183
184
185
186
187
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 183

def response
  hash[:"http.response.body.content"] = formatted_payload.dig :response, :body
  hash[:"http.response.body.content"] = hash[:"http.response.body.content"].to_json if hash[:"http.response.body.content"].respond_to?(:to_json)
  hash[:"http.response.status_code"] = formatted_payload.dig :response, :status
end

#tagsObject

Tags



73
74
75
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 73

def tags
  hash[:tags] = log.tags if log.tags && !log.tags.empty?
end

#timeObject

Date & time



53
54
55
# File 'lib/semantic_logger_ecs_addon/formatters/base.rb', line 53

def time
  hash[time_key] = format_time log.time.utc
end