nexus_semantic_logger 1.7.3 → 1.9.0

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: 6fb8608fc5db931115c7c1398607eff97e56745183939261b1993ea10004e10e
4
- data.tar.gz: 9b326b54b65bcd45a0f5a8fef49e4d0b0112710028996afcb957ff0113aae8ff
3
+ metadata.gz: 71ea65404e5b4980ffa32eda0d91588142cd2571252117f1f651f566f506bb98
4
+ data.tar.gz: ade58c1fcc429f832d26ed23786d859068cefb6e33a1f7b5b32d2627de999c91
5
5
  SHA512:
6
- metadata.gz: f5d864a434d1499e2b0880b55f5969e2f0856e2625d9e20db54387b01610fea866cc09191276f2c2f5ff1601927f4a2a7140f42ca70993cf6f5c5499753c055e
7
- data.tar.gz: 240f197160c496ac997ae2c5cd33a672d656b6bf6280318e7926d5cb593ecac40f794316a9090dfa7984273bff9ed987cf6ef689e20591a62690dd3b40b971c5
6
+ metadata.gz: 0d488c447d1e7f14c49a0c33ff0ee79ff512346ea17557c68a91e4b204dd37d9bdafb04383ed4db1c7c2c71d15273a9375c49c1e031a9a710e2345b34f143db9
7
+ data.tar.gz: 3712bf027d2fc5668c3a593d8cbd79457aef86d69a19e5602bfe4929ba301e14f6ce9006680acfbf4ce777ba5ae42f18ee45cdb6fded3a3fa4d1e0f8c284479b
data/README.md CHANGED
@@ -9,7 +9,44 @@ As well as providing a semantic logger, this gem handles datadog telemetry assoc
9
9
  * logs
10
10
  * traces
11
11
  * metrics
12
- * statsd is automatically attached to datadog runtime metrics and may also be used for custom metrics.
12
+ * statsd is automatically attached to datadog runtime metrics and may also be used for custom metrics.
13
+
14
+ ### Customise log level per logger
15
+
16
+ For example, to show debug logging for `MySubscriber` while having all other logs on info.
17
+
18
+ ```
19
+ # The log level must be set to the lowest level which can be dynamically controlled.
20
+ LOG_LEVEL=DEBUG
21
+ # The default level for filtered logs.
22
+ LOG_NAMES_DEFAULT_LEVEL=INFO
23
+ # Per level overrides for filtered logs.
24
+ LOG_NAMES_DEBUG=MySubscriber
25
+ ```
26
+
27
+ * Customised log names are available for each level e.g. `LOG_NAMES_TRACE`
28
+ * Log names are matched on prefix.
29
+ * Multiple log names are supported via comma separated values.
30
+
31
+ ### Changing log level dynamically
32
+
33
+ The default level for filtered logs (`LOG_NAMES_DEFAULT_LEVEL`) may be changed on a running instance with the `WINCH`
34
+ signal. This cycles through the available levels `[trace debug info warn error fatal]`.
35
+
36
+ Note that you cannot dynamically enable a level lower than the `LOG_LEVEL`. Instead the env var must be adjusted and the
37
+ instance restarted.
38
+
39
+ Send signal: `pkill --signal WINCH --count --full "^puma.*"`
40
+
41
+ Instance output: `WINCH signal changed LOG_NAMES_DEFAULT_LEVEL from debug to info`
42
+
43
+ ### Querying current log level
44
+
45
+ The `SYS` signal will print the levels used by the running instance.
46
+
47
+ Send signal: `pkill --signal SYS --count --full "^puma.*"`
48
+
49
+ Instance output: `SYS signal reports LOG_LEVEL=debug LOG_NAMES_DEFAULT_LEVEL=warn`
13
50
 
14
51
  ### Sending metrics
15
52
 
@@ -32,8 +32,12 @@ module NexusSemanticLogger
32
32
  }
33
33
  end
34
34
 
35
+ def self.env_level
36
+ @@level ||= ENV.fetch('LOG_LEVEL', Rails.application.config.log_level).downcase
37
+ end
38
+
35
39
  def self.env_names_default_level
36
- @@names_default_level ||= ENV.fetch('LOG_NAMES_DEFAULT_LEVEL', Rails.application.config.log_level)
40
+ @@names_default_level ||= ENV.fetch('LOG_NAMES_DEFAULT_LEVEL', Rails.application.config.log_level).downcase
37
41
  end
38
42
 
39
43
  def self.env_names_trace
