zuora_observability 0.1.0.pre.b → 0.1.0.pre.c

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3c6f15e5345dd32d8ada993579cf90efa2a2382573fe86f608f598be3f69f9e
4
- data.tar.gz: 38035565943c737e2f5ac59032780b6ce0c9e2eed0d039870d9b31b4780f7629
3
+ metadata.gz: be19d78e7a52c884e0bd5cc705a3725ea9616cd96491116d6ac047abbe8018b3
4
+ data.tar.gz: 446dc9c840d1d00cf66c0316d2fca0b38718d2b4ac32bcda718069515283c3f9
5
5
  SHA512:
6
- metadata.gz: c51373a4c25bebde5158c57e035a4363895f67c6f991fc7dbcd9a0741496e65ae07d7f6f65da86f8de14c4ef86ea509f0ba110d9fd7e3d29dcaa83e19117bbd6
7
- data.tar.gz: ca248b0270c959804ded1396591e6bacde2abaa2f478ea3b12c2a8265716562ddf0f8f87ddbd90f1ba228657568c337258936faaccebb9540dcbdff59e2903f9
6
+ metadata.gz: a70635409b8672344d7efd3c4025507ca0f450fc64aa78d5d81de9558926d1e5a59716832e7408a83abf24ed6492e4470a80fbb8bf1f84ad6391d1e188eaf94f
7
+ data.tar.gz: 7718bfc8650dc24092149163861a6f55ae7164cecda3f91534ee98c92645462195b9be625d0f212df974d2b87d4cc767ef9721d6f45581d47dfa0c878a53fccb
data/README.md CHANGED
@@ -17,9 +17,6 @@ end
17
17
 
18
18
  | Configuration Field | Default Value | Description |
19
19
  | ------------------- | ---------------------------------------------------------------- | ------------------------------------ |
20
- | `enable_metrics` | `false` | Enables writing metrics to telegraf |
21
- | `telegraf_endpoint` | `'udp://telegraf-app-metrics.monitoring.svc.cluster.local:8094'` | The URL to send telegraf metrics to |
22
- | `telegraf_debug` | `false` | Log info about data sent to telegraf |
23
20
  | `json_logging` | `false` in development/test, `true` otherwise | Use structured JSON logging for ZuoraObservability::Logger. **This configuration option cannot be changed in an initializer, but can be set to `true` with the presence of `ZUORA_JSON_LOGGING` environment variable** |
24
21
 
25
22
  ## Installation
@@ -7,8 +7,6 @@ require 'zuora_observability/metrics'
7
7
  require 'zuora_observability/logger'
8
8
 
9
9
  require 'zuora_observability/logging/formatter'
10
- require 'zuora_observability/metrics/telegraf'
11
- require 'zuora_observability/metrics/point_value'
12
10
 
13
11
  # Provides Rails application with tools for observabilty
14
12
  module ZuoraObservability
@@ -3,13 +3,9 @@
3
3
  module ZuoraObservability
4
4
  # Global configuration that can be set in a Rails initializer
5
5
  class Configuration
6
- attr_accessor :enable_metrics, :telegraf_endpoint, :telegraf_debug,
7
- :json_logging
6
+ attr_accessor :json_logging
8
7
 
9
8
  def initialize
10
- @enable_metrics = false
11
- @telegraf_endpoint = 'udp://telegraf-app-metrics.monitoring.svc.cluster.local:8094'
12
- @telegraf_debug = false
13
9
  # NOTE(hartley): this checks the var for presence rather than value to
14
10
  # align with how Rails does RAILS_LOG_TO_STDOUT
15
11
  @json_logging = ENV['ZUORA_JSON_LOGGING'].present? ? true : !(Rails.env.development? || Rails.env.test?)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'zuora_observability/metrics/page_request'
4
-
5
3
  module ZuoraObservability
6
4
  # The ZuoraObservability Engine is mounted to hook into Rails
7
5
  class Engine < ::Rails::Engine
@@ -22,12 +20,6 @@ module ZuoraObservability
22
20
  g.test_framework :rspec
23
21
  end
24
22
 
25
- # hook to process_action
26
- ActiveSupport::Notifications.subscribe(
27
- 'process_action.action_controller',
28
- ZuoraObservability::Metrics::PageRequest.new
29
- )
30
-
31
23
  initializer(:rails_stdout_logging, before: :initialize_logger) do
