scout_apm_logging 0.0.12 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/NOTICE +4 -0
- data/lib/scout_apm/logging/config.rb +5 -131
- data/lib/scout_apm/logging/loggers/capture.rb +8 -6
- data/lib/scout_apm/logging/loggers/formatter.rb +21 -2
- data/lib/scout_apm/logging/loggers/opentelemetry/LICENSE +201 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/NOTICE +9 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/log_record.rb +18 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/logger.rb +64 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/logger_provider.rb +31 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/severity_number.rb +43 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/version.rb +18 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/api/logs.rb +28 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/exporter/otlp/logs_exporter.rb +389 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/exporter/otlp/version.rb +20 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/collector/logs/v1/logs_service_pb.rb +43 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/common/v1/common_pb.rb +58 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/logs/v1/logs_pb.rb +91 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/resource/v1/resource_pb.rb +33 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/opentelemetry.rb +62 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export/batch_log_record_processor.rb +225 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export/log_record_exporter.rb +64 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export.rb +34 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record.rb +115 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record_data.rb +31 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record_processor.rb +53 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/logger.rb +94 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/logger_provider.rb +158 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/version.rb +20 -0
- data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs.rb +28 -0
- data/lib/scout_apm/logging/loggers/patches/rails_logger.rb +17 -0
- data/lib/scout_apm/logging/loggers/proxy.rb +22 -5
- data/lib/scout_apm/logging/loggers/swaps/rails.rb +4 -12
- data/lib/scout_apm/logging/loggers/swaps/scout.rb +2 -10
- data/lib/scout_apm/logging/loggers/swaps/sidekiq.rb +2 -6
- data/lib/scout_apm/logging/utils.rb +0 -69
- data/lib/scout_apm/logging/version.rb +1 -1
- data/lib/scout_apm_logging.rb +3 -12
- data/scout_apm_logging.gemspec +7 -0
- data/spec/data/config_test_1.yml +0 -1
- data/spec/data/mock_config.yml +0 -3
- data/spec/integration/rails/lifecycle_spec.rb +57 -23
- data/spec/spec_helper.rb +0 -12
- data/spec/unit/config_spec.rb +0 -12
- data/spec/unit/loggers/capture_spec.rb +0 -6
- metadata +127 -39
- data/bin/scout_apm_logging_monitor +0 -6
- data/lib/scout_apm/logging/monitor/_rails.rb +0 -22
- data/lib/scout_apm/logging/monitor/collector/checksum.rb +0 -51
- data/lib/scout_apm/logging/monitor/collector/configuration.rb +0 -150
- data/lib/scout_apm/logging/monitor/collector/downloader.rb +0 -78
- data/lib/scout_apm/logging/monitor/collector/extractor.rb +0 -37
- data/lib/scout_apm/logging/monitor/collector/manager.rb +0 -57
- data/lib/scout_apm/logging/monitor/monitor.rb +0 -216
- data/lib/scout_apm/logging/monitor_manager/manager.rb +0 -162
- data/lib/scout_apm/logging/state.rb +0 -69
- data/spec/data/empty_logs_config.yml +0 -0
- data/spec/data/logs_config.yml +0 -3
- data/spec/data/state_file.json +0 -3
- data/spec/integration/loggers/capture_spec.rb +0 -68
- data/spec/integration/monitor/collector/downloader/will_verify_checksum.rb +0 -49
- data/spec/integration/monitor/collector_healthcheck_spec.rb +0 -29
- data/spec/integration/monitor/continuous_state_collector_spec.rb +0 -31
- data/spec/integration/monitor/previous_collector_setup_spec.rb +0 -45
- data/spec/integration/monitor_manager/disable_agent_spec.rb +0 -30
- data/spec/integration/monitor_manager/monitor_pid_file_spec.rb +0 -38
- data/spec/integration/monitor_manager/single_monitor_spec.rb +0 -53
- data/spec/unit/monitor/collector/configuration_spec.rb +0 -64
- data/spec/unit/state_spec.rb +0 -20
- data/tooling/checksums.rb +0 -106
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module ScoutApm
|
8
|
+
module Logging
|
9
|
+
module Loggers
|
10
|
+
module OpenTelemetry
|
11
|
+
module SDK
|
12
|
+
module Logs
|
13
|
+
# LogRecordProcessor describes a duck type and provides a synchronous no-op hook for when a
|
14
|
+
# {LogRecord} is emitted. It is not required to subclass this
|
15
|
+
# class to provide an implementation of LogRecordProcessor, provided the interface is
|
16
|
+
# satisfied.
|
17
|
+
class LogRecordProcessor
|
18
|
+
# Called when a {LogRecord} is emitted. Subsequent calls are not
|
19
|
+
# permitted after shutdown is called.
|
20
|
+
# @param [LogRecord] log_record The emitted {LogRecord}
|
21
|
+
# @param [Context] context The {Context}
|
22
|
+
def on_emit(log_record, context); end
|
23
|
+
|
24
|
+
# Export all log records to the configured `Exporter` that have not yet
|
25
|
+
# been exported.
|
26
|
+
#
|
27
|
+
# This method should only be called in cases where it is absolutely
|
28
|
+
# necessary, such as when using some FaaS providers that may suspend
|
29
|
+
# the process after an invocation, but before the `Processor` exports
|
30
|
+
# the completed spans.
|
31
|
+
#
|
32
|
+
# @param [Numeric] timeout An optional timeout in seconds.
|
33
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
34
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
35
|
+
def force_flush(timeout: nil)
|
36
|
+
Export::SUCCESS
|
37
|
+
end
|
38
|
+
|
39
|
+
# Called when {LoggerProvider#shutdown} is called.
|
40
|
+
#
|
41
|
+
# @param [Numeric] timeout An optional timeout in seconds.
|
42
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
43
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
44
|
+
def shutdown(timeout: nil)
|
45
|
+
Export::SUCCESS
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module ScoutApm
|
8
|
+
module Logging
|
9
|
+
module Loggers
|
10
|
+
module OpenTelemetry
|
11
|
+
module SDK
|
12
|
+
module Logs
|
13
|
+
# The SDK implementation of OpenTelemetry::Logs::Logger
|
14
|
+
class Logger < OpenTelemetry::Logs::Logger
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
# Returns a new {OpenTelemetry::SDK::Logs::Logger} instance. This should
|
18
|
+
# not be called directly. New loggers should be created using
|
19
|
+
# {LoggerProvider#logger}.
|
20
|
+
#
|
21
|
+
# @param [String] name Instrumentation package name
|
22
|
+
# @param [String] version Instrumentation package version
|
23
|
+
# @param [LoggerProvider] logger_provider The {LoggerProvider} that
|
24
|
+
# initialized the logger
|
25
|
+
#
|
26
|
+
# @return [OpenTelemetry::SDK::Logs::Logger]
|
27
|
+
def initialize(name, version, logger_provider)
|
28
|
+
@instrumentation_scope = ::OpenTelemetry::SDK::InstrumentationScope.new(name, version)
|
29
|
+
@logger_provider = logger_provider
|
30
|
+
end
|
31
|
+
|
32
|
+
# Emit a {LogRecord} to the processing pipeline.
|
33
|
+
#
|
34
|
+
# @param [optional Time] timestamp Time when the event occurred.
|
35
|
+
# @param [optional Time] observed_timestamp Time when the event was
|
36
|
+
# observed by the collection system.
|
37
|
+
# @param [optional OpenTelemetry::Trace::SpanContext] span_context The
|
38
|
+
# OpenTelemetry::Trace::SpanContext to associate with the
|
39
|
+
# {LogRecord}.
|
40
|
+
# @param severity_number [optional Integer] Numerical value of the
|
41
|
+
# severity. Smaller numerical values correspond to less severe events
|
42
|
+
# (such as debug events), larger numerical values correspond to more
|
43
|
+
# severe events (such as errors and critical events).
|
44
|
+
# @param [optional String, Numeric, Boolean, Array<String, Numeric,
|
45
|
+
# Boolean>, Hash{String => String, Numeric, Boolean, Array<String,
|
46
|
+
# Numeric, Boolean>}] body A value containing the body of the log record.
|
47
|
+
# @param [optional Hash{String => String, Numeric, Boolean,
|
48
|
+
# Array<String, Numeric, Boolean>}] attributes Additional information
|
49
|
+
# about the event.
|
50
|
+
# @param [optional String (16-byte binary)] trace_id Request trace id as
|
51
|
+
# defined in {https://www.w3.org/TR/trace-context/#trace-id W3C Trace Context}.
|
52
|
+
# Can be set for logs that are part of request processing and have an
|
53
|
+
# assigned trace id.
|
54
|
+
# @param [optional String (8-byte binary)] span_id Span id. Can be set
|
55
|
+
# for logs that are part of a particular processing span. If span_id
|
56
|
+
# is present trace_id should also be present.
|
57
|
+
# @param [optional Integer (8-bit byte of bit flags)] trace_flags Trace
|
58
|
+
# flag as defined in {https://www.w3.org/TR/trace-context/#trace-flags W3C Trace Context}
|
59
|
+
# specification. At the time of writing the specification defines one
|
60
|
+
# flag - the SAMPLED flag.
|
61
|
+
# @param [optional OpenTelemetry::Context] context The OpenTelemetry::Context
|
62
|
+
# to associate with the {LogRecord}.
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
def on_emit(timestamp: nil,
|
66
|
+
observed_timestamp: Time.now,
|
67
|
+
severity_text: nil,
|
68
|
+
severity_number: nil,
|
69
|
+
body: nil,
|
70
|
+
attributes: nil,
|
71
|
+
trace_id: nil,
|
72
|
+
span_id: nil,
|
73
|
+
trace_flags: nil,
|
74
|
+
context: ::OpenTelemetry::Context.current)
|
75
|
+
|
76
|
+
@logger_provider.on_emit(timestamp: timestamp,
|
77
|
+
observed_timestamp: observed_timestamp,
|
78
|
+
severity_text: severity_text,
|
79
|
+
severity_number: severity_number,
|
80
|
+
body: body,
|
81
|
+
attributes: attributes,
|
82
|
+
trace_id: nil,
|
83
|
+
span_id: nil,
|
84
|
+
trace_flags: nil,
|
85
|
+
instrumentation_scope: @instrumentation_scope,
|
86
|
+
context: context)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module ScoutApm
|
8
|
+
module Logging
|
9
|
+
module Loggers
|
10
|
+
module OpenTelemetry
|
11
|
+
module SDK
|
12
|
+
module Logs
|
13
|
+
# The SDK implementation of OpenTelemetry::Logs::LoggerProvider.
|
14
|
+
class LoggerProvider < OpenTelemetry::Logs::LoggerProvider
|
15
|
+
UNEXPECTED_ERROR_MESSAGE = 'unexpected error in ' \
|
16
|
+
'OpenTelemetry::SDK::Logs::LoggerProvider#%s'
|
17
|
+
|
18
|
+
private_constant :UNEXPECTED_ERROR_MESSAGE
|
19
|
+
|
20
|
+
# Returns a new LoggerProvider instance.
|
21
|
+
#
|
22
|
+
# @param [optional Resource] resource The resource to associate with
|
23
|
+
# new LogRecords created by {Logger}s created by this LoggerProvider.
|
24
|
+
#
|
25
|
+
# @return [OpenTelemetry::SDK::Logs::LoggerProvider]
|
26
|
+
def initialize(resource: OpenTelemetry::SDK::Resources::Resource.create)
|
27
|
+
@log_record_processors = []
|
28
|
+
@mutex = Mutex.new
|
29
|
+
@resource = resource
|
30
|
+
@stopped = false
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns an {OpenTelemetry::SDK::Logs::Logger} instance.
|
34
|
+
#
|
35
|
+
# @param [String] name Instrumentation package name
|
36
|
+
# @param [optional String] version Instrumentation package version
|
37
|
+
#
|
38
|
+
# @return [OpenTelemetry::SDK::Logs::Logger]
|
39
|
+
def logger(name:, version: nil)
|
40
|
+
version ||= ''
|
41
|
+
|
42
|
+
if !name.is_a?(String) || name.empty?
|
43
|
+
OpenTelemetry.logger.warn('LoggerProvider#logger called with an ' \
|
44
|
+
"invalid name. Name provided: #{name.inspect}")
|
45
|
+
end
|
46
|
+
|
47
|
+
Logger.new(name, version, self)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Adds a new log record processor to this LoggerProvider's
|
51
|
+
# log_record_processors.
|
52
|
+
#
|
53
|
+
# @param [LogRecordProcessor] log_record_processor The
|
54
|
+
# {LogRecordProcessor} to add to this LoggerProvider.
|
55
|
+
def add_log_record_processor(log_record_processor)
|
56
|
+
@mutex.synchronize do
|
57
|
+
if @stopped
|
58
|
+
OpenTelemetry.logger.warn('calling LoggerProvider#' \
|
59
|
+
'add_log_record_processor after shutdown.')
|
60
|
+
return
|
61
|
+
end
|
62
|
+
@log_record_processors = @log_record_processors.dup.push(log_record_processor)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Attempts to stop all the activity for this LoggerProvider. Calls
|
67
|
+
# {LogRecordProcessor#shutdown} for all registered {LogRecordProcessor}s.
|
68
|
+
#
|
69
|
+
# This operation may block until all log records are processed. Must
|
70
|
+
# be called before turning off the main application to ensure all data
|
71
|
+
# are processed and exported.
|
72
|
+
#
|
73
|
+
# After this is called all newly created {LogRecord}s will be no-op.
|
74
|
+
#
|
75
|
+
# @param [optional Numeric] timeout An optional timeout in seconds.
|
76
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
77
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
78
|
+
def shutdown(timeout: nil)
|
79
|
+
@mutex.synchronize do
|
80
|
+
if @stopped
|
81
|
+
OpenTelemetry.logger.warn('LoggerProvider#shutdown called multiple times.')
|
82
|
+
return Export::FAILURE
|
83
|
+
end
|
84
|
+
|
85
|
+
start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
|
86
|
+
results = @log_record_processors.map do |processor|
|
87
|
+
remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
|
88
|
+
break [Export::TIMEOUT] if remaining_timeout&.zero?
|
89
|
+
|
90
|
+
processor.shutdown(timeout: remaining_timeout)
|
91
|
+
end
|
92
|
+
|
93
|
+
@stopped = true
|
94
|
+
results.max || Export::SUCCESS
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Immediately export all {LogRecord}s that have not yet been exported
|
99
|
+
# for all the registered {LogRecordProcessor}s.
|
100
|
+
#
|
101
|
+
# This method should only be called in cases where it is absolutely
|
102
|
+
# necessary, such as when using some FaaS providers that may suspend
|
103
|
+
# the process after an invocation, but before the {LogRecordProcessor}
|
104
|
+
# exports the completed {LogRecord}s.
|
105
|
+
#
|
106
|
+
# @param [optional Numeric] timeout An optional timeout in seconds.
|
107
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
108
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
109
|
+
def force_flush(timeout: nil)
|
110
|
+
@mutex.synchronize do
|
111
|
+
return Export::SUCCESS if @stopped
|
112
|
+
|
113
|
+
start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
|
114
|
+
results = @log_record_processors.map do |processor|
|
115
|
+
remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
|
116
|
+
return Export::TIMEOUT if remaining_timeout&.zero?
|
117
|
+
|
118
|
+
processor.force_flush(timeout: remaining_timeout)
|
119
|
+
end
|
120
|
+
|
121
|
+
results.max || Export::SUCCESS
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# @api private
|
126
|
+
def on_emit(timestamp: nil,
|
127
|
+
observed_timestamp: nil,
|
128
|
+
severity_text: nil,
|
129
|
+
severity_number: nil,
|
130
|
+
body: nil,
|
131
|
+
attributes: nil,
|
132
|
+
trace_id: nil,
|
133
|
+
span_id: nil,
|
134
|
+
trace_flags: nil,
|
135
|
+
instrumentation_scope: nil,
|
136
|
+
context: nil)
|
137
|
+
|
138
|
+
log_record = LogRecord.new(timestamp: timestamp,
|
139
|
+
observed_timestamp: observed_timestamp,
|
140
|
+
severity_text: severity_text,
|
141
|
+
severity_number: severity_number,
|
142
|
+
body: body,
|
143
|
+
attributes: attributes,
|
144
|
+
trace_id: trace_id,
|
145
|
+
span_id: span_id,
|
146
|
+
trace_flags: trace_flags,
|
147
|
+
resource: @resource,
|
148
|
+
instrumentation_scope: instrumentation_scope)
|
149
|
+
|
150
|
+
@log_record_processors.each { |processor| processor.on_emit(log_record, context) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
module ScoutApm
|
8
|
+
module Logging
|
9
|
+
module Loggers
|
10
|
+
module OpenTelemetry
|
11
|
+
module SDK
|
12
|
+
module Logs
|
13
|
+
# Current OpenTelemetry logs sdk version
|
14
|
+
VERSION = '0.1.0'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require_relative 'logs/version'
|
8
|
+
require_relative 'logs/logger'
|
9
|
+
require_relative 'logs/logger_provider'
|
10
|
+
require_relative 'logs/log_record'
|
11
|
+
require_relative 'logs/log_record_data'
|
12
|
+
require_relative 'logs/log_record_processor'
|
13
|
+
require_relative 'logs/export'
|
14
|
+
|
15
|
+
module ScoutApm
|
16
|
+
module Logging
|
17
|
+
module Loggers
|
18
|
+
module OpenTelemetry
|
19
|
+
module SDK
|
20
|
+
# The Logs module contains the OpenTelemetry logs reference
|
21
|
+
# implementation.
|
22
|
+
module Logs
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -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
|
@@ -4,9 +4,7 @@ module ScoutApm
|
|
4
4
|
module Logging
|
5
5
|
module Loggers
|
6
6
|
# Holds both the original application logger and the new one. Relays commands to both.
|
7
|
-
class Proxy
|
8
|
-
include ::Kernel
|
9
|
-
|
7
|
+
class Proxy
|
10
8
|
def self.create_with_loggers(*loggers)
|
11
9
|
new.tap do |proxy_logger|
|
12
10
|
loggers.each { |logger| proxy_logger.add_scout_loggers(logger) }
|
@@ -21,12 +19,19 @@ module ScoutApm
|
|
21
19
|
@loggers << logger
|
22
20
|
end
|
23
21
|
|
24
|
-
def remove_scout_loggers(logger)
|
22
|
+
def remove_scout_loggers!(logger)
|
25
23
|
@loggers.reject! { |inst_log| inst_log == logger }
|
26
24
|
|
27
25
|
@loggers
|
28
26
|
end
|
29
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
|
+
|
30
35
|
# We don't want other libraries to change the formatter of the logger we create.
|
31
36
|
def formatter=(formatter)
|
32
37
|
@loggers.first.formatter = formatter
|
@@ -38,8 +43,20 @@ module ScoutApm
|
|
38
43
|
@loggers.first.level = level
|
39
44
|
end
|
40
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
|
+
|
41
58
|
def class
|
42
|
-
|
59
|
+
@loggers.first.class
|
43
60
|
end
|
44
61
|
|
45
62
|
def is_scout_proxy_logger?
|
@@ -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,18 +39,8 @@ module ScoutApm
|
|
37
39
|
@new_file_logger ||= Loggers::Logger.new(context, log_instance).create_logger!
|
38
40
|
end
|
39
41
|
|
40
|
-
|
41
|
-
|
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
45
|
next if ::ActiveSupport::Logger.respond_to?(:logger_outputs_to?) && ::ActiveSupport::Logger.logger_outputs_to?(
|
54
46
|
logger, $stdout, $stderr
|
@@ -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
|
-
|
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
|
-
|
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
|
@@ -12,75 +12,6 @@ module ScoutApm
|
|
12
12
|
|
13
13
|
FileUtils.mkdir_p(file_path) unless File.directory?(file_path)
|
14
14
|
end
|
15
|
-
|
16
|
-
# TODO: Add support for other platforms
|
17
|
-
def self.get_architecture
|
18
|
-
if /arm/ =~ RbConfig::CONFIG['arch']
|
19
|
-
'arm64'
|
20
|
-
else
|
21
|
-
'amd64'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.get_host_os
|
26
|
-
if /darwin|mac os/ =~ RbConfig::CONFIG['host_os']
|
27
|
-
'darwin'
|
28
|
-
else
|
29
|
-
'linux'
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.check_process_liveliness(pid, name)
|
34
|
-
# Pipe to cat to prevent truncation of the output
|
35
|
-
process_information = `ps -p #{pid} -o pid=,stat=,command= | cat`
|
36
|
-
return false if process_information.empty?
|
37
|
-
|
38
|
-
process_information_parts = process_information.split(' ')
|
39
|
-
process_information_status = process_information_parts[1]
|
40
|
-
|
41
|
-
return false if process_information_status == 'Z'
|
42
|
-
return false unless process_information.include?(name)
|
43
|
-
|
44
|
-
true
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.current_process_is_app_server?
|
48
|
-
# TODO: Add more app servers.
|
49
|
-
process_command = `ps -p #{Process.pid} -o command= | cat`.downcase
|
50
|
-
[
|
51
|
-
process_command.include?('puma'),
|
52
|
-
process_command.include?('unicorn'),
|
53
|
-
process_command.include?('passenger')
|
54
|
-
].any?
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.skip_setup?
|
58
|
-
[
|
59
|
-
ARGV.include?('assets:precompile'),
|
60
|
-
ARGV.include?('assets:clean'),
|
61
|
-
(defined?(::Rails::Console) && $stdout.isatty && $stdin.isatty)
|
62
|
-
].any?
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.attempt_exclusive_lock(context)
|
66
|
-
lock_file = context.config.value('manager_lock_file')
|
67
|
-
ensure_directory_exists(lock_file)
|
68
|
-
|
69
|
-
begin
|
70
|
-
file = File.open(lock_file, File::RDWR | File::CREAT | File::EXCL)
|
71
|
-
rescue Errno::EEXIST
|
72
|
-
context.logger.info('Manager lock file held, continuing.')
|
73
|
-
return
|
74
|
-
end
|
75
|
-
|
76
|
-
# Ensure the lock file is deleted when the block completes
|
77
|
-
begin
|
78
|
-
yield
|
79
|
-
ensure
|
80
|
-
file.close
|
81
|
-
File.delete(lock_file) if File.exist?(lock_file)
|
82
|
-
end
|
83
|
-
end
|
84
15
|
end
|
85
16
|
end
|
86
17
|
end
|
data/lib/scout_apm_logging.rb
CHANGED
@@ -6,28 +6,19 @@ require 'scout_apm/logging/config'
|
|
6
6
|
require 'scout_apm/logging/logger'
|
7
7
|
require 'scout_apm/logging/context'
|
8
8
|
require 'scout_apm/logging/utils'
|
9
|
-
require 'scout_apm/logging/state'
|
10
|
-
|
11
9
|
require 'scout_apm/logging/loggers/capture'
|
12
10
|
|
13
|
-
require 'scout_apm/logging/monitor_manager/manager'
|
14
|
-
|
15
11
|
module ScoutApm
|
16
12
|
## This module is responsible for setting up monitoring of the application's logs.
|
17
13
|
module Logging
|
18
14
|
if defined?(Rails) && defined?(Rails::Railtie)
|
19
15
|
# If we are in a Rails environment, setup the monitor daemon manager.
|
20
16
|
class RailTie < ::Rails::Railtie
|
21
|
-
initializer 'scout_apm_logging.monitor' do
|
22
|
-
context =
|
17
|
+
initializer 'scout_apm_logging.monitor', after: :initialize_logger, before: :initialize_cache do
|
18
|
+
context = Context.new
|
19
|
+
context.config = Config.with_file(context, context.config.value('config_file'))
|
23
20
|
|
24
21
|
Loggers::Capture.new(context).setup!
|
25
|
-
|
26
|
-
unless Utils.skip_setup?
|
27
|
-
Utils.attempt_exclusive_lock(context) do
|
28
|
-
ScoutApm::Logging::MonitorManager.instance.setup!
|
29
|
-
end
|
30
|
-
end
|
31
22
|
end
|
32
23
|
end
|
33
24
|
end
|
data/scout_apm_logging.gemspec
CHANGED
@@ -17,9 +17,16 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.required_ruby_version = '>= 2.6'
|
19
19
|
|
20
|
+
s.add_dependency 'googleapis-common-protos-types'
|
21
|
+
s.add_dependency 'google-protobuf', '< 3.18'
|
22
|
+
s.add_dependency 'opentelemetry-api'
|
23
|
+
s.add_dependency 'opentelemetry-common'
|
24
|
+
s.add_dependency 'opentelemetry-instrumentation-base'
|
25
|
+
s.add_dependency 'opentelemetry-sdk', '>= 1.2'
|
20
26
|
s.add_dependency 'scout_apm'
|
21
27
|
|
22
28
|
s.add_development_dependency 'rspec'
|
23
29
|
s.add_development_dependency 'rubocop', '1.50.2'
|
24
30
|
s.add_development_dependency 'rubocop-ast', '1.30.0'
|
31
|
+
s.add_development_dependency 'webmock'
|
25
32
|
end
|
data/spec/data/config_test_1.yml
CHANGED
data/spec/data/mock_config.yml
CHANGED
@@ -9,9 +9,6 @@ common: &defaults
|
|
9
9
|
###
|
10
10
|
logs_monitor: true
|
11
11
|
logs_ingest_key: "00001000010000abc"
|
12
|
-
logs_monitored: ["/tmp/fake_log_file.log"]
|
13
|
-
# Need to give a high enough number for the original health check to pass
|
14
|
-
monitor_interval: 10
|
15
12
|
|
16
13
|
production:
|
17
14
|
<<: *defaults
|