scout_apm_logging 0.0.11 → 0.0.13

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: 8bbd257d9d08bbe578c328b108c2ce42e488ae5f7f0577a2ce7a692bbf208ac0
4
- data.tar.gz: f274d28b0e8485077d460cc5f00d259211a135e580fc5591cb84a04713650476
3
+ metadata.gz: dd453a461cde33d8b0dd69cf25180bd88aa1c29d7576001ac2605fd6e2eab95b
4
+ data.tar.gz: 86fcb8e29e7506ba5abc0a0961c0260c8a3c5695a04761c4f33bda002efaa201
5
5
  SHA512:
6
- metadata.gz: 120b0718b958634f0ba0b04ab122e4d8b6b2a743962b9089fbf309b0d97616107ebfcbab61dca6684d79079094d46f50cee1d4d27dfe2f4b945b4f6bdb9541da
7
- data.tar.gz: b9fa5e1dcfbe6d005c17a4719c9f8c93750639915d81ba946f597662c101fe4edd2b732dd176a180e6f1043d3f8eda0b9c8f0c6f7cd6a51ff24c7e61203adfaf
6
+ metadata.gz: 43ce974c35e2544f4870bebfdaa580dcb535f96d9905954df47be5afb75d3471ab12ef6bbda4c79605e83daa777fe15e8604d763ac99db616841b0acc82ab244
7
+ data.tar.gz: '09f7492dc86c28b91e38f340b2aad44b3fbe0cb1689f0e50bc814aa4dee78257f96417377c59b884ad147035576ed80dcaea73d9ee3a97e7429d5d94b114ed10'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 0.0.13
2
+ * Add ability to handle other libraries setting the Rails logger.
3
+ * Overwrite comparability methods on the proxy class. Have proxy class inherit from Object again.
4
+ * Clone original log instances.
5
+
6
+ ## 0.0.12
7
+ * Prevent certain attributes from being changed on created FileLogger.
8
+ * Update proxy class to inherit from BasicObject to relay class comparison methods
9
+ to held loggers.
10
+ * Fix ERB evaluation in scout_apm.yml config file to allow for usage of Rails.env.
11
+
1
12
  ## 0.0.11
2
13
  * Fix Scout layer capturing in log attributes for background jobs.
3
14
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require_relative '../lib/scout_apm/logging/monitor/_rails.rb'
3
4
  require_relative "../lib/scout_apm/logging/monitor/monitor.rb"
4
5
 
5
6
  ScoutApm::Logging::Monitor.instance.setup!
@@ -42,10 +42,11 @@ module ScoutApm
42
42
  Utils.ensure_directory_exists(context.config.value('logs_proxy_log_dir'))
43
43
  end
44
44
 
45
- def add_logging_patches!
45
+ def add_logging_patches! # rubocop:disable Metrics/AbcSize
46
+ require_relative './patches/rails_logger' unless ::Rails.logger.respond_to?(:broadcasts)
46
47
  # We can't swap out the logger similar to that of Rails and Sidekiq, as
47
48
  # the TaggedLogging logger is dynamically generated.
48
- return unless Rails.logger.respond_to?(:tagged)
49
+ return unless ::Rails.logger.respond_to?(:tagged)
49
50
 
50
51
  ::ActiveSupport::TaggedLogging.prepend(Patches::TaggedLogging)
51
52
 
@@ -53,9 +54,9 @@ module ScoutApm
53
54
  # This appears to be an issue in Ruby 2.7 with the broadcast logger.
54
55
  ruby_version = Gem::Version.new(RUBY_VERSION)
55
56
  isruby27 = (ruby_version >= Gem::Version.new('2.7') && ruby_version < Gem::Version.new('3.0'))
56
- return unless isruby27 && Rails.logger.respond_to?(:broadcasts)
57
+ return unless isruby27 && ::Rails.logger.respond_to?(:broadcasts)
57
58
 
58
- Rails.logger.broadcasts.each do |logger|
59
+ ::Rails.logger.broadcasts.each do |logger|
59
60
  logger.extend ::ActiveSupport::TaggedLogging