32
24
  require 'lograge'
33
25
 
@@ -42,7 +34,12 @@ module ZuoraObservability
42
34
  if Rails.configuration.logger.class.to_s == 'Ougai::Logger'
43
35
  Rails.configuration.lograge.formatter = Class.new do |fmt|
44
36
  def fmt.call(data)
45
- { msg: 'Rails Request', request: data }
37
+ {
38
+ msg: 'Rails Request',
39
+ trace_id: data.delete(:trace_id),
40
+ zuora_trace_id: data.delete(:zuora_trace_id),
41
+ request: data
42
+ }.compact
46
43
  end
47
44
  end
48
45
  end
@@ -51,7 +48,9 @@ module ZuoraObservability
51
48
  exceptions = %w(controller action format)
52
49
  items = {
53
50
  #time: event.time.strftime('%FT%T.%6N'),
54
- params: event.payload[:params].as_json(except: exceptions).to_json.to_s
51
+ params: event.payload[:params].as_json(except: exceptions).to_json.to_s,
52
+ trace_id: event.payload[:headers]['action_dispatch.request_id'],
53
+ zuora_trace_id: event.payload[:headers]['HTTP_ZUORA_REQUEST_ID']
55
54
  }
56
55
  items.merge!({exception_object: event.payload[:exception_object]}) if event.payload[:exception_object].present?
57
56
  items.merge!({exception: event.payload[:exception]}) if event.payload[:exception].present?
@@ -21,11 +21,6 @@ module ZuoraObservability
21
21
  if ZuoraObservability.configuration.json_logging
22
22
  require 'zuora_observability/logging/formatter'
23
23
  logger.formatter = ZuoraObservability::Logging::Formatter.new(name)
24
- logger.before_log = lambda do |data|
25
- data[:trace_id] = ZuoraConnect::RequestIdMiddleware.request_id if ZuoraConnect::RequestIdMiddleware.request_id.present?
26
- data[:zuora_trace_id] = ZuoraConnect::RequestIdMiddleware.zuora_request_id if ZuoraConnect::RequestIdMiddleware.zuora_request_id.present?
27
- #data[:traces] = {amazon_id: data[:trace_id], zuora_id: data[:zuora_trace_id]}
28
- end
29
24
  else
