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

Instance Attribute Summary collapse

Attributes inherited from Base

#log, #log_application, #log_environment, #log_host, #logger, #precision, #time_format

Instance Method Summary collapse

Methods inherited from Base

build_time_format, #pid

Constructor Details

#initialize(token:, dimensions: nil, gauge_name: "Application.average", counter_name: "Application.counter", time_format: :ms, **args) ⇒ Signalfx

Returns a new instance of Signalfx.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/semantic_logger/formatters/signalfx.rb', line 7

def initialize(token:,
               dimensions: nil,
               gauge_name: "Application.average",
               counter_name: "Application.counter",
               time_format: :ms,
               **args)

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

  super(time_format: time_format, **args)
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

#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

#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.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/semantic_logger/formatters/signalfx.rb', line 108

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.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/semantic_logger/formatters/signalfx.rb', line 80

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



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/semantic_logger/formatters/signalfx.rb', line 58

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] = logger.environment if log_environment && logger.environment
end

#metricObject

Create SignalFx friendly metric.

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


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/semantic_logger/formatters/signalfx.rb', line 25

def metric
  name = log.metric.to_s.sub(%r{\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



47
48
49
50
# File 'lib/semantic_logger/formatters/signalfx.rb', line 47

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

#valueObject

Value of this metric



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

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