scout_apm_logging 0.0.13 → 1.0.1

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -4
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +6 -0
  5. data/NOTICE +4 -0
  6. data/lib/scout_apm/logging/config.rb +5 -131
  7. data/lib/scout_apm/logging/loggers/capture.rb +3 -2
  8. data/lib/scout_apm/logging/loggers/formatter.rb +21 -2
  9. data/lib/scout_apm/logging/loggers/opentelemetry/LICENSE +201 -0
  10. data/lib/scout_apm/logging/loggers/opentelemetry/NOTICE +9 -0
  11. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/log_record.rb +18 -0
  12. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/logger.rb +64 -0
  13. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/logger_provider.rb +31 -0
  14. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/severity_number.rb +43 -0
  15. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs/version.rb +18 -0
  16. data/lib/scout_apm/logging/loggers/opentelemetry/api/logs.rb +28 -0
  17. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/exporter/otlp/logs_exporter.rb +389 -0
  18. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/exporter/otlp/version.rb +20 -0
  19. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/collector/logs/v1/logs_service_pb.rb +43 -0
  20. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/common/v1/common_pb.rb +58 -0
  21. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/logs/v1/logs_pb.rb +91 -0
  22. data/lib/scout_apm/logging/loggers/opentelemetry/exporter/proto/resource/v1/resource_pb.rb +33 -0
  23. data/lib/scout_apm/logging/loggers/opentelemetry/opentelemetry.rb +62 -0
  24. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export/batch_log_record_processor.rb +225 -0
  25. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export/log_record_exporter.rb +64 -0
  26. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/export.rb +34 -0
  27. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record.rb +115 -0
  28. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record_data.rb +31 -0
  29. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/log_record_processor.rb +53 -0
  30. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/logger.rb +94 -0
  31. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/logger_provider.rb +158 -0
  32. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs/version.rb +20 -0
  33. data/lib/scout_apm/logging/loggers/opentelemetry/sdk/logs.rb +28 -0
  34. data/lib/scout_apm/logging/utils.rb +0 -69
  35. data/lib/scout_apm/logging/version.rb +1 -1
  36. data/lib/scout_apm_logging.rb +2 -11
  37. data/scout_apm_logging.gemspec +7 -0
  38. data/spec/data/config_test_1.yml +0 -1
  39. data/spec/data/mock_config.yml +0 -3
  40. data/spec/integration/rails/lifecycle_spec.rb +57 -23
  41. data/spec/spec_helper.rb +0 -12
  42. data/spec/unit/config_spec.rb +0 -12
  43. data/spec/unit/loggers/capture_spec.rb +0 -6
  44. metadata +126 -39
  45. data/bin/scout_apm_logging_monitor +0 -6
  46. data/lib/scout_apm/logging/monitor/_rails.rb +0 -22
  47. data/lib/scout_apm/logging/monitor/collector/checksum.rb +0 -51
  48. data/lib/scout_apm/logging/monitor/collector/configuration.rb +0 -150
  49. data/lib/scout_apm/logging/monitor/collector/downloader.rb +0 -78
  50. data/lib/scout_apm/logging/monitor/collector/extractor.rb +0 -37
  51. data/lib/scout_apm/logging/monitor/collector/manager.rb +0 -57
  52. data/lib/scout_apm/logging/monitor/monitor.rb +0 -216
  53. data/lib/scout_apm/logging/monitor_manager/manager.rb +0 -162
  54. data/lib/scout_apm/logging/state.rb +0 -69
  55. data/spec/data/empty_logs_config.yml +0 -0
  56. data/spec/data/logs_config.yml +0 -3
  57. data/spec/data/state_file.json +0 -3
  58. data/spec/integration/loggers/capture_spec.rb +0 -68
  59. data/spec/integration/monitor/collector/downloader/will_verify_checksum.rb +0 -49
  60. data/spec/integration/monitor/collector_healthcheck_spec.rb +0 -29
  61. data/spec/integration/monitor/continuous_state_collector_spec.rb +0 -31
  62. data/spec/integration/monitor/previous_collector_setup_spec.rb +0 -45
  63. data/spec/integration/monitor_manager/disable_agent_spec.rb +0 -30
  64. data/spec/integration/monitor_manager/monitor_pid_file_spec.rb +0 -38
  65. data/spec/integration/monitor_manager/single_monitor_spec.rb +0 -53
  66. data/spec/unit/monitor/collector/configuration_spec.rb +0 -64
  67. data/spec/unit/state_spec.rb +0 -20
  68. data/tooling/checksums.rb +0 -106
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: opentelemetry/proto/resource/v1/resource.proto
5
+
6
+ require 'google/protobuf'
7
+
8
+ require_relative '../../common/v1/common_pb'
9
+
10
+ Google::Protobuf::DescriptorPool.generated_pool.build do
11
+ add_file("scout/opentelemetry/proto/resource/v1/resource.proto", :syntax => :proto3) do
12
+ add_message "scout_apm.logging.loggers.opentelemetry.proto.resource.v1.Resource" do
13
+ repeated :attributes, :message, 1, "scout_apm.logging.loggers.opentelemetry.proto.common.v1.KeyValue"
14
+ optional :dropped_attributes_count, :uint32, 2
15
+ end
16
+ end
17
+ end
18
+
19
+ module ScoutApm
20
+ module Logging
21
+ module Loggers
22
+ module Opentelemetry
23
+ module Proto
24
+ module Resource
25
+ module V1
26
+ Resource = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("scout_apm.logging.loggers.opentelemetry.proto.resource.v1.Resource").msgclass
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+ require 'opentelemetry'
4
+ require 'opentelemetry/sdk'
5
+
6
+ require_relative 'api/logs'
7
+ require_relative 'sdk/logs'
8
+ require_relative 'exporter/exporter/otlp/version'
9
+ require_relative 'exporter/exporter/otlp/logs_exporter'
10
+
11
+ module ScoutApm
12
+ module Logging
13
+ module Loggers
14
+ module OpenTelemetry
15
+ class << self
16
+ # Overwritten on setup to be the internal logger.
17
+ # @return [Object, Logger] configured Logger or a default STDOUT Logger.
18
+ def logger
19
+ @logger ||= ::Logger.new($stdout, level: ENV['OTEL_LOG_LEVEL'] || ::Logger::INFO)
20
+ end
21
+
22
+ # @return [Callable] configured error handler or a default that logs the
23
+ # exception and message at ERROR level.
24
+ def error_handler
25
+ @error_handler ||= ->(exception: nil, message: nil) { logger.error("OpenTelemetry error: #{[message, exception&.message, exception&.backtrace&.first].compact.join(' - ')}") }
26
+ end
27
+
28
+ # Handles an error by calling the configured error_handler.
29
+ #
30
+ # @param [optional Exception] exception The exception to be handled
31
+ # @param [optional String] message An error message.
32
+ def handle_error(exception: nil, message: nil)
33
+ error_handler.call(exception: exception, message: message)
34
+ end
35
+
36
+ def logger_provider=(logger_provider)
37
+ @logger_provider = logger_provider
38
+ end
39
+
40
+ def logger_provider
41
+ @logger_provider
42
+ end
43
+ end
44
+
45
+ def self.setup(context)
46
+ @logger = context.logger
47
+
48
+ exporter = OpenTelemetry::Exporter::OTLP::LogsExporter.new(endpoint: context.config.value('logs_reporting_endpoint_http'))
49
+ processor = OpenTelemetry::SDK::Logs::Export::BatchLogRecordProcessor.new(exporter)
50
+ ScoutApm::Logging::Loggers::OpenTelemetry.logger_provider = OpenTelemetry::SDK::Logs::LoggerProvider.new(resource: scout_resource(context))
51
+ ScoutApm::Logging::Loggers::OpenTelemetry.logger_provider.add_log_record_processor(processor)
52
+ end
53
+
54
+ def self.scout_resource(context)
55
+ our_resources = ::OpenTelemetry::SDK::Resources::Resource.create({'telemetryhub.key' => context.config.value('logs_ingest_key')})
56
+ default_resources = ::OpenTelemetry::SDK::Resources::Resource.default
57
+ default_resources.merge(our_resources)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,225 @@
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
+ module Export
14
+ # WARNING - The spec has some differences from the LogRecord version of this processor
15
+ # Implementation of the duck type LogRecordProcessor that batches
16
+ # log records exported by the SDK then pushes them to the exporter
17
+ # pipeline.
18
+ #
19
+ # Typically, the BatchLogRecordProcessor will be more suitable for
20
+ # production environments than the SimpleLogRecordProcessor.
21
+ class BatchLogRecordProcessor < LogRecordProcessor # rubocop:disable Metrics/ClassLength
22
+ # Returns a new instance of the {BatchLogRecordProcessor}.
23
+ #
24
+ # @param [LogRecordExporter] exporter The (duck type) LogRecordExporter to where the
25
+ # recorded LogRecords are pushed after batching.
26
+ # @param [Numeric] exporter_timeout The maximum allowed time to export data.
27
+ # Defaults to the value of the OTEL_BLRP_EXPORT_TIMEOUT
28
+ # environment variable, if set, or 30,000 (30 seconds).
29
+ # @param [Numeric] schedule_delay the delay interval between two consecutive exports.
30
+ # Defaults to the value of the OTEL_BLRP_SCHEDULE_DELAY environment
31
+ # variable, if set, or 1,000 (1 second).
32
+ # @param [Integer] max_queue_size the maximum queue size in log records.
33
+ # Defaults to the value of the OTEL_BLRP_MAX_QUEUE_SIZE environment
34
+ # variable, if set, or 2048.
35
+ # @param [Integer] max_export_batch_size the maximum batch size in log records.
36
+ # Defaults to the value of the OTEL_BLRP_MAX_EXPORT_BATCH_SIZE environment
37
+ # variable, if set, or 512.
38
+ #
39
+ # @return a new instance of the {BatchLogRecordProcessor}.
40
+ def initialize(exporter,
41
+ exporter_timeout: Float(ENV.fetch('OTEL_BLRP_EXPORT_TIMEOUT', 30_000)),
42
+ schedule_delay: Float(ENV.fetch('OTEL_BLRP_SCHEDULE_DELAY', 1000)),
43
+ max_queue_size: Integer(ENV.fetch('OTEL_BLRP_MAX_QUEUE_SIZE', 2048)),
44
+ max_export_batch_size: Integer(ENV.fetch('OTEL_BLRP_MAX_EXPORT_BATCH_SIZE', 256)),
45
+ start_thread_on_boot: String(ENV['OTEL_RUBY_BLRP_START_THREAD_ON_BOOT']) !~ /false/i)
46
+
47
+ unless max_export_batch_size <= max_queue_size
48
+ raise ArgumentError,
49
+ 'max_export_batch_size much be less than or equal to max_queue_size'
50
+ end
51
+
52
+ unless ::OpenTelemetry::Common::Utilities.valid_exporter?(exporter)
53
+ raise ArgumentError,
54
+ "exporter #{exporter.inspect} does not appear to be a valid exporter"
55
+ end
56
+
57
+ @exporter = exporter
58
+ @exporter_timeout_seconds = exporter_timeout / 1000.0
59
+ @mutex = Mutex.new
60
+ @export_mutex = Mutex.new
61
+ @condition = ConditionVariable.new
62
+ @keep_running = true
63
+ @stopped = false
64
+ @delay_seconds = schedule_delay / 1000.0
65
+ @max_queue_size = max_queue_size
66
+ @batch_size = max_export_batch_size
67
+ @log_records = []
68
+ @pid = nil
69
+ @thread = nil
70
+ reset_on_fork(restart_thread: start_thread_on_boot)
71
+ end
72
+
73
+ # Adds a log record to the batch. Thread-safe; may block on lock.
74
+ def on_emit(log_record, _context)
75
+ return if @stopped
76
+
77
+ lock do
78
+ reset_on_fork
79
+ n = log_records.size + 1 - max_queue_size
80
+ if n.positive?
81
+ log_records.shift(n)
82
+ report_dropped_log_records(n, reason: 'buffer-full')
83
+ end
84
+ log_records << log_record
85
+ @condition.signal if log_records.size > batch_size
86
+ end
87
+ end
88
+
89
+ # Export all emitted log records that have not yet been exported to
90
+ # the configured `Exporter`.
91
+ #
92
+ # This method should only be called in cases where it is absolutely
93
+ # necessary, such as when using some FaaS providers that may suspend
94
+ # the process after an invocation, but before the `Processor` exports
95
+ # the completed log records.
96
+ #
97
+ # @param [optional Numeric] timeout An optional timeout in seconds.
98
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
99
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
100
+ def force_flush(timeout: nil)
101
+ start_time = ::OpenTelemetry::Common::Utilities.timeout_timestamp
102
+
103
+ snapshot = lock do
104
+ reset_on_fork if @keep_running
105
+ log_records.shift(log_records.size)
106
+ end
107
+
108
+ until snapshot.empty?
109
+ remaining_timeout = ::OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
110
+ return TIMEOUT if remaining_timeout&.zero?
111
+
112
+ batch = snapshot.shift(batch_size).map!(&:to_log_record_data)
113
+ result_code = export_batch(batch, timeout: remaining_timeout)
114
+ return result_code unless result_code == SUCCESS
115
+ end
116
+
117
+ @exporter.force_flush(timeout: ::OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
118
+ ensure
119
+ # Unshift the remaining log records if we timed out. We drop excess
120
+ # log records from the snapshot because they're older than any
121
+ # records in the buffer.
122
+ lock do
123
+ n = log_records.size + snapshot.size - max_queue_size
124
+
125
+ if n.positive?
126
+ snapshot.shift(n)
127
+ report_dropped_log_records(n, reason: 'buffer-full')
128
+ end
129
+
130
+ log_records.unshift(*snapshot) unless snapshot.empty?
131
+ @condition.signal if log_records.size > max_queue_size / 2
132
+ end
133
+ end
134
+
135
+ # Shuts the consumer thread down and flushes the current accumulated
136
+ # buffer will block until the thread is finished.
137
+ #
138
+ # @param [optional Numeric] timeout An optional timeout in seconds.
139
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
140
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
141
+ def shutdown(timeout: nil)
142
+ return if @stopped
143
+
144
+ start_time = ::OpenTelemetry::Common::Utilities.timeout_timestamp
145
+ thread = lock do
146
+ @keep_running = false
147
+ @stopped = true
148
+ @condition.signal
149
+ @thread
150
+ end
151
+
152
+ thread&.join(timeout)
153
+ force_flush(timeout: ::OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
154
+ dropped_log_records = lock { log_records.size }
155
+ report_dropped_log_records(dropped_log_records, reason: 'terminating') if dropped_log_records.positive?
156
+
157
+ @exporter.shutdown(timeout: ::OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
158
+ end
159
+
160
+ private
161
+
162
+ attr_reader :log_records, :max_queue_size, :batch_size
163
+
164
+ def work
165
+ loop do
166
+ batch = lock do
167
+ @condition.wait(@mutex, @delay_seconds) if log_records.size < batch_size && @keep_running
168
+ @condition.wait(@mutex, @delay_seconds) while log_records.empty? && @keep_running
169
+ return unless @keep_running
170
+
171
+ fetch_batch
172
+ end
173
+
174
+ export_batch(batch)
175
+ end
176
+ end
177
+
178
+ def reset_on_fork(restart_thread: true)
179
+ pid = Process.pid
180
+ return if @pid == pid
181
+
182
+ @pid = pid
183
+ log_records.clear
184
+ @thread = restart_thread ? Thread.new { work } : nil
185
+ rescue ThreadError => e
186
+ OpenTelemetry.handle_error(exception: e, message: 'unexpected error in BatchLogRecordProcessor#reset_on_fork')
187
+ end
188
+
189
+ def export_batch(batch, timeout: @exporter_timeout_seconds)
190
+ result_code = @export_mutex.synchronize { @exporter.export(batch, timeout: timeout) }
191
+ report_result(result_code, batch)
192
+ result_code
193
+ rescue StandardError => e
194
+ report_result(FAILURE, batch)
195
+ OpenTelemetry.handle_error(exception: e, message: 'unexpected error in BatchLogRecordProcessor#export_batch')
196
+ end
197
+
198
+ def report_result(result_code, batch)
199
+ if result_code == SUCCESS
200
+ OpenTelemetry.logger.debug("Successfully exported #{batch.size} log records")
201
+ else
202
+ OpenTelemetry.handle_error(exception: ExportError.new("Unable to export #{batch.size} log records"))
203
+ OpenTelemetry.logger.error("Result code: #{result_code}")
204
+ end
205
+ end
206
+
207
+ def report_dropped_log_records(count, reason:)
208
+ OpenTelemetry.logger.warn("#{count} log record(s) dropped. Reason: #{reason}")
209
+ end
210
+
211
+ def fetch_batch
212
+ log_records.shift(@batch_size).map!(&:to_log_record_data)
213
+ end
214
+
215
+ def lock(&block)
216
+ @mutex.synchronize(&block)
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,64 @@
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
+ module Export
14
+ # LogRecordExporter describes a duck type. It is not required to
15
+ # subclass this class to provide an implementation of LogRecordExporter,
16
+ # provided the interface is satisfied. LogRecordExporter allows
17
+ # different tracing services to export log record data in their own format.
18
+ #
19
+ # To export data an exporter MUST be registered to the {LoggerProvider}
20
+ # using a {LogRecordProcessor} implementation.
21
+ class LogRecordExporter
22
+ def initialize
23
+ @stopped = false
24
+ end
25
+
26
+ # Called to export {LogRecordData}s.
27
+ #
28
+ # @param [Enumerable<LogRecordData>] log_record_data the list of
29
+ # {LogRecordData} to be exported.
30
+ # @param [optional Numeric] timeout An optional timeout in seconds.
31
+ #
32
+ # @return [Integer] the result of the export.
33
+ def export(log_record_data, timeout: nil)
34
+ return SUCCESS unless @stopped
35
+
36
+ FAILURE
37
+ end
38
+
39
+ # Called when {LoggerProvider#force_flush} is called, if this exporter is
40
+ # registered to a {LoggerProvider} object.
41
+ #
42
+ # @param [optional Numeric] timeout An optional timeout in seconds.
43
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
44
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
45
+ def force_flush(timeout: nil)
46
+ SUCCESS
47
+ end
48
+
49
+ # Called when {LoggerProvider#shutdown} is called, if this exporter is
50
+ # registered to a {LoggerProvider} object.
51
+ #
52
+ # @param [optional Numeric] timeout An optional timeout in seconds.
53
+ def shutdown(timeout: nil)
54
+ @stopped = true
55
+ SUCCESS
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,34 @@
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 Export module contains the built-in exporters and log record
14
+ # processors for the OpenTelemetry reference implementation.
15
+ module Export
16
+ ExportError = Class.new(::OpenTelemetry::Error)
17
+ # The operation finished successfully.
18
+ SUCCESS = 0
19
+
20
+ # The operation finished with an error.
21
+ FAILURE = 1
22
+
23
+ # The operation timed out.
24
+ TIMEOUT = 2
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require_relative 'export/log_record_exporter'
34
+ require_relative 'export/batch_log_record_processor'
@@ -0,0 +1,115 @@
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
+ # Implementation of OpenTelemetry::Logs::LogRecord that records log events.
14
+ class LogRecord < OpenTelemetry::Logs::LogRecord
15
+ attr_accessor :timestamp,
16
+ :observed_timestamp,
17
+ :severity_text,
18
+ :severity_number,
19
+ :body,
20
+ :attributes,
21
+ :trace_id,
22
+ :span_id,
23
+ :trace_flags,
24
+ :resource,
25
+ :instrumentation_scope
26
+
27
+ # Creates a new {LogRecord}.
28
+ #
29
+ # @param [optional Time] timestamp Time when the event occurred.
30
+ # @param [optional Time] observed_timestamp Time when the event
31
+ # was observed by the collection system. If nil, will first attempt
32
+ # to set to `timestamp`. If `timestamp` is nil, will set to Time.now.
33
+ # @param [optional OpenTelemetry::Trace::SpanContext] span_context The
34
+ # OpenTelemetry::Trace::SpanContext to associate with the LogRecord.
35
+ # @param [optional String] severity_text The log severity, also known as
36
+ # log level.
37
+ # @param [optional Integer] severity_number The numerical value of the
38
+ # log severity.
39
+ # @param [optional String, Numeric, Boolean, Array<String, Numeric,
40
+ # Boolean>, Hash{String => String, Numeric, Boolean, Array<String,
41
+ # Numeric, Boolean>}] body The body of the {LogRecord}.
42
+ # @param [optional Hash{String => String, Numeric, Boolean,
43
+ # Array<String, Numeric, Boolean>}] attributes Attributes to associate
44
+ # with the {LogRecord}.
45
+ # @param [optional String] trace_id The trace ID associated with the
46
+ # current context.
47
+ # @param [optional String] span_id The span ID associated with the
48
+ # current context.
49
+ # @param [optional OpenTelemetry::Trace::TraceFlags] trace_flags The
50
+ # trace flags associated with the current context.
51
+ # @param [optional OpenTelemetry::SDK::Resources::Resource] resource The
52
+ # source of the log, desrived from the LoggerProvider.
53
+ # @param [optional OpenTelemetry::SDK::InstrumentationScope] instrumentation_scope
54
+ # The instrumentation scope, derived from the emitting Logger
55
+ #
56
+ #
57
+ # @return [LogRecord]
58
+ def initialize(
59
+ timestamp: nil,
60
+ observed_timestamp: nil,
61
+ severity_text: nil,
62
+ severity_number: nil,
63
+ body: nil,
64
+ attributes: nil,
65
+ trace_id: nil,
66
+ span_id: nil,
67
+ trace_flags: nil,
68
+ resource: nil,
69
+ instrumentation_scope: nil
70
+ )
71
+ @timestamp = timestamp
72
+ @observed_timestamp = observed_timestamp || timestamp || Time.now
73
+ @severity_text = severity_text
74
+ @severity_number = severity_number
75
+ @body = body
76
+ @attributes = attributes.nil? ? nil : Hash[attributes] # We need a mutable copy of attributes
77
+ @trace_id = trace_id
78
+ @span_id = span_id
79
+ @trace_flags = trace_flags
80
+ @resource = resource
81
+ @instrumentation_scope = instrumentation_scope
82
+ @total_recorded_attributes = @attributes&.size || 0
83
+ end
84
+
85
+ def to_log_record_data
86
+ LogRecordData.new(
87
+ to_integer_nanoseconds(@timestamp),
88
+ to_integer_nanoseconds(@observed_timestamp),
89
+ @severity_text,
90
+ @severity_number,
91
+ @body,
92
+ @attributes,
93
+ @trace_id,
94
+ @span_id,
95
+ @trace_flags,
96
+ @resource,
97
+ @instrumentation_scope,
98
+ @total_recorded_attributes
99
+ )
100
+ end
101
+
102
+ private
103
+
104
+ def to_integer_nanoseconds(timestamp)
105
+ return unless timestamp.is_a?(Time)
106
+
107
+ (timestamp.to_r * 10**9).to_i
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,31 @@
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
+ # LogRecordData is a Struct containing {LogRecord} data for export.
14
+ LogRecordData = Struct.new(:timestamp, # optional Integer nanoseconds since Epoch
15
+ :observed_timestamp, # Integer nanoseconds since Epoch
16
+ :severity_text, # optional String
17
+ :severity_number, # optional Integer
18
+ :body, # optional String, Numeric, Boolean, Array<String, Numeric, Boolean>, Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}
19
+ :attributes, # optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}
20
+ :trace_id, # optional String (16-byte binary)
21
+ :span_id, # optional String (8-byte binary)
22
+ :trace_flags, # optional Integer (8-bit byte of bit flags)
23
+ :resource, # optional OpenTelemetry::SDK::Resources::Resource
24
+ :instrumentation_scope, # optional OpenTelemetry::SDK::InstrumentationScope
25
+ :total_recorded_attributes) # Integer
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -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