scout_apm_logging 0.0.13 → 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 +3 -0
- data/NOTICE +4 -0
- data/lib/scout_apm/logging/config.rb +5 -131
- data/lib/scout_apm/logging/loggers/capture.rb +3 -2
- 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/utils.rb +0 -69
- data/lib/scout_apm/logging/version.rb +1 -1
- data/lib/scout_apm_logging.rb +2 -11
- 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 +126 -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
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require_relative '../../../lib/scout_apm/logging/monitor/collector/manager'
|
4
|
-
|
5
|
-
describe ScoutApm::Logging::Collector::Manager do
|
6
|
-
it 'If monitor is false, it should remove the daemon and collector process if they are present' do
|
7
|
-
ENV['SCOUT_LOGS_MONITOR'] = 'true'
|
8
|
-
ENV['SCOUT_LOGS_MONITORED'] = '["/tmp/test.log"]'
|
9
|
-
|
10
|
-
expect(`pgrep otelcol-contrib --runstates D,R,S`).to be_empty
|
11
|
-
|
12
|
-
ScoutApm::Logging::MonitorManager.instance.context.logger.info "Time start: #{Time.now}"
|
13
|
-
ScoutApm::Logging::MonitorManager.instance.setup!
|
14
|
-
ScoutApm::Logging::MonitorManager.instance.context.logger.info "Time after setup: #{Time.now}"
|
15
|
-
|
16
|
-
wait_for_process_with_timeout!('otelcol-contrib', 20)
|
17
|
-
|
18
|
-
ENV['SCOUT_LOGS_MONITOR'] = 'false'
|
19
|
-
|
20
|
-
ScoutApm::Logging::MonitorManager.new.setup!
|
21
|
-
|
22
|
-
sleep 5 # Give the process time to exit
|
23
|
-
|
24
|
-
expect(File.exist?(ScoutApm::Logging::MonitorManager.instance.context.config.value('monitor_pid_file'))).to be_falsey
|
25
|
-
expect(`pgrep otelcol-contrib --runstates D,R,S`).to be_empty
|
26
|
-
expect(`pgrep scout_apm_log_monitor --runstates D,R,S`).to be_empty
|
27
|
-
|
28
|
-
ENV.delete('SCOUT_LOGS_MONITOR')
|
29
|
-
end
|
30
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require_relative '../../../lib/scout_apm/logging/monitor/collector/manager'
|
4
|
-
|
5
|
-
describe ScoutApm::Logging::Collector::Manager do
|
6
|
-
it 'should recreate the monitor process if monitor.pid file is errant' do
|
7
|
-
ENV['SCOUT_LOGS_MONITOR'] = 'true'
|
8
|
-
ENV['SCOUT_LOGS_MONITORED'] = '["/tmp/test.log"]'
|
9
|
-
|
10
|
-
ScoutApm::Logging::Utils.ensure_directory_exists('/tmp/scout_apm/scout_apm_log_monitor.pid')
|
11
|
-
|
12
|
-
# A high enough number to not be a PID of a running process
|
13
|
-
pid_file_path = '/tmp/scout_apm/scout_apm_log_monitor.pid'
|
14
|
-
File.open(pid_file_path, 'w') do |file|
|
15
|
-
file.write('123456')
|
16
|
-
end
|
17
|
-
|
18
|
-
ScoutApm::Logging::MonitorManager.instance.context.logger.info "Time start: #{Time.now}"
|
19
|
-
ScoutApm::Logging::MonitorManager.instance.setup!
|
20
|
-
ScoutApm::Logging::MonitorManager.instance.context.logger.info "Time after setup: #{Time.now}"
|
21
|
-
|
22
|
-
# Give the process time to initialize, download the collector, and start it
|
23
|
-
wait_for_process_with_timeout!('otelcol-contrib', 20)
|
24
|
-
|
25
|
-
new_pid = File.read(pid_file_path).to_i
|
26
|
-
|
27
|
-
expect(new_pid).not_to eq(12_345)
|
28
|
-
|
29
|
-
# Check if the process with the stored PID is running
|
30
|
-
expect(Process.kill(0, new_pid)).to be_truthy
|
31
|
-
ENV.delete('SCOUT_LOGS_MONITOR')
|
32
|
-
|
33
|
-
# Kill the process and ensure PID file clean up
|
34
|
-
Process.kill('TERM', new_pid)
|
35
|
-
Process.kill('TERM', `pgrep otelcol-contrib --runstates D,R,S`.to_i)
|
36
|
-
sleep 1 # Give the process time to exit
|
37
|
-
end
|
38
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# This is really meant to simulate multiple processes calling the MonitorManager setup.
|
2
|
-
# Trying to create **multiple fake** rails environments is a bit challening
|
3
|
-
# (such as a rails app and a couple rails runners).
|
4
|
-
|
5
|
-
# See: https://github.com/rails/rails/blob/6d126e03dbbf5d30fa97b580f7dee46343537b7b/railties/test/isolation/abstract_unit.rb#L339
|
6
|
-
|
7
|
-
# We simulate the ultimate outcome here -- ie Railtie invoking the setup.
|
8
|
-
require 'spec_helper'
|
9
|
-
|
10
|
-
describe ScoutApm::Logging do
|
11
|
-
it 'Should only create a single monitor daemon if manager is called multiple times' do
|
12
|
-
ENV['SCOUT_LOGS_MONITOR'] = 'true'
|
13
|
-
ENV['SCOUT_LOGS_MONITORED'] = '["/tmp/test.log"]'
|
14
|
-
|
15
|
-
pid_file = ScoutApm::Logging::MonitorManager.instance.context.config.value('monitor_pid_file')
|
16
|
-
expect(File.exist?(pid_file)).to be_falsey
|
17
|
-
|
18
|
-
context = ScoutApm::Logging::MonitorManager.instance.context
|
19
|
-
|
20
|
-
pids = 3.times.map do
|
21
|
-
fork do
|
22
|
-
puts 'fork attempting to gain lock'
|
23
|
-
ScoutApm::Logging::Utils.attempt_exclusive_lock(context) do
|
24
|
-
puts 'obtained lock'
|
25
|
-
ScoutApm::Logging::MonitorManager.new.setup!
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
pids.each { |pid| Process.wait(pid) }
|
31
|
-
|
32
|
-
wait_for_process_with_timeout!('otelcol-contrib', 20)
|
33
|
-
|
34
|
-
# The file lock really should be gone at this point.
|
35
|
-
expect(File.exist?(context.config.value('manager_lock_file'))).to be_falsey
|
36
|
-
expect(File.exist?(pid_file)).to be_truthy
|
37
|
-
|
38
|
-
original_pid = File.read(pid_file).to_i
|
39
|
-
expect(ScoutApm::Logging::Utils.check_process_liveliness(original_pid, 'scout_apm_logging_monitor')).to be_truthy
|
40
|
-
|
41
|
-
# Another process comes in and tries to start it again
|
42
|
-
ScoutApm::Logging::Utils.attempt_exclusive_lock(context) do
|
43
|
-
puts 'obtained lock later on'
|
44
|
-
ScoutApm::Logging::MonitorManager.new.setup!
|
45
|
-
end
|
46
|
-
|
47
|
-
expect(File.exist?(context.config.value('manager_lock_file'))).to be_falsey
|
48
|
-
expect(File.exist?(pid_file)).to be_truthy
|
49
|
-
updated_pid = File.read(pid_file).to_i
|
50
|
-
expect(updated_pid).to eq(original_pid)
|
51
|
-
expect(ScoutApm::Logging::Utils.check_process_liveliness(original_pid, 'scout_apm_logging_monitor')).to be_truthy
|
52
|
-
end
|
53
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
require_relative '../../../../lib/scout_apm/logging/monitor/collector/configuration'
|
6
|
-
|
7
|
-
describe ScoutApm::Logging::Collector::Configuration do
|
8
|
-
it 'creates the correct configuration for the otelcol' do
|
9
|
-
context = ScoutApm::Logging::Context.new
|
10
|
-
setup_collector_config!(context)
|
11
|
-
|
12
|
-
expect(File.exist?(context.config.value('collector_config_file'))).to be_truthy
|
13
|
-
config = YAML.load_file(context.config.value('collector_config_file'))
|
14
|
-
|
15
|
-
expect(config['exporters']['otlp']['endpoint']).to eq('https://otlp.scoutotel.com:4317')
|
16
|
-
expect(config['exporters']['otlp']['headers']['x-telemetryhub-key']).to eq('00001000010000abc')
|
17
|
-
expect(config['receivers']['filelog']['include']).to eq(['/tmp/fake_log_file.log'])
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'merges in a logs config correctly' do
|
21
|
-
ENV['SCOUT_LOGS_CONFIG'] = File.expand_path('../../../data/logs_config.yml', __dir__)
|
22
|
-
|
23
|
-
context = ScoutApm::Logging::Context.new
|
24
|
-
setup_collector_config!(context)
|
25
|
-
|
26
|
-
expect(File.exist?(context.config.value('collector_config_file'))).to be_truthy
|
27
|
-
config = YAML.load_file(context.config.value('collector_config_file'))
|
28
|
-
|
29
|
-
expect(config['exporters']['otlp']['endpoint']).to eq('https://otlp.scoutotel.com:4317')
|
30
|
-
expect(config['exporters']['otlp']['headers']['x-telemetryhub-key']).to eq('00001000010000abc')
|
31
|
-
expect(config['receivers']['filelog']['include']).to eq(['/tmp/fake_log_file.log'])
|
32
|
-
|
33
|
-
# Verify merge and consistent keys
|
34
|
-
expect(config['extensions']['file_storage/otc']['directory']).to eq('/dev/null')
|
35
|
-
expect(config['extensions']['file_storage/otc']['timeout']).to eq('10s')
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'handles an empty logs config file well' do
|
39
|
-
ENV['SCOUT_LOGS_CONFIG'] = File.expand_path('../../../data/empty_logs_config.yml', __dir__)
|
40
|
-
|
41
|
-
context = ScoutApm::Logging::Context.new
|
42
|
-
setup_collector_config!(context)
|
43
|
-
|
44
|
-
expect(File.exist?(context.config.value('collector_config_file'))).to be_truthy
|
45
|
-
config = YAML.load_file(context.config.value('collector_config_file'))
|
46
|
-
|
47
|
-
expect(config['exporters']['otlp']['endpoint']).to eq('https://otlp.scoutotel.com:4317')
|
48
|
-
expect(config['exporters']['otlp']['headers']['x-telemetryhub-key']).to eq('00001000010000abc')
|
49
|
-
expect(config['receivers']['filelog']['include']).to eq(['/tmp/fake_log_file.log'])
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def setup_collector_config!(context)
|
55
|
-
ENV['SCOUT_MONITOR_STATE_FILE'] = File.expand_path('../../../data/state_file.json', __dir__)
|
56
|
-
conf_file = File.expand_path('../../../data/mock_config.yml', __dir__)
|
57
|
-
context.config = ScoutApm::Logging::Config.with_file(context, conf_file)
|
58
|
-
|
59
|
-
ScoutApm::Logging::Utils.ensure_directory_exists(context.config.value('collector_config_file'))
|
60
|
-
|
61
|
-
collector_config = ScoutApm::Logging::Collector::Configuration.new(context)
|
62
|
-
collector_config.setup!
|
63
|
-
end
|
64
|
-
end
|
data/spec/unit/state_spec.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ScoutApm::Logging::Config do
|
4
|
-
it 'flushes and loads the state' do
|
5
|
-
context = ScoutApm::Logging::Context.new
|
6
|
-
conf_file = File.expand_path('../data/config_test_1.yml', __dir__)
|
7
|
-
conf = ScoutApm::Logging::Config.with_file(context, conf_file)
|
8
|
-
|
9
|
-
context.config = conf
|
10
|
-
|
11
|
-
ScoutApm::Logging::Config::ConfigDynamic.set_value('health_check_port', 1234)
|
12
|
-
|
13
|
-
context.config.state.flush_state!
|
14
|
-
|
15
|
-
data = ScoutApm::Logging::Config::State.new(context).load_state_from_file
|
16
|
-
|
17
|
-
expect(data['health_check_port']).to eq(context.config.value('health_check_port'))
|
18
|
-
expect(data['logs_monitored']).to eq(context.config.value('logs_monitored'))
|
19
|
-
end
|
20
|
-
end
|
data/tooling/checksums.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
###
|
2
|
-
# Calculates the checksums for the otelcol-contrib files
|
3
|
-
# Usage: ruby tooling/checksums.rb <version>
|
4
|
-
##
|
5
|
-
# frozen_string_literal: true
|
6
|
-
|
7
|
-
require 'digest'
|
8
|
-
require 'fileutils'
|
9
|
-
require 'net/http'
|
10
|
-
require 'pp'
|
11
|
-
|
12
|
-
DOUBLES = [
|
13
|
-
'darwin_amd64',
|
14
|
-
'darwin_arm64',
|
15
|
-
'linux_amd64',
|
16
|
-
'linux_arm64'
|
17
|
-
]
|
18
|
-
|
19
|
-
version = ARGV[0]
|
20
|
-
|
21
|
-
current_directory = Dir.pwd
|
22
|
-
unless current_directory.include?("/tooling")
|
23
|
-
tooling_directory = File.join(current_directory, "/tooling")
|
24
|
-
FileUtils.cd(tooling_directory)
|
25
|
-
end
|
26
|
-
|
27
|
-
def download_source_checksums(url, destination)
|
28
|
-
uri = URI(url)
|
29
|
-
|
30
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
31
|
-
request = Net::HTTP::Get.new(uri)
|
32
|
-
http.request(request) do |response|
|
33
|
-
return download_source_checksums(response['location'], destination) if response.code == '302'
|
34
|
-
|
35
|
-
File.open(destination, 'wb') do |file|
|
36
|
-
response.read_body do |chunk|
|
37
|
-
file.write(chunk)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def validate_and_return_checksums(version)
|
45
|
-
checksum_file_url = "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v#{version}/opentelemetry-collector-releases_otelcol-contrib_checksums.txt"
|
46
|
-
destination = "./opentelemetry-collector-releases_otelcol-contrib_checksums.txt"
|
47
|
-
|
48
|
-
download_source_checksums(checksum_file_url, destination)
|
49
|
-
|
50
|
-
contents = File.read(destination)
|
51
|
-
lines = contents.split("\n")
|
52
|
-
pairs = lines.each_with_object({}) do |item, hash|
|
53
|
-
value, key = item.split
|
54
|
-
hash[key] = value
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
relavent_pairs = {}
|
59
|
-
DOUBLES.each do |double|
|
60
|
-
file_name = "otelcol-contrib_#{version}_#{double}.tar.gz"
|
61
|
-
file_location = "./#{file_name}"
|
62
|
-
|
63
|
-
local_checksum = Digest::SHA256.file(file_location).hexdigest
|
64
|
-
source_checksum = pairs[file_name]
|
65
|
-
|
66
|
-
if source_checksum != local_checksum
|
67
|
-
puts "#{double} contains different checksums: Local checksum #{local_checksum} -- Source checksum #{source_checksum}"
|
68
|
-
raise "Different checksums for #{double}"
|
69
|
-
end
|
70
|
-
|
71
|
-
relavent_pairs[double] = local_checksum
|
72
|
-
end
|
73
|
-
|
74
|
-
relavent_pairs
|
75
|
-
end
|
76
|
-
|
77
|
-
def download_collector(url, destination)
|
78
|
-
uri = URI(url)
|
79
|
-
|
80
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
81
|
-
request = Net::HTTP::Get.new(uri)
|
82
|
-
http.request(request) do |response|
|
83
|
-
return download_collector(response['location'], destination) if response.code == '302'
|
84
|
-
|
85
|
-
File.open(destination, 'wb') do |file|
|
86
|
-
response.read_body do |chunk|
|
87
|
-
file.write(chunk)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
DOUBLES.each do |double|
|
95
|
-
host_os, architecture = double.split('_')
|
96
|
-
|
97
|
-
url = "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v#{version}/otelcol-contrib_#{version}_#{host_os}_#{architecture}.tar.gz"
|
98
|
-
|
99
|
-
destination = "./otelcol-contrib_#{version}_#{host_os}_#{architecture}.tar.gz"
|
100
|
-
|
101
|
-
download_collector(url, destination)
|
102
|
-
end
|
103
|
-
|
104
|
-
checksums = validate_and_return_checksums(version)
|
105
|
-
|
106
|
-
pp checksums
|