@@ -61,6 +65,7 @@ module NexusSemanticLogger
61
65
  end
62
66
 
63
67
  def self.flush
68
+ @@level = nil
64
69
  @@names_default_level = nil
65
70
  @@names_trace = nil
66
71
  @@names_debug = nil
@@ -73,5 +78,40 @@ module NexusSemanticLogger
73
78
  def self.fetch_env_names(var)
74
79
  ENV.fetch(var, '').split(',').to_set
75
80
  end
81
+
82
+ # Change LOG_LEVEL and LOG_NAMES_DEFAULT_LEVEL on a running process by sending signals.
83
+ # Each signal rotates through the levels, wrapping around.
84
+ # Based on SemanticLogger.add_signal_handler.
85
+ # Note that USR1/USR2 are already used by puma. WINCH/SYS should be unused these days.
86
+ def self.add_signal_handler(log_names_level_signal = "WINCH", info_signal = "SYS")
87
+ if log_names_level_signal
88
+ Signal.trap(log_names_level_signal) do
89
+ current_level = env_names_default_level
90
+ next_level = get_next_log_level(current_level)
91
+ @@names_default_level = next_level
92
+ puts "#{log_names_level_signal} signal changed LOG_NAMES_DEFAULT_LEVEL from #{current_level} to #{next_level}"
93
+ rescue => err
94
+ puts "Error handling signal #{log_names_level_signal}: #{err}"
95
+ puts err.backtrace
96
+ end
97
+ end
98
+
99
+ if info_signal
100
+ Signal.trap(info_signal) do
101
+ current_level = env_names_default_level
102
+ puts "#{info_signal} signal reports LOG_LEVEL=#{env_level} LOG_NAMES_DEFAULT_LEVEL=#{current_level}"
103
+ rescue => err
104
+ puts "Error handling signal #{info_signal}: #{err}"
105
+ puts err.backtrace
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.get_next_log_level(current_log_level)
111
+ current_log_level_index = SemanticLogger::Levels.index(current_log_level)
112
+ next_log_level_index = current_log_level_index + 1
113
+ next_log_level_index = 0 if next_log_level_index >= SemanticLogger::Levels.all_levels.size
114
+ SemanticLogger::Levels.level(next_log_level_index)
115
+ end
76
116
  end
77
117
  end
@@ -35,9 +35,12 @@ module NexusSemanticLogger
35
35
  config.rails_semantic_logger.add_file_appender = false
36
36
  dd_appender = config.semantic_logger.add_appender(io: $stdout, formatter: config.rails_semantic_logger.format)
37
37
  dd_appender.filter = NexusSemanticLogger::AppenderFilter.filter_lambda
38
+ NexusSemanticLogger::AppenderFilter.add_signal_handler
38
39
 
39
40
  NexusSemanticLogger::DatadogTracer.new(service)
40
41
 
42
+ SemanticLogger.on_log(NexusSemanticLogger::LoggerMetricsSubscriber.new)
43
+
41
44
  logger.info('SemanticLogger initialised.', level: config.log_level)
42
45
 
43
46
  config.after_initialize do
@@ -17,7 +17,7 @@ module NexusSemanticLogger
17
17
  # @param [String] metric Metric name.
18
18
  # @param [Array<String>] tags Additional tags.
19
19
  def increment(metric, tags: [])
20
- statsd&.increment(metric, tags: global_tags + tags)
20
+ statsd&.increment(metric, tags: combine_tags(tags))
21
21
  flush
22
22
  end
23
23
 
@@ -25,7 +25,7 @@ module NexusSemanticLogger
25
25
  # @param [String] metric Metric name.
26
26
  # @param [Array<String>] tags Additional tags.
27
27
  def decrement(metric, tags: [])
28
- statsd&.decrement(metric, tags: global_tags + tags)
28
+ statsd&.decrement(metric, tags: combine_tags(tags))
29
29
  flush
30
30
  end
31
31
 
@@ -34,7 +34,7 @@ module NexusSemanticLogger
34
34
  # @param [Integer] ms Timing in milliseconds.
35
35
  # @param [Array<String>] tags Additional tags.
36
36
  def timing(metric, ms, tags: [])
37
- statsd&.timing(metric, ms, tags: global_tags + tags)
37
+ statsd&.timing(metric, ms, tags: combine_tags(tags))
38
38
  flush
39
39
  end
40
40
 