60
61
  end
61
62
  end
@@ -6,6 +6,21 @@ module ScoutApm
6
6
  # The actual instance of the logger.
7
7
  class FileLogger < ::Logger
8
8
  include ::ActiveSupport::LoggerSilence if const_defined?('::ActiveSupport::LoggerSilence')
9
+
10
+ # Other loggers may be extended with additional methods that have not been applied to this file logger.
11
+ # Most likely, these methods will still utilize the exiting logging methods to write to the IO device,
12
+ # however, if this is not the case we may miss logs. With that being said, we shouldn't impact the original
13
+ # applications intended behavior and let the user know we don't support it and no-op.
14
+ def method_missing(name, *_args)
15
+ return unless defined?(::Rails)
16
+
17
+ ::Rails.logger.warn("Method #{name} called on ScoutApm::Logging::Loggers::FileLogger, but it is not defined.")
18
+ end
19
+
20
+ # More impactful for the broadcast logger.
21
+ def respond_to_missing?(name, *_args)
22
+ super
23
+ end
9
24
  end
10
25
 
11
26
  # The newly created logger which we can configure, and will log to a filepath.
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A patch to Rails to allow swapping out the logger for the held logger in the proxy.
4
+ module Rails
5
+ class << self
6
+ def logger=(new_logger)
7
+ @logger.tap do |rails_logger|
8
+ if rails_logger.respond_to?(:is_scout_proxy_logger?)
9
+ old_logger = rails_logger.instance_variable_get(:@loggers).first
10
+ rails_logger.swap_scout_loggers!(old_logger, new_logger)
11
+ else
12
+ @logger = new_logger
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -11,10 +11,10 @@ module ScoutApm
11
11
  # Patches TaggedLogging to work with our loggers.
12
12
  module TaggedLogging
13
13
  def tagged(*tags) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
14
- return super(*tags) unless (self == ::Rails.logger && is_a?(ScoutApm::Logging::Loggers::Proxy)) ||
14
+ return super(*tags) unless (self == ::Rails.logger && respond_to?(:is_scout_proxy_logger?)) ||
15
15
  (::Rails.logger.respond_to?(:broadcasts) && ::Rails.logger.broadcasts.include?(self))
16
16
 
17
- if is_a?(ScoutApm::Logging::Loggers::Proxy)
17
+ if respond_to?(:is_scout_proxy_logger?)
18
18
  if block_given?
19
19
  # We skip the first logger to prevent double tagging when calling formatter.tagged
20
20
  loggers = @loggers[1..]
@@ -19,12 +19,50 @@ module ScoutApm
19
19
  @loggers << logger
20
20
  end
21
21
 
22
- def remove_scout_loggers(logger)
22
+ def remove_scout_loggers!(logger)
23
23
  @loggers.reject! { |inst_log| inst_log == logger }
24
24
 
25
25
  @loggers
26
26
  end
27
27
 
28
+ def swap_scout_loggers!(old_logger, new_logger)
29
+ logger_index = @loggers.index(old_logger)
30
+ return unless logger_index
31
+
32
+ @loggers[logger_index] = new_logger
33
+ end
34
+
35
+ # We don't want other libraries to change the formatter of the logger we create.
36
+ def formatter=(formatter)
37
+ @loggers.first.formatter = formatter
38
+ end
39
+
40
+ # We don't want other libraries to change the level of the logger we create, as this
41
+ # is dictated by the logs_capture_level configuration.
42
+ def level=(level)
43
+ @loggers.first.level = level
44
+ end
45
+
46
+ def is_a?(klass)
47
+ @loggers.first.is_a?(klass)
48
+ end
49
+
50
+ def kind_of?(klass)
51
+ @loggers.first.is_a?(klass)
52
+ end
53
+
54
+ def instance_of?(klass)
55
+ @loggers.first.instance_of?(klass)
56
+ end
57
+
58
+ def class
59
+ @loggers.first.class
60
+ end
61
+
62
+ def is_scout_proxy_logger?
63
+ true
64
+ end
65
+
28
66
  def method_missing(name, *args, &block)
29
67
  # Some libraries will do stuff like Library.logger.formatter = Rails.logger.formatter
30
68
  # As such, we should return the first logger's (the original logger) return value.
@@ -19,8 +19,10 @@ module ScoutApm
19
19
  def update_logger!
20
20
  # In Rails 7.1, broadcast logger was added which allows sinking to multiple IO devices.
21
21
  if defined?(::ActiveSupport::BroadcastLogger) && log_instance.is_a?(::ActiveSupport::BroadcastLogger)
22
+ context.logger.debug('Rails Broadcast logger detected. Adding new logger to broadcast.')
22
23
  add_logger_to_broadcast!
23
24
  else
25
+ context.logger.debug("Swapping in Proxy for current Rails logger: #{log_instance.class}.")
24
26
  swap_in_proxy_logger!
25
27
  end
26
28
 
@@ -37,24 +39,14 @@ module ScoutApm
37
39
  @new_file_logger ||= Loggers::Logger.new(context, log_instance).create_logger!
38
40
  end
39
41
 
40
- # Eseentially creates the original logger.
41
- def original_logger # rubocop:disable Metrics/AbcSize
42
- # We can use the previous logdev. log_device will continuously call write
43
- # through the devices until the logdev (@dev) is an IO device other than logdev:
44
- # https://github.com/ruby/ruby/blob/master/lib/logger/log_device.rb#L42
45
- # Log device holds the configurations around shifting too.
46
- original_logdevice = log_instance.instance_variable_get(:@logdev)
47
-
48
- ::Logger.new(original_logdevice).tap do |logger|
49
- logger.level = log_instance.level
50
- logger.formatter = log_instance.formatter
51
-
42
+ def original_logger
43
+ @original_logger = log_instance.clone.tap do |logger|
52
44
  if ::Rails.env.development? && $stdout.tty? && $stderr.tty?
53
- next if ActiveSupport::Logger.respond_to?(:logger_outputs_to?) && ActiveSupport::Logger.logger_outputs_to?(
45
+ next if ::ActiveSupport::Logger.respond_to?(:logger_outputs_to?) && ::ActiveSupport::Logger.logger_outputs_to?(
54
46
  logger, $stdout, $stderr
55
47
  )
56
48
 
57
- logger.extend(ActiveSupport::Logger.broadcast(ActiveSupport::Logger.new($stdout)))
49
+ logger.extend(ActiveSupport::Logger.broadcast(::ActiveSupport::Logger.new($stdout)))
58
50
  end
59
51
  end
60
52
  end
@@ -17,6 +17,7 @@ module ScoutApm
17
17
  end
18
18
 
19
19
  def update_logger!
20
+ context.logger.debug('Swapping in Proxy for Test logger.')
20
21
  swap_in_proxy_logger!
21
22
 
22
23
  new_log_location
@@ -34,16 +35,7 @@ module ScoutApm
34
35
 
35
36
  # Eseentially creates the original logger.
36
37
  def original_logger
37
- # We can use the previous logdev. log_device will continuously call write
38
- # through the devices until the logdev (@dev) is an IO device other than logdev:
39
- # https://github.com/ruby/ruby/blob/master/lib/logger/log_device.rb#L42
40
- # Log device holds the configurations around shifting too.
41
- original_logdevice = log_instance.instance_variable_get(:@logdev)
42
-
43
- ::Logger.new(original_logdevice).tap do |logger|
44
- logger.level = log_instance.level
45
- logger.formatter = log_instance.formatter
46
- end
38
+ @original_logger = log_instance.clone
47
39
  end
48
40
 
49
41
  def new_log_location
@@ -17,6 +17,7 @@ module ScoutApm
17
17
  end
18
18
 
19
19
  def update_logger!
20
+ context.logger.debug("Swapping in Proxy for current Sidekiq logger: #{log_instance.class}.")
20
21
  swap_in_proxy_logger!
21
22
 
22
23
  new_log_location
@@ -38,12 +39,7 @@ module ScoutApm
38
39
  # through the devices until the logdev (@dev) is an IO device other than logdev:
39
40
  # https://github.com/ruby/ruby/blob/master/lib/logger/log_device.rb#L42
40
41
  # Log device holds the configurations around shifting too.
41
- original_logdevice = log_instance.instance_variable_get(:@logdev)
42
-
43
- ::Logger.new(original_logdevice).tap do |logger|
44
- logger.level = log_instance.level
45
- logger.formatter = log_instance.formatter
46
- end
42
+ @original_logger = log_instance.clone
47
43
  end
48
44
 
49
45
  def new_log_location
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # We start the monitor process outside the context of Rails, and ultimately don't use
4
+ # it for anything related to starting the collector. However, when we load the config/scout_apm.yml file,
5
+ # we support ERB, and users may be using Rails.env methods for naming the app, or configuring whether
6
+ # monitor should be enabled for a specific environment.
7
+
8
+ require 'active_support'
9
+
10
+ # https://github.com/rails/rails/blob/v7.2.1/railties/lib/rails.rb#L76
11
+ module Rails
12
+ class << self
13
+ def env
14
+ # EnvironmentInquirer was added in Rails 6.1
15
+ @env ||= if const_defined?('::ActiveSupport::EnvironmentInquirer')
16
+ ::ActiveSupport::EnvironmentInquirer.new(ENV['RAILS_ENV'].presence || ENV['RACK_ENV'].presence || 'development')
17
+ else
18
+ ::ActiveSupport::StringInquirer.new(ENV['RAILS_ENV'].presence || ENV['RACK_ENV'].presence || 'development')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ScoutApm
4
4
  module Logging
5
- VERSION = '0.0.11'
5
+ VERSION = '0.0.13'
6
6
  end
7
7
  end
@@ -18,7 +18,7 @@ module ScoutApm
18
18
  if defined?(Rails) && defined?(Rails::Railtie)
19
19
  # If we are in a Rails environment, setup the monitor daemon manager.
20
20
  class RailTie < ::Rails::Railtie
21
- initializer 'scout_apm_logging.monitor' do
21
+ initializer 'scout_apm_logging.monitor', after: :initialize_logger, before: :initialize_cache do
22
22
  context = ScoutApm::Logging::MonitorManager.instance.context
23
23
 
24
24
  Loggers::Capture.new(context).setup!
@@ -35,7 +35,7 @@ describe ScoutApm::Logging::Loggers::Capture do
35
35
  capture = ScoutApm::Logging::Loggers::Capture.new(context)
36
36
  capture.setup!
37
37
 
38
- expect(TestLoggerWrapper.logger.class).to eq(ScoutApm::Logging::Loggers::Proxy)
38
+ expect(TestLoggerWrapper.logger.respond_to?(:is_scout_proxy_logger?)).to eq(true)
39
39
 
40
40
  TestLoggerWrapper.logger.info('TEST')
41
41
  TestLoggerWrapper.logger.debug('SHOULD NOT CAPTURE')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scout_apm_logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scout APM
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-23 00:00:00.000000000 Z
11
+ date: 2024-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: scout_apm
@@ -89,11 +89,13 @@ files:
89
89
  - lib/scout_apm/logging/loggers/capture.rb
90
90
  - lib/scout_apm/logging/loggers/formatter.rb
91
91
  - lib/scout_apm/logging/loggers/logger.rb
92
+ - lib/scout_apm/logging/loggers/patches/rails_logger.rb
92
93
  - lib/scout_apm/logging/loggers/patches/tagged_logging.rb
93
94
  - lib/scout_apm/logging/loggers/proxy.rb
94
95
  - lib/scout_apm/logging/loggers/swaps/rails.rb
95
96
  - lib/scout_apm/logging/loggers/swaps/scout.rb
96
97
  - lib/scout_apm/logging/loggers/swaps/sidekiq.rb
98
+ - lib/scout_apm/logging/monitor/_rails.rb
97
99
  - lib/scout_apm/logging/monitor/collector/checksum.rb
98
100
  - lib/scout_apm/logging/monitor/collector/configuration.rb
99
101
  - lib/scout_apm/logging/monitor/collector/downloader.rb