scout_apm_logging 0.0.11 → 0.0.13

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: 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