@@ -43,7 +43,7 @@ module NexusSemanticLogger
43
43
  # @param [Numeric] value Distribution value.
44
44
  # @param [Array<String>] tags Additional tags.
45
45
  def distribution(metric, value, tags: [])
46
- statsd&.distribution(metric, value, tags: global_tags + tags)
46
+ statsd&.distribution(metric, value, tags: combine_tags(tags))
47
47
  flush
48
48
  end
49
49
 
@@ -52,8 +52,18 @@ module NexusSemanticLogger
52
52
  # @param [Numeric] value Gauge value.
53
53
  # @param [Array<String>] tags Additional tags.
54
54
  def gauge(metric, value, tags: [])
55
- statsd&.gauge(metric, value, tags: global_tags + tags)
55
+ statsd&.gauge(metric, value, tags: combine_tags(tags))
56
56
  flush
57
57
  end
58
+
59
+ private
60
+
61
+ # Safely combine the global tags with the supplied tags.
62
+ def combine_tags(tags)
63
+ final_tags = []
64
+ final_tags += global_tags unless global_tags.nil?
65
+ final_tags += tags unless tags.nil?
66
+ final_tags
67
+ end
58
68
  end
59
69
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ require 'semantic_logger'
3
+
4
+ module NexusSemanticLogger
5
+ # Sends SemanticLogger metrics to statsd.
6
+ # This is a candidate to move into the nexus_semantic_logger gem if it becomes widely useful.
7
+ # See https://logger.rocketjob.io/metrics.html
8
+ # Based on https://github.com/reidmorrison/semantic_logger/blob/master/lib/semantic_logger/metric/statsd.rb
9
+ class LoggerMetricsSubscriber < SemanticLogger::Subscriber
10
+ def call(log)
11
+ log(log) if should_log?(log)
12
+ end
13
+
14
+ def log(log)
15
+ metric = log.metric
16
+ tags = log.payload.nil? ? nil : []
17
+ log.payload&.each_pair { |key, value| tags << "#{key}:#{value}" }
18
+ if (duration = log.duration)
19
+ NexusSemanticLogger.metrics.timing(metric, duration, tags: tags)
20
+ else
21
+ amount = (log.metric_amount || 1).round
22
+ if amount.negative?
23
+ NexusSemanticLogger.metrics.decrement(metric, tags: tags)
24
+ else
25
+ NexusSemanticLogger.metrics.increment(metric, tags: tags)
26
+ end
27
+ end
28
+ end
29
+
30
+ # Only forward log entries that contain metrics.
31
+ def should_log?(log)
32
+ # Does not support metrics with dimensions.
33
+ log.metric && !log.dimensions && meets_log_level?(log) && !filtered?(log)
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module NexusSemanticLogger
3
- # Leave this as 1.7.3 in order for CI process to replace with the tagged version.
4
- VERSION = '1.7.3'
3
+ # Leave this as 1.9.0 in order for CI process to replace with the tagged version.
4
+ VERSION = '1.9.0'
5
5
  end
@@ -4,6 +4,7 @@ require 'nexus_semantic_logger/application'
4
4
  require 'nexus_semantic_logger/datadog_formatter'
5
5
  require 'nexus_semantic_logger/datadog_singleton'
6
6
  require 'nexus_semantic_logger/datadog_tracer'
7
+ require 'nexus_semantic_logger/logger_metrics_subscriber'
7
8
 
8
9
  module NexusSemanticLogger
9
10
  # Get application wide object for sending metrics.
@@ -11,3 +12,12 @@ module NexusSemanticLogger
11
12
  DatadogSingleton.instance
12
13
  end
13
14
  end
15
+
16
+ # Patch access to LEVELS array.
17
+ module SemanticLogger
18
+ module Levels
19
+ def self.all_levels
20
+ LEVELS
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexus_semantic_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.3
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johnathon Harris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-22 00:00:00.000000000 Z
11
+ date: 2022-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print
@@ -112,6 +112,7 @@ files:
112
112
  - lib/nexus_semantic_logger/datadog_singleton.rb
113
113
  - lib/nexus_semantic_logger/datadog_tracer.rb
114
114
  - lib/nexus_semantic_logger/extensions/action_dispatch/debug_exceptions.rb
115
+ - lib/nexus_semantic_logger/logger_metrics_subscriber.rb
115
116
  - lib/nexus_semantic_logger/sneakers_metrics.rb
116
117
  - lib/nexus_semantic_logger/version.rb
117
118
  - nexus_semantic_logger.gemspec