Class: SemanticLogger::Formatters::Signalfx

Inherits:
Base
  • Object
show all
Defined in:
lib/semantic_logger/formatters/signalfx.rb

Constant Summary

Constants inherited from Base

Base::PRECISION, Base::TIME_FORMAT

Instance Attribute Summary collapse

Attributes inherited from Base

#log_application, #log_host, #time_format

Instance Method Summary collapse

Constructor Details

#initialize(token:, dimensions: nil, log_host: true, log_application: true, gauge_name: 'Application.average', counter_name: 'Application.counter', environment: true) ⇒ Signalfx

Returns a new instance of Signalfx.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/semantic_logger/formatters/signalfx.rb', line 7

def initialize(token:,
               dimensions: nil,
               log_host: true,
               log_application: true,
               gauge_name: 'Application.average',
               counter_name: 'Application.counter',
               environment: true)

  @token        = token
  @dimensions   = dimensions.map(&:to_sym) if dimensions
  @gauge_name   = gauge_name
  @counter_name = counter_name

  if environment == true
    @environment = defined?(Rails) ? Rails.env : ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
  elsif environment
    @environment = environment
  end

  super(time_format: :ms, log_host: log_host, log_application: log_application)
end

Instance Attribute Details

#counter_nameObject

Returns the value of attribute counter_name.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def counter_name
  @counter_name
end

#dimensionsObject

Returns the value of attribute dimensions.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def dimensions
  @dimensions
end

#environmentObject

Returns the value of attribute environment.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def environment
  @environment
end

#gauge_nameObject

Returns the value of attribute gauge_name.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def gauge_name
  @gauge_name
end

#hashObject

Returns the value of attribute hash.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def hash
  @hash
end

#logObject

Returns the value of attribute log.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def log
  @log
end

#loggerObject

Returns the value of attribute logger.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def logger
  @logger
end

#tokenObject

Returns the value of attribute token.



5
6
7
# File 'lib/semantic_logger/formatters/signalfx.rb', line 5

def token
  @token
end

Instance Method Details

#batch(logs, logger) ⇒ Object

Returns [Hash] a batch of log messages. Signalfx has a minimum resolution of 1 second. Metrics of the same type, time (second), and dimensions can be aggregated together.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/semantic_logger/formatters/signalfx.rb', line 114

def batch(logs, logger)
  self.logger = logger

  data = {}
  logs.each do |log|
    self.hash = {}
    self.log  = log

    metric; time; value; format_dimensions

    if log.duration
      gauges = (data[:gauge] ||= [])
      add_gauge(gauges, hash)

      # Also send a count metric whenever it is a gauge so that it can be counted.
      unless log.dimensions
        count_hash          = hash.dup
        count_hash[:value]  = log.metric_amount || 1
        count_hash[:metric] = counter_name
        counters            = (data[:counter] ||= [])
        add_counter(counters, count_hash)
      end
    else
      counters = (data[:counter] ||= [])
      add_counter(counters, hash)
    end
  end

  data.to_json
end

#call(log, logger) ⇒ Object

Returns [Hash] log message in Signalfx format.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/semantic_logger/formatters/signalfx.rb', line 86

def call(log, logger)
  self.hash   = {}
  self.log    = log
  self.logger = logger

  metric; time; value; format_dimensions

  # gauge, counter, or cumulative_counter
  data = {}
  if log.duration
    data[:gauge] = [hash]
    # Also send a count metric whenever it is a gauge so that it can be counted.
    unless log.dimensions
      count_hash          = hash.dup
      count_hash[:value]  = log.metric_amount || 1
      count_hash[:metric] = counter_name
      data[:counter]      = [count_hash]
    end
  else
    data[:counter] = [hash]
  end

  data.to_json
end

#format_dimensionsObject

Dimensions for this metric



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/semantic_logger/formatters/signalfx.rb', line 65

def format_dimensions
  h = (hash[:dimensions] ||= {})
  if log.dimensions
    log.dimensions.each_pair do |name, value|
      value   = value.to_s
      h[name] = value unless value.empty?
    end
  else
    log.named_tags.each_pair do |name, value|
      name  = name.to_sym
      value = value.to_s
      next if value.empty?
      h[name] = value if dimensions&.include?(name)
    end
  end
  h[:host]        = logger.host if log_host && logger.host
  h[:application] = logger.application if log_application && logger.application
  h[:environment] = environment if environment
end

#metricObject

Create SignalFx friendly metric.

Strip leading '/'
Convert remaining '/' to '.'


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/semantic_logger/formatters/signalfx.rb', line 32

def metric
  name = log.metric.to_s.sub(/\A\/+/, '')
  if log.dimensions
    name.tr!('/', '.')
    hash[:metric] = name
  else
    # Extract class and action from metric name
    names = name.split('/')
    h     = (hash[:dimensions] ||= {})
    if names.size > 1
      h[:action] = names.pop
      h[:class]  = names.join('::')
    else
      h[:class]  = 'Unknown'
      h[:action] = names.first || log.metric
    end

    hash[:metric] = log.duration ? gauge_name : counter_name
  end
end

#timeObject

Date & time



54
55
56
57
# File 'lib/semantic_logger/formatters/signalfx.rb', line 54

def time
  # 1 second resolution, represented as ms.
  hash[:timestamp] = log.time.to_i * 1000
end

#valueObject

Value of this metric



60
61
62
# File 'lib/semantic_logger/formatters/signalfx.rb', line 60

def value
  hash[:value] = log.metric_amount || log.duration || 1
end