30
25
  logger.formatter = Ougai::Formatters::Customizable.new(
31
26
  format_err: proc do |data|
@@ -3,18 +3,7 @@
3
3
  module ZuoraObservability
4
4
  # Methods to gather and format metrics
5
5
  module Metrics
6
- @@telegraf_host = nil
7
-
8
6
  class << self
9
- def write_to_telegraf(*args)
10
- if ZuoraObservability.configuration.enable_metrics && !defined?(Prometheus)
11
- @@telegraf_host = Metrics::Telegraf.new() if @@telegraf_host == nil
12
- unicorn_stats = Metrics.unicorn_listener if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
13
- @@telegraf_host.write(direction: 'Raindrops', tags: {}, values: unicorn_stats) unless unicorn_stats.blank?
14
- return @@telegraf_host.write(*args)
15
- end
16
- end
17
-
18
7
  def resque
19
8
  Resque.redis.ping
20
9
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZuoraObservability
4
- VERSION = '0.1.0-b'
4
+ VERSION = '0.1.0-c'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_observability
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.b
4
+ version: 0.1.0.pre.c
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hartley McGuire
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-03 00:00:00.000000000 Z
11
+ date: 2021-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lograge
@@ -263,9 +263,6 @@ files:
263
263
  - lib/zuora_observability/logger.rb
264
264
  - lib/zuora_observability/logging/formatter.rb
265
265
  - lib/zuora_observability/metrics.rb
266
- - lib/zuora_observability/metrics/page_request.rb
267
- - lib/zuora_observability/metrics/point_value.rb
268
- - lib/zuora_observability/metrics/telegraf.rb
269
266
  - lib/zuora_observability/version.rb
270
267
  homepage:
271
268
  licenses:
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ZuoraObservability
4
- module Metrics
5
- # Object of this class is passed to the ActiveSupport::Notification hook
6
- class PageRequest
7
- # This method is triggered when a non error page is loaded (not 404)
8
- def call(_name, started, finished, unique_id, payload)
9
- # If the url contains any css or JavaScript files then do not collect metrics for them
10
- return nil if %w[css assets jpg png jpeg ico].any? { |word| payload[:path].include?(word) }
11
-
12
- # Getting the endpoint and the content_type
13
- content_hash = { :html => 'text/html', :js => 'application/javascript', :json => 'application/json', :csv => 'text/csv' }
14
- content_type = content_hash.key?(payload[:format]) ? content_hash[payload[:format]] : payload[:format]
15
- content_type = content_type.to_s.gsub('text/javascript', 'application/javascript')
16
-
17
- # payloads with 500 requests do not have status as it is not set by the controller
18
- # https://github.com/rails/rails/issues/33335
19
- # status_code = payload[:status] ? payload[:status] : payload[:exception_object].present? ? 500 : ""
20
- if payload[:exception].present?
21
- status_code, exception = [500, payload[:exception].first]
22
- else
23
- status_code, exception = [payload[:status], nil]
24
- end
25
-
26
- tags = { method: payload[:method], status: status_code, error_type: exception, content_type: content_type, controller: payload[:controller], action: payload[:action] }.compact
27
-
28
- values = { view_time: payload[:view_runtime], db_time: payload[:db_runtime], response_time: ((finished - started) * 1000) }.compact
29
- values = values.map { |k, v| [k, v.round(2)] }.to_h
30
-
31
- ZuoraObservability::Metrics.write_to_telegraf(direction: :inbound, tags: tags, values: values)
32
- end
33
- end
34
- end
35
- end
@@ -1,84 +0,0 @@
1
- # this looks copied from https://github.com/influxdata/influxdb-ruby, it may be
2
- # worth just using the gem instead of vendoring the file
3
- # module InfluxDB
4
- module ZuoraObservability
5
- module Metrics
6
- # Convert data point to string using Line protocol
7
- class PointValue
8
- attr_reader :series, :values, :tags, :timestamp
9
-
10
- def initialize(data)
11
- @series = escape data[:series], :measurement
12
- @values = escape_values data[:values]
13
- @tags = escape_tags data[:tags]
14
- @timestamp = data[:timestamp]
15
- end
16
-
17
- def dump
18
- dump = @series.dup
19
- dump << ",#{@tags}" if @tags
20
- dump << " #{@values}"
21
- dump << " #{@timestamp}" if @timestamp
22
- dump
23
- end
24
-
25
- private
26
-
27
- ESCAPES = {
28
- measurement: [' '.freeze, ','.freeze],
29
- tag_key: ['='.freeze, ' '.freeze, ','.freeze],
30
- tag_value: ['='.freeze, ' '.freeze, ','.freeze],
31
- field_key: ['='.freeze, ' '.freeze, ','.freeze, '"'.freeze],
32
- field_value: ["\\".freeze, '"'.freeze],
33
- }.freeze
34
-
35
- private_constant :ESCAPES
36
-
37
- def escape(str, type)
38
- # rubocop:disable Layout/AlignParameters
39
- str = str.encode "UTF-8".freeze, "UTF-8".freeze,
40
- invalid: :replace,
41
- undef: :replace,
42
- replace: "".freeze
43
- # rubocop:enable Layout/AlignParameters
44
-
45
- ESCAPES[type].each do |ch|
46
- str = str.gsub(ch) { "\\#{ch}" }
47
- end
48
- str
49
- end
50
-
51
- def escape_values(values)
52
- return if values.nil?
53
- values.map do |k, v|
54
- key = escape(k.to_s, :field_key)
55
- val = escape_value(v)
56
- "#{key}=#{val}"
57
- end.join(",".freeze)
58
- end
59
-
60
- def escape_value(value)
61
- if value.is_a?(String)
62
- '"'.freeze + escape(value, :field_value) + '"'.freeze
63
- elsif value.is_a?(Integer)
64
- "#{value}i"
65
- else
66
- value.to_s
67
- end
68
- end
69
-
70
- def escape_tags(tags)
71
- return if tags.nil?
72
-
73
- tags = tags.map do |k, v|
74
- key = escape(k.to_s, :tag_key)
75
- val = escape(v.to_s, :tag_value)
76
-
77
- "#{key}=#{val}" unless key == "".freeze || val == "".freeze
78
- end.compact
79
-
80
- tags.join(",") unless tags.empty?
81
- end
82
- end
83
- end
84
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ZuoraObservability
4
- module Metrics
5
- # Functionality for sending metrics to a Telegraf endpoint
6
- #
7
- # it looks like https://github.com/influxdata/influxdb-ruby may provide some
8
- # more high level abstractions instead of using a UDPSocket directly
9
- class Telegraf
10
- attr_accessor :host
11
-
12
- OUTBOUND_METRICS = true
13
- OUTBOUND_METRICS_NAME = 'request-outbound'
14
- INBOUND_METRICS = true
15
- INBOUND_METRICS_NAME = 'request-inbound'
16
-
17
- def initialize
18
- connect
19
- end
20
-
21
- def connect
22
- # TODO(hartley): this Rails logger was originally ZuoraConnect.logger
23
- Rails.logger.debug(format_metric_log('Telegraf', 'Need new connection')) if ZuoraObservability.configuration.telegraf_debug
24
- uri = URI.parse(ZuoraObservability.configuration.telegraf_endpoint)
25
- self.host = UDPSocket.new.tap do |socket|
26
- socket.connect uri.host, uri.port
27
- end
28
- rescue => ex
29
- self.host = nil
30
- # TODO(hartley): this Rails logger was originally ZuoraConnect.logger
31
- Rails.logger.warn(self.format_metric_log('Telegraf', "Failed to connect: #{ex.class}")) if Rails.env.to_s != 'production'
32
- end
33
-
34
- def write(direction: 'Unknown', tags: {}, values: {})
35
- time = Benchmark.measure do
36
- # To avoid writing metrics from rspec tests
37
- if Rails.env.to_sym != :test
38
- app_instance = Thread.current[:appinstance].present? ? Thread.current[:appinstance].id : 0
39
- tags = {
40
- app_name: Env.app_name, process_type: Env.process_type,
41
- app_instance: app_instance, pod_name: Env.pod_name
42
- }.merge(tags)
43
-
44
- if direction == :inbound
45
- # This condition relies on a monkey patch in the connect gem that
46
- # adds a to_bool method for Nil, True, and False that are not
47
- # present by default
48
- if INBOUND_METRICS && !Thread.current[:inbound_metric].to_bool
49
- self.write_udp(series: INBOUND_METRICS_NAME, tags: tags, values: values)
50
- Thread.current[:inbound_metric] = true
51
- else
52
- return
53
- end
54
- elsif direction == :outbound
55
- write_udp(series: OUTBOUND_METRICS_NAME, tags: tags, values: values) if OUTBOUND_METRICS
56
- else
57
- write_udp(series: direction, tags: tags, values: values)
58
- end
59
- end
60
- end
61
-
62
- return unless ZuoraObservability.configuration.telegraf_debug
63
-
64
- # TODO(hartley): these Rails loggers were originally ZuoraConnect.logger
65
- Rails.logger.debug(format_metric_log('Telegraf', tags.to_s))
66
- Rails.logger.debug(format_metric_log('Telegraf', values.to_s))
67
- Rails.logger.debug(
68
- format_metric_log(
69
- 'Telegraf',
70
- "Writing '#{direction.capitalize}': #{time.real.round(5)} ms"
71
- )
72
- )
73
- end
74
-
75
- def write_udp(series: '', tags: {}, values: {})
76
- return if values.blank?
77
-
78
- host.write PointValue.new({ series: series, tags: tags, values: values }).dump
79
- rescue => ex
80
- self.connect
81
- ZuoraConnect.logger.warn(self.format_metric_log('Telegraf', "Failed to write udp: #{ex.class}")) if Rails.env.to_s != 'production'
82
- end
83
-
84
- def format_metric_log(message, dump = nil)
85
- message_color = '1;91'
86
- dump_color = '0;1'
87
- log_entry = " \e[#{message_color}m#{message}\e[0m #{
88
- "\e[#{dump_color}m#{dump}\e[0m" if dump
89
- }"
90
- if Rails.env.development?
91
- log_entry
92
- else
93
- [message, dump].compact.join(' - ')
94
- end
95
- end
96
- end
97
- end
98
- end