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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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