scout_apm 2.6.10 → 3.0.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.rubocop.yml +3 -11
- data/CHANGELOG.markdown +4 -362
- data/Gemfile +1 -14
- data/README.markdown +7 -52
- data/Rakefile +1 -0
- data/ext/allocations/allocations.c +1 -7
- data/ext/allocations/extconf.rb +0 -1
- data/ext/rusage/rusage.c +0 -26
- data/ext/stacks/extconf.rb +37 -0
- data/ext/stacks/scout_atomics.h +86 -0
- data/ext/stacks/stacks.c +811 -0
- data/lib/scout_apm/agent/logging.rb +69 -0
- data/lib/scout_apm/agent/reporting.rb +126 -0
- data/lib/scout_apm/agent.rb +259 -138
- data/lib/scout_apm/app_server_load.rb +15 -41
- data/lib/scout_apm/attribute_arranger.rb +3 -14
- data/lib/scout_apm/background_job_integrations/delayed_job.rb +1 -70
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +24 -31
- data/lib/scout_apm/background_worker.rb +12 -23
- data/lib/scout_apm/capacity.rb +57 -0
- data/lib/scout_apm/config.rb +37 -206
- data/lib/scout_apm/context.rb +4 -20
- data/lib/scout_apm/deploy_integrations/capistrano_2.cap +12 -0
- data/lib/scout_apm/deploy_integrations/capistrano_2.rb +83 -0
- data/lib/scout_apm/deploy_integrations/capistrano_3.cap +12 -0
- data/lib/scout_apm/deploy_integrations/capistrano_3.rb +88 -0
- data/lib/scout_apm/environment.rb +28 -42
- data/lib/scout_apm/fake_store.rb +0 -12
- data/lib/scout_apm/framework_integrations/rails_2.rb +1 -2
- data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +6 -17
- data/lib/scout_apm/framework_integrations/sinatra.rb +1 -1
- data/lib/scout_apm/histogram.rb +3 -12
- data/lib/scout_apm/instant/assets/xmlhttp_instrumentation.html +2 -2
- data/lib/scout_apm/instant/middleware.rb +54 -202
- data/lib/scout_apm/instant_reporting.rb +7 -7
- data/lib/scout_apm/instruments/.DS_Store +0 -0
- data/lib/scout_apm/instruments/action_controller_rails_2.rb +9 -15
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +76 -124
- data/lib/scout_apm/instruments/active_record.rb +29 -324
- data/lib/scout_apm/instruments/delayed_job.rb +57 -0
- data/lib/scout_apm/instruments/elasticsearch.rb +6 -10
- data/lib/scout_apm/instruments/grape.rb +9 -12
- data/lib/scout_apm/instruments/http_client.rb +7 -14
- data/lib/scout_apm/instruments/influxdb.rb +6 -10
- data/lib/scout_apm/instruments/middleware_detailed.rb +11 -15
- data/lib/scout_apm/instruments/middleware_summary.rb +5 -11
- data/lib/scout_apm/instruments/mongoid.rb +8 -39
- data/lib/scout_apm/instruments/moped.rb +6 -11
- data/lib/scout_apm/instruments/net_http.rb +9 -27
- data/lib/scout_apm/instruments/percentile_sampler.rb +23 -42
- data/lib/scout_apm/instruments/process/process_cpu.rb +6 -11
- data/lib/scout_apm/instruments/process/process_memory.rb +12 -17
- data/lib/scout_apm/instruments/rails_router.rb +6 -12
- data/lib/scout_apm/instruments/redis.rb +6 -10
- data/lib/scout_apm/instruments/sinatra.rb +4 -5
- data/lib/scout_apm/job_record.rb +2 -4
- data/lib/scout_apm/layaway.rb +34 -88
- data/lib/scout_apm/layaway_file.rb +3 -13
- data/lib/scout_apm/layer.rb +60 -25
- data/lib/scout_apm/layer_converters/allocation_metric_converter.rb +6 -7
- data/lib/scout_apm/layer_converters/converter_base.rb +14 -203
- data/lib/scout_apm/layer_converters/depth_first_walker.rb +10 -22
- data/lib/scout_apm/layer_converters/error_converter.rb +8 -8
- data/lib/scout_apm/layer_converters/job_converter.rb +50 -37
- data/lib/scout_apm/layer_converters/metric_converter.rb +19 -18
- data/lib/scout_apm/layer_converters/request_queue_time_converter.rb +13 -13
- data/lib/scout_apm/layer_converters/slow_job_converter.rb +116 -52
- data/lib/scout_apm/layer_converters/slow_request_converter.rb +120 -51
- data/lib/scout_apm/metric_meta.rb +5 -0
- data/lib/scout_apm/metric_set.rb +1 -9
- data/lib/scout_apm/metric_stats.rb +8 -7
- data/lib/scout_apm/middleware.rb +9 -7
- data/lib/scout_apm/reporter.rb +24 -71
- data/lib/scout_apm/request_histograms.rb +0 -12
- data/lib/scout_apm/request_manager.rb +7 -5
- data/lib/scout_apm/scored_item_set.rb +0 -7
- data/lib/scout_apm/serializers/app_server_load_serializer.rb +0 -4
- data/lib/scout_apm/serializers/deploy_serializer.rb +16 -0
- data/lib/scout_apm/serializers/directive_serializer.rb +0 -4
- data/lib/scout_apm/serializers/payload_serializer.rb +4 -11
- data/lib/scout_apm/serializers/payload_serializer_to_json.rb +16 -35
- data/lib/scout_apm/serializers/slow_jobs_serializer_to_json.rb +1 -2
- data/lib/scout_apm/server_integrations/passenger.rb +1 -1
- data/lib/scout_apm/server_integrations/puma.rb +2 -5
- data/lib/scout_apm/slow_job_policy.rb +13 -25
- data/lib/scout_apm/slow_job_record.rb +4 -13
- data/lib/scout_apm/slow_request_policy.rb +13 -25
- data/lib/scout_apm/slow_transaction.rb +5 -25
- data/lib/scout_apm/store.rb +32 -99
- data/lib/scout_apm/trace_compactor.rb +312 -0
- data/lib/scout_apm/tracer.rb +31 -35
- data/lib/scout_apm/tracked_request.rb +95 -262
- data/lib/scout_apm/utils/active_record_metric_name.rb +13 -88
- data/lib/scout_apm/utils/backtrace_parser.rb +4 -7
- data/lib/scout_apm/utils/fake_stacks.rb +87 -0
- data/lib/scout_apm/utils/installed_gems.rb +3 -7
- data/lib/scout_apm/utils/klass_helper.rb +2 -8
- data/lib/scout_apm/utils/null_logger.rb +13 -0
- data/lib/scout_apm/utils/sql_sanitizer.rb +5 -16
- data/lib/scout_apm/utils/sql_sanitizer_regex.rb +0 -7
- data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +0 -6
- data/lib/scout_apm/utils/unique_id.rb +0 -27
- data/lib/scout_apm/version.rb +2 -1
- data/lib/scout_apm.rb +25 -84
- data/scout_apm.gemspec +3 -17
- data/test/test_helper.rb +3 -57
- data/test/unit/agent_test.rb +54 -1
- data/test/unit/background_job_integrations/sidekiq_test.rb +3 -0
- data/test/unit/config_test.rb +12 -25
- data/test/unit/context_test.rb +4 -4
- data/test/unit/histogram_test.rb +4 -25
- data/test/unit/ignored_uris_test.rb +1 -1
- data/test/unit/instruments/active_record_instruments_test.rb +5 -0
- data/test/unit/layaway_test.rb +2 -62
- data/test/unit/serializers/payload_serializer_test.rb +15 -43
- data/test/unit/slow_request_policy_test.rb +6 -15
- data/test/unit/sql_sanitizer_test.rb +6 -53
- data/test/unit/store_test.rb +4 -73
- data/test/unit/utils/active_record_metric_name_test.rb +5 -59
- data/test/unit/utils/backtrace_parser_test.rb +1 -6
- data/tester.rb +53 -0
- metadata +28 -229
- data/.travis.yml +0 -26
- data/Guardfile +0 -43
- data/gems/README.md +0 -28
- data/gems/octoshark.gemfile +0 -4
- data/gems/rails3.gemfile +0 -5
- data/gems/rails4.gemfile +0 -4
- data/gems/rails5.gemfile +0 -4
- data/gems/rails6.gemfile +0 -4
- data/lib/scout_apm/agent/exit_handler.rb +0 -65
- data/lib/scout_apm/agent/preconditions.rb +0 -81
- data/lib/scout_apm/agent_context.rb +0 -261
- data/lib/scout_apm/auto_instrument/instruction_sequence.rb +0 -31
- data/lib/scout_apm/auto_instrument/layer.rb +0 -23
- data/lib/scout_apm/auto_instrument/parser.rb +0 -27
- data/lib/scout_apm/auto_instrument/rails.rb +0 -175
- data/lib/scout_apm/auto_instrument.rb +0 -5
- data/lib/scout_apm/background_job_integrations/legacy_sneakers.rb +0 -55
- data/lib/scout_apm/background_job_integrations/que.rb +0 -134
- data/lib/scout_apm/background_job_integrations/resque.rb +0 -88
- data/lib/scout_apm/background_job_integrations/shoryuken.rb +0 -124
- data/lib/scout_apm/background_job_integrations/sneakers.rb +0 -87
- data/lib/scout_apm/background_recorder.rb +0 -48
- data/lib/scout_apm/db_query_metric_set.rb +0 -97
- data/lib/scout_apm/db_query_metric_stats.rb +0 -102
- data/lib/scout_apm/debug.rb +0 -37
- data/lib/scout_apm/detailed_trace.rb +0 -217
- data/lib/scout_apm/error.rb +0 -27
- data/lib/scout_apm/error_service/error_buffer.rb +0 -39
- data/lib/scout_apm/error_service/error_record.rb +0 -211
- data/lib/scout_apm/error_service/ignored_exceptions.rb +0 -66
- data/lib/scout_apm/error_service/middleware.rb +0 -32
- data/lib/scout_apm/error_service/notifier.rb +0 -33
- data/lib/scout_apm/error_service/payload.rb +0 -47
- data/lib/scout_apm/error_service/periodic_work.rb +0 -17
- data/lib/scout_apm/error_service/railtie.rb +0 -11
- data/lib/scout_apm/error_service/sidekiq.rb +0 -80
- data/lib/scout_apm/error_service.rb +0 -32
- data/lib/scout_apm/extensions/config.rb +0 -87
- data/lib/scout_apm/extensions/transaction_callback_payload.rb +0 -74
- data/lib/scout_apm/git_revision.rb +0 -59
- data/lib/scout_apm/instrument_manager.rb +0 -88
- data/lib/scout_apm/instruments/action_view.rb +0 -141
- data/lib/scout_apm/instruments/http.rb +0 -48
- data/lib/scout_apm/instruments/memcached.rb +0 -43
- data/lib/scout_apm/instruments/resque.rb +0 -39
- data/lib/scout_apm/instruments/samplers.rb +0 -11
- data/lib/scout_apm/layer_children_set.rb +0 -86
- data/lib/scout_apm/layer_converters/database_converter.rb +0 -70
- data/lib/scout_apm/layer_converters/find_layer_by_type.rb +0 -38
- data/lib/scout_apm/layer_converters/histograms.rb +0 -15
- data/lib/scout_apm/layer_converters/trace_converter.rb +0 -184
- data/lib/scout_apm/limited_layer.rb +0 -126
- data/lib/scout_apm/logger.rb +0 -158
- data/lib/scout_apm/periodic_work.rb +0 -47
- data/lib/scout_apm/rack.rb +0 -26
- data/lib/scout_apm/remote/message.rb +0 -27
- data/lib/scout_apm/remote/recorder.rb +0 -57
- data/lib/scout_apm/remote/router.rb +0 -49
- data/lib/scout_apm/remote/server.rb +0 -60
- data/lib/scout_apm/reporting.rb +0 -143
- data/lib/scout_apm/serializers/db_query_serializer_to_json.rb +0 -15
- data/lib/scout_apm/serializers/histograms_serializer_to_json.rb +0 -21
- data/lib/scout_apm/synchronous_recorder.rb +0 -30
- data/lib/scout_apm/tasks/doctor.rb +0 -75
- data/lib/scout_apm/tasks/support.rb +0 -22
- data/lib/scout_apm/transaction.rb +0 -13
- data/lib/scout_apm/transaction_time_consumed.rb +0 -51
- data/lib/scout_apm/utils/gzip_helper.rb +0 -24
- data/lib/scout_apm/utils/marshal_logging.rb +0 -90
- data/lib/scout_apm/utils/numbers.rb +0 -14
- data/lib/scout_apm/utils/scm.rb +0 -14
- data/lib/tasks/doctor.rake +0 -11
- data/test/tmp/README.md +0 -17
- data/test/unit/agent_context_test.rb +0 -15
- data/test/unit/auto_instrument/assignments-instrumented.rb +0 -31
- data/test/unit/auto_instrument/assignments.rb +0 -31
- data/test/unit/auto_instrument/controller-ast.txt +0 -57
- data/test/unit/auto_instrument/controller-instrumented.rb +0 -49
- data/test/unit/auto_instrument/controller.rb +0 -49
- data/test/unit/auto_instrument/rescue_from-instrumented.rb +0 -13
- data/test/unit/auto_instrument/rescue_from.rb +0 -13
- data/test/unit/auto_instrument_test.rb +0 -54
- data/test/unit/db_query_metric_set_test.rb +0 -67
- data/test/unit/db_query_metric_stats_test.rb +0 -113
- data/test/unit/error_service/error_buffer_test.rb +0 -25
- data/test/unit/error_service/ignored_exceptions_test.rb +0 -49
- data/test/unit/extensions/periodic_callbacks_test.rb +0 -58
- data/test/unit/extensions/transaction_callbacks_test.rb +0 -58
- data/test/unit/fake_store_test.rb +0 -10
- data/test/unit/git_revision_test.rb +0 -15
- data/test/unit/instruments/active_record_test.rb +0 -40
- data/test/unit/instruments/net_http_test.rb +0 -27
- data/test/unit/instruments/percentile_sampler_test.rb +0 -133
- data/test/unit/layer_children_set_test.rb +0 -97
- data/test/unit/layer_converters/depth_first_walker_test.rb +0 -70
- data/test/unit/layer_converters/metric_converter_test.rb +0 -22
- data/test/unit/layer_converters/stubs.rb +0 -33
- data/test/unit/limited_layer_test.rb +0 -53
- data/test/unit/logger_test.rb +0 -69
- data/test/unit/remote/test_message.rb +0 -13
- data/test/unit/remote/test_router.rb +0 -33
- data/test/unit/remote/test_server.rb +0 -15
- data/test/unit/request_histograms_test.rb +0 -17
- data/test/unit/tracer_test.rb +0 -76
- data/test/unit/tracked_request_test.rb +0 -71
- data/test/unit/transaction_test.rb +0 -14
- data/test/unit/transaction_time_consumed_test.rb +0 -46
- data/test/unit/utils/numbers_test.rb +0 -15
- data/test/unit/utils/scm.rb +0 -17
data/test/unit/agent_test.rb
CHANGED
@@ -1,5 +1,58 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'scout_apm/agent'
|
3
|
+
require 'scout_apm/slow_transaction'
|
4
|
+
require 'scout_apm/metric_meta'
|
5
|
+
require 'scout_apm/metric_stats'
|
6
|
+
require 'scout_apm/context'
|
7
|
+
require 'scout_apm/store'
|
2
8
|
|
3
9
|
class AgentTest < Minitest::Test
|
4
|
-
|
10
|
+
|
11
|
+
# Safeguard to ensure the main agent thread doesn't have any interaction with the layaway file. Contention on file locks can cause delays.
|
12
|
+
def test_start_with_lock_on_layaway_file
|
13
|
+
# setup the file, putting a lock on it.
|
14
|
+
File.open(DATA_FILE_PATH, "w") {}
|
15
|
+
f = File.open(DATA_FILE_PATH, File::RDWR | File::CREAT)
|
16
|
+
f.flock(File::LOCK_EX)
|
17
|
+
|
18
|
+
agent = ScoutApm::Agent.instance
|
19
|
+
|
20
|
+
no_timeout = true
|
21
|
+
begin
|
22
|
+
Timeout::timeout(3) { agent.start({:monitor => true, :force => true}) }
|
23
|
+
rescue Timeout::Error
|
24
|
+
no_timeout = false
|
25
|
+
ensure
|
26
|
+
f.flock(File::LOCK_UN)
|
27
|
+
f.close
|
28
|
+
end
|
29
|
+
assert no_timeout, "Agent took >= 3s to start. Possible file lock issue."
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_reset_file_with_old_format
|
33
|
+
File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(OLD_FORMAT)) }
|
34
|
+
begin
|
35
|
+
ScoutApm::Agent.instance(:force => true).process_metrics
|
36
|
+
rescue NoMethodError
|
37
|
+
# The agent will raise an exception the first time metrics are processed for scout_apm < 1.2.
|
38
|
+
#
|
39
|
+
# NoMethodError: undefined method `values' for []:Array
|
40
|
+
# /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/layaway.rb:46:in `periods_ready_for_delivery'
|
41
|
+
# /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/agent/reporting.rb:31:in `report_to_server'
|
42
|
+
# /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/agent/reporting.rb:24:in `process_metrics'
|
43
|
+
# /Users/dlite/projects/scout_apm_ruby/test/unit/layaway_test.rb:27:in `test_reset_file_with_old_format'
|
44
|
+
end
|
45
|
+
# Data will be fine the next go-around
|
46
|
+
no_error = true
|
47
|
+
begin
|
48
|
+
ScoutApm::Agent.instance(:force => true).process_metrics
|
49
|
+
rescue Exception => e
|
50
|
+
no_error = false
|
51
|
+
end
|
52
|
+
assert no_error, "Error trying to process metrics after upgrading from < 1.2 data format: #{e.message if e}"
|
53
|
+
end
|
54
|
+
|
55
|
+
## TODO - adds tests to ensure other potentially long-running things don't sneak in, like HTTP calls.
|
56
|
+
|
57
|
+
OLD_FORMAT = {1452533280 => {:metrics => {}, :slow_transactions => {}} } # Pre 1.2 agents used a different file format to store data.
|
5
58
|
end
|
@@ -11,6 +11,7 @@ class SidekiqTest < Minitest::Test
|
|
11
11
|
def test_middleware_call_happy_path
|
12
12
|
fake_request = mock
|
13
13
|
fake_request.expects(:annotate_request)
|
14
|
+
fake_request.expects(:job!)
|
14
15
|
fake_request.expects(:start_layer).twice
|
15
16
|
fake_request.expects(:stop_layer).twice
|
16
17
|
fake_request.expects(:error!).never
|
@@ -28,6 +29,7 @@ class SidekiqTest < Minitest::Test
|
|
28
29
|
def test_middleware_call_job_exception
|
29
30
|
fake_request = mock
|
30
31
|
fake_request.expects(:annotate_request)
|
32
|
+
fake_request.expects(:job!)
|
31
33
|
fake_request.expects(:start_layer).twice
|
32
34
|
fake_request.expects(:stop_layer).twice
|
33
35
|
fake_request.expects(:error!)
|
@@ -45,6 +47,7 @@ class SidekiqTest < Minitest::Test
|
|
45
47
|
def test_middleware_call_edge_cases
|
46
48
|
fake_request = mock
|
47
49
|
fake_request.expects(:annotate_request)
|
50
|
+
fake_request.expects(:job!)
|
48
51
|
fake_request.expects(:start_layer).twice
|
49
52
|
fake_request.expects(:stop_layer).twice
|
50
53
|
fake_request.expects(:error!)
|
data/test/unit/config_test.rb
CHANGED
@@ -3,40 +3,36 @@ require 'test_helper'
|
|
3
3
|
require 'scout_apm/config'
|
4
4
|
|
5
5
|
class ConfigTest < Minitest::Test
|
6
|
-
def setup
|
7
|
-
@context = ScoutApm::AgentContext.new
|
8
|
-
end
|
9
|
-
|
10
6
|
def test_initalize_without_a_config
|
11
|
-
conf = ScoutApm::Config.without_file
|
7
|
+
conf = ScoutApm::Config.without_file
|
12
8
|
|
13
9
|
# nil for random keys
|
14
|
-
assert_nil conf.value(
|
10
|
+
assert_nil conf.value("log_file_path")
|
15
11
|
|
16
12
|
# but has values for defaulted keys
|
17
|
-
assert conf.value(
|
13
|
+
assert conf.value("host")
|
18
14
|
|
19
15
|
# and still reads from ENV
|
20
16
|
ENV['SCOUT_CONFIG_TEST_KEY'] = 'testval'
|
21
|
-
assert_equal 'testval', conf.value(
|
17
|
+
assert_equal 'testval', conf.value("config_test_key")
|
22
18
|
end
|
23
19
|
|
24
20
|
def test_loading_a_file
|
25
|
-
set_rack_env(
|
21
|
+
set_rack_env("production")
|
26
22
|
|
27
|
-
conf_file = File.expand_path(
|
28
|
-
conf = ScoutApm::Config.with_file(
|
23
|
+
conf_file = File.expand_path("../../data/config_test_1.yml", __FILE__)
|
24
|
+
conf = ScoutApm::Config.with_file(conf_file)
|
29
25
|
|
30
|
-
assert_equal
|
31
|
-
assert_equal
|
26
|
+
assert_equal "debug", conf.value('log_level')
|
27
|
+
assert_equal "APM Test Conf (Production)", conf.value('name')
|
32
28
|
end
|
33
29
|
|
34
30
|
def test_loading_file_without_env_in_file
|
35
31
|
conf_file = File.expand_path("../../data/config_test_1.yml", __FILE__)
|
36
|
-
conf = ScoutApm::Config.with_file(
|
32
|
+
conf = ScoutApm::Config.with_file(conf_file, environment: "staging")
|
37
33
|
|
38
34
|
assert_equal "info", conf.value('log_level') # the default value
|
39
|
-
|
35
|
+
assert_equal nil, conf.value('name') # the default value
|
40
36
|
end
|
41
37
|
|
42
38
|
def test_boolean_coercion
|
@@ -71,15 +67,6 @@ class ConfigTest < Minitest::Test
|
|
71
67
|
assert_equal 10, coercion.coerce(10)
|
72
68
|
assert_equal ["a"], coercion.coerce(["a"])
|
73
69
|
end
|
70
|
+
end
|
74
71
|
|
75
|
-
def test_any_keys_found
|
76
|
-
ENV.stubs(:has_key?).returns(nil)
|
77
|
-
|
78
|
-
conf = ScoutApm::Config.with_file(@context, "a_file_that_doesnt_exist.yml")
|
79
|
-
assert ! conf.any_keys_found?
|
80
72
|
|
81
|
-
ENV.stubs(:has_key?).with("SCOUT_MONITOR").returns("true")
|
82
|
-
conf = ScoutApm::Config.with_file(@context, "a_file_that_doesnt_exist.yml")
|
83
|
-
assert conf.any_keys_found?
|
84
|
-
end
|
85
|
-
end
|
data/test/unit/context_test.rb
CHANGED
@@ -4,25 +4,25 @@ require 'scout_apm/context'
|
|
4
4
|
|
5
5
|
class ContextText < Minitest::Test
|
6
6
|
def test_ignore_nil_value
|
7
|
-
context = ScoutApm::Context.new
|
7
|
+
context = ScoutApm::Context.new
|
8
8
|
assert hash = context.add(:nil_key => nil, :org => 'org')
|
9
9
|
assert_equal ({:org => 'org'}), hash
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_ignore_nil_key
|
13
|
-
context = ScoutApm::Context.new
|
13
|
+
context = ScoutApm::Context.new
|
14
14
|
assert hash = context.add(nil => nil, :org => 'org')
|
15
15
|
assert_equal ({:org => 'org'}), hash
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_ignore_unsupported_value_type
|
19
|
-
context = ScoutApm::Context.new
|
19
|
+
context = ScoutApm::Context.new
|
20
20
|
assert hash = context.add(:array => [1,2,3,4], :org => 'org')
|
21
21
|
assert_equal ({:org => 'org'}), hash
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_ignore_unsupported_key_type
|
25
|
-
context = ScoutApm::Context.new
|
25
|
+
context = ScoutApm::Context.new
|
26
26
|
assert hash = context.add([1,2,3,4] => 'hey', :org => 'org')
|
27
27
|
assert_equal ({:org => 'org'}), hash
|
28
28
|
end
|
data/test/unit/histogram_test.rb
CHANGED
@@ -35,8 +35,8 @@ class HistogramTest < Minitest::Test
|
|
35
35
|
end
|
36
36
|
}
|
37
37
|
|
38
|
-
assert_equal 1.5,
|
39
|
-
assert_equal 9.5,
|
38
|
+
assert_equal 1.5, hist.quantile(0).round(1)
|
39
|
+
assert_equal 9.5, hist.quantile(100).round(1)
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_combine
|
@@ -55,8 +55,8 @@ class HistogramTest < Minitest::Test
|
|
55
55
|
}
|
56
56
|
|
57
57
|
combined = hist1.combine!(hist2)
|
58
|
-
assert_equal 1.5,
|
59
|
-
assert_equal 9.5,
|
58
|
+
assert_equal 1.5, combined.quantile(0).round(1)
|
59
|
+
assert_equal 9.5, combined.quantile(100).round(1)
|
60
60
|
assert_equal 200, combined.total
|
61
61
|
end
|
62
62
|
|
@@ -79,20 +79,6 @@ class HistogramTest < Minitest::Test
|
|
79
79
|
assert combined.quantile(0) < combined.quantile(100)
|
80
80
|
end
|
81
81
|
|
82
|
-
def test_combine_dedups_identicals
|
83
|
-
hist1 = ScoutApm::NumericHistogram.new(5)
|
84
|
-
hist2 = ScoutApm::NumericHistogram.new(5)
|
85
|
-
hist1.add(1)
|
86
|
-
hist1.add(2)
|
87
|
-
hist2.add(2)
|
88
|
-
hist2.add(3)
|
89
|
-
|
90
|
-
combined = hist1.combine!(hist2)
|
91
|
-
assert_equal 4, combined.total
|
92
|
-
assert_equal [[1, 1], [2, 2], [1, 3]],
|
93
|
-
combined.bins.map{|bin| [bin.count, bin.value.to_i] }
|
94
|
-
end
|
95
|
-
|
96
82
|
def test_mean
|
97
83
|
hist = ScoutApm::NumericHistogram.new(5)
|
98
84
|
10.times {
|
@@ -103,12 +89,5 @@ class HistogramTest < Minitest::Test
|
|
103
89
|
|
104
90
|
assert_equal 5.5, hist.mean
|
105
91
|
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
# Ruby 1.8 compatible round with precision
|
110
|
-
def round(number, precision)
|
111
|
-
((number * 10**precision).round.to_f) / (10**precision)
|
112
|
-
end
|
113
92
|
end
|
114
93
|
|
data/test/unit/layaway_test.rb
CHANGED
@@ -10,75 +10,15 @@ class LayawayTest < Minitest::Test
|
|
10
10
|
def test_directory_uses_DATA_FILE_option
|
11
11
|
FileUtils.mkdir_p '/tmp/scout_apm_test/data_file_option'
|
12
12
|
config = make_fake_config("data_file" => "/tmp/scout_apm_test/data_file_option")
|
13
|
-
context = ScoutApm::AgentContext.new().tap{|c| c.config = config }
|
14
|
-
layaway = ScoutApm::Layaway.new(context)
|
15
13
|
|
16
|
-
assert_equal Pathname.new("/tmp/scout_apm_test/data_file_option"),
|
14
|
+
assert_equal Pathname.new("/tmp/scout_apm_test/data_file_option"), ScoutApm::Layaway.new(config, ScoutApm::Agent.instance.environment).directory
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_directory_looks_for_root_slash_tmp
|
20
18
|
FileUtils.mkdir_p '/tmp/scout_apm_test/tmp'
|
21
19
|
config = make_fake_config({})
|
22
20
|
env = make_fake_environment(:root => "/tmp/scout_apm_test")
|
23
|
-
context = ScoutApm::AgentContext.new().tap{|c| c.config = config; c.environment = env }
|
24
21
|
|
25
|
-
assert_equal Pathname.new("/tmp/scout_apm_test/tmp"), ScoutApm::Layaway.new(
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_layaway_file_limit_prevents_new_writes
|
29
|
-
FileUtils.mkdir_p '/tmp/scout_apm_test/layaway_limit'
|
30
|
-
config = make_fake_config("data_file" => "/tmp/scout_apm_test/layaway_limit")
|
31
|
-
context = ScoutApm::AgentContext.new().tap{|c| c.config = config }
|
32
|
-
layaway = ScoutApm::Layaway.new(context)
|
33
|
-
layaway.delete_files_for(:all)
|
34
|
-
|
35
|
-
context = ScoutApm::AgentContext.new
|
36
|
-
current_time = Time.now.utc
|
37
|
-
current_rp = ScoutApm::StoreReportingPeriod.new(current_time, context)
|
38
|
-
stale_rp = ScoutApm::StoreReportingPeriod.new(current_time - current_time.sec - 120, context)
|
39
|
-
|
40
|
-
# layaway.write_reporting_period returns nil on successful write
|
41
|
-
# It should probably be changed to return true or the number of bytes written
|
42
|
-
assert_nil layaway.write_reporting_period(stale_rp, 1)
|
43
|
-
|
44
|
-
# layaway.write_reporting_period returns an explicit false class on failure
|
45
|
-
assert layaway.write_reporting_period(current_rp, 1).is_a?(FalseClass)
|
46
|
-
|
47
|
-
layaway.delete_files_for(:all)
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_layaway_stale_regex_pattern
|
51
|
-
data_dir = '/tmp/scout_apm_test/shared/scout_apm'
|
52
|
-
FileUtils.mkdir_p data_dir
|
53
|
-
# Clean out files
|
54
|
-
FileUtils.safe_unlink(Dir.glob("#{data_dir}/scout_*_*.data"))
|
55
|
-
|
56
|
-
config = make_fake_config({'data_file' => data_dir})
|
57
|
-
env = make_fake_environment(:root => '/tmp/scout_apm_test')
|
58
|
-
context = ScoutApm::AgentContext.new().tap{|c| c.config = config; c.environment = env }
|
59
|
-
layaway = ScoutApm::Layaway.new(context)
|
60
|
-
|
61
|
-
|
62
|
-
not_stale_time = Time.now
|
63
|
-
not_stale_time_formatted = not_stale_time.strftime(ScoutApm::Layaway::TIME_FORMAT)
|
64
|
-
|
65
|
-
stale_time = not_stale_time - (ScoutApm::Layaway::STALE_AGE + 120) # ScoutApm::Layaway::STALE_AGE is in seconds. Add another 2 minutes to STALE_AGE
|
66
|
-
stale_time_formatted = stale_time.strftime(ScoutApm::Layaway::TIME_FORMAT)
|
67
|
-
|
68
|
-
not_stale_file_names = [File.join(data_dir, "scout_#{not_stale_time_formatted}_1.data"),
|
69
|
-
File.join(data_dir, "scout_#{not_stale_time_formatted}_20.data")]
|
70
|
-
stale_file_names = [File.join(data_dir, "scout_#{stale_time_formatted}_1.data"),
|
71
|
-
File.join(data_dir, "scout_#{stale_time_formatted}_20.data")]
|
72
|
-
all_file_names = not_stale_file_names + stale_file_names
|
73
|
-
|
74
|
-
(all_file_names).each do |filename|
|
75
|
-
File.new(filename, 'w').close
|
76
|
-
end
|
77
|
-
|
78
|
-
assert_equal Pathname.new("/tmp/scout_apm_test/shared/scout_apm"), ScoutApm::Layaway.new(context).directory
|
79
|
-
assert_equal all_file_names.sort, Dir.glob("#{data_dir}/*data").sort
|
80
|
-
|
81
|
-
layaway.delete_stale_files(not_stale_time - ScoutApm::Layaway::STALE_AGE)
|
82
|
-
assert_equal not_stale_file_names.sort, Dir.glob("#{data_dir}/*data").sort
|
22
|
+
assert_equal Pathname.new("/tmp/scout_apm_test/tmp"), ScoutApm::Layaway.new(config, env).directory
|
83
23
|
end
|
84
24
|
end
|
@@ -1,4 +1,13 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'scout_apm/attribute_arranger'
|
3
|
+
require 'scout_apm/bucket_name_splitter'
|
4
|
+
require 'scout_apm/serializers/payload_serializer'
|
5
|
+
require 'scout_apm/serializers/payload_serializer_to_json'
|
6
|
+
require 'scout_apm/slow_transaction'
|
7
|
+
require 'scout_apm/metric_meta'
|
8
|
+
require 'scout_apm/metric_stats'
|
9
|
+
require 'scout_apm/context'
|
10
|
+
require 'ostruct'
|
2
11
|
require 'json' # to deserialize what has been manually serialized by the production code
|
3
12
|
|
4
13
|
class PayloadSerializerTest < Minitest::Test
|
@@ -8,7 +17,7 @@ class PayloadSerializerTest < Minitest::Test
|
|
8
17
|
:unique_id => "unique_idz",
|
9
18
|
:agent_version => 123
|
10
19
|
}
|
11
|
-
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize(metadata, {}, {}, [], []
|
20
|
+
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize(metadata, {}, {}, [], [])
|
12
21
|
|
13
22
|
# symbol keys turn to strings
|
14
23
|
formatted_metadata = {
|
@@ -46,10 +55,10 @@ class PayloadSerializerTest < Minitest::Test
|
|
46
55
|
stats.min_call_time = 0.034881757
|
47
56
|
stats.sum_of_squares = 0.007382350213180609
|
48
57
|
stats.total_call_time = 0.113403176
|
49
|
-
stats.total_exclusive_time = 0.
|
58
|
+
stats.total_exclusive_time = 0.07813208899999999
|
50
59
|
}
|
51
60
|
}
|
52
|
-
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize({}, metrics, {}, [], []
|
61
|
+
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize({}, metrics, {}, [], [])
|
53
62
|
formatted_metrics = [
|
54
63
|
{
|
55
64
|
"key" => {
|
@@ -82,11 +91,10 @@ class PayloadSerializerTest < Minitest::Test
|
|
82
91
|
"max_call_time" => 0.078521419,
|
83
92
|
"min_call_time" => 0.034881757,
|
84
93
|
"total_call_time" => 0.113403176,
|
85
|
-
"total_exclusive_time" => 0.
|
94
|
+
"total_exclusive_time" => 0.07813208899999999,
|
86
95
|
}
|
87
96
|
]
|
88
|
-
assert_equal formatted_metrics,
|
89
|
-
JSON.parse(payload)["metrics"].sort_by { |m| m["key"]["bucket"] }
|
97
|
+
assert_equal formatted_metrics, JSON.parse(payload)["metrics"]
|
90
98
|
end
|
91
99
|
|
92
100
|
def test_escapes_json_quotes
|
@@ -94,7 +102,7 @@ class PayloadSerializerTest < Minitest::Test
|
|
94
102
|
:quotie => "here are some \"quotes\"",
|
95
103
|
:payload_version => 2,
|
96
104
|
}
|
97
|
-
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize(metadata, {}, {}, [], []
|
105
|
+
payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize(metadata, {}, {}, [], [])
|
98
106
|
|
99
107
|
# symbol keys turn to strings
|
100
108
|
formatted_metadata = {
|
@@ -108,40 +116,4 @@ class PayloadSerializerTest < Minitest::Test
|
|
108
116
|
json = { "foo" => "\bbar\nbaz\r" }
|
109
117
|
assert_equal json, JSON.parse(ScoutApm::Serializers::PayloadSerializerToJson.jsonify_hash(json))
|
110
118
|
end
|
111
|
-
|
112
|
-
def test_escapes_escaped_quotes
|
113
|
-
# Some escapes haven't ever worked on 1.8.7, and is not the issue I'm
|
114
|
-
# fixing now. Remove this when we drop support for ancient ruby
|
115
|
-
skip if RUBY_VERSION == "1.8.7"
|
116
|
-
|
117
|
-
json = {"foo" => %q|`additional_details` = '{\"amount\":1}'|}
|
118
|
-
result = ScoutApm::Serializers::PayloadSerializerToJson.jsonify_hash(json)
|
119
|
-
assert_equal json, JSON.parse(result)
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_escapes_various_special_characters
|
123
|
-
# Some escapes haven't ever worked on 1.8.7, and is not the issue I'm
|
124
|
-
# fixing now. Remove this when we drop support for ancient ruby
|
125
|
-
skip if RUBY_VERSION == "1.8.7"
|
126
|
-
|
127
|
-
json = {"foo" => [
|
128
|
-
%Q|\fbar|,
|
129
|
-
%Q|\rbar|,
|
130
|
-
%Q|\nbar|,
|
131
|
-
%Q|\tbar|,
|
132
|
-
%Q|"bar|,
|
133
|
-
%Q|'bar|,
|
134
|
-
%Q|{bar|,
|
135
|
-
%Q|}bar|,
|
136
|
-
%Q|\\bar|,
|
137
|
-
if RUBY_VERSION == '1.8.7'
|
138
|
-
""
|
139
|
-
else
|
140
|
-
%Q|\\\nbar|
|
141
|
-
end,
|
142
|
-
]}
|
143
|
-
|
144
|
-
result = ScoutApm::Serializers::PayloadSerializerToJson.jsonify_hash(json)
|
145
|
-
assert_equal json, JSON.parse(result)
|
146
|
-
end
|
147
119
|
end
|
@@ -17,13 +17,9 @@ class FakeRequest
|
|
17
17
|
end
|
18
18
|
|
19
19
|
class SlowRequestPolicyTest < Minitest::Test
|
20
|
-
def setup
|
21
|
-
@context = ScoutApm::AgentContext.new
|
22
|
-
end
|
23
|
-
|
24
20
|
def test_stored_records_current_time
|
25
21
|
test_start = Time.now
|
26
|
-
policy = ScoutApm::SlowRequestPolicy.new
|
22
|
+
policy = ScoutApm::SlowRequestPolicy.new
|
27
23
|
request = FakeRequest.new("users/index")
|
28
24
|
|
29
25
|
policy.stored!(request)
|
@@ -31,20 +27,15 @@ class SlowRequestPolicyTest < Minitest::Test
|
|
31
27
|
end
|
32
28
|
|
33
29
|
def test_score
|
34
|
-
policy = ScoutApm::SlowRequestPolicy.new
|
30
|
+
policy = ScoutApm::SlowRequestPolicy.new
|
35
31
|
request = FakeRequest.new("users/index")
|
36
32
|
|
37
33
|
request.set_duration(10) # 10 seconds
|
38
34
|
policy.last_seen[request.unique_name] = Time.now - 120 # 2 minutes since last seen
|
39
|
-
|
40
|
-
@context.transaction_time_consumed.add(request.unique_name, 1)
|
41
|
-
|
42
|
-
# Actual value I have in console is 4.01
|
43
|
-
# Score uses Time.now to compare w/ last_seen, and will tick up slowly as
|
44
|
-
# time passes, hence the range below.
|
45
|
-
score = policy.score(request)
|
35
|
+
ScoutApm::Agent.instance.request_histograms.add(request.unique_name, 1)
|
46
36
|
|
47
|
-
|
48
|
-
assert score
|
37
|
+
# Actual value I have in console is 1.499
|
38
|
+
assert policy.score(request) > 1.45
|
39
|
+
assert policy.score(request) < 1.55
|
49
40
|
end
|
50
41
|
end
|
@@ -1,8 +1,14 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
require 'scout_apm/utils/sql_sanitizer'
|
4
|
+
|
3
5
|
module ScoutApm
|
4
6
|
module Utils
|
5
7
|
class SqlSanitizerTest < Minitest::Test
|
8
|
+
def setup
|
9
|
+
ScoutApm::Agent.instance.init_logger
|
10
|
+
end
|
11
|
+
|
6
12
|
# Too long, and we just bail out to prevent long running instrumentation
|
7
13
|
def test_long_sql
|
8
14
|
sql = " " * 1001
|
@@ -10,8 +16,6 @@ module ScoutApm
|
|
10
16
|
end
|
11
17
|
|
12
18
|
def test_postgres_simple_select_of_first
|
13
|
-
skip "Broken on Ruby 1.8.7 because regular expressions do not support look-behinds" if RUBY_VERSION.start_with?("1.8.")
|
14
|
-
|
15
19
|
sql = %q|SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1|
|
16
20
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
|
17
21
|
assert_equal %q|SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1|, ss.to_s
|
@@ -28,23 +32,7 @@ module ScoutApm
|
|
28
32
|
sql = %q|SELECT "users".* FROM "users" INNER JOIN "blogs" ON "blogs"."user_id" = "users"."id" WHERE (blogs.title = 'hello world')|
|
29
33
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
|
30
34
|
assert_equal %q|SELECT "users".* FROM "users" INNER JOIN "blogs" ON "blogs"."user_id" = "users"."id" WHERE (blogs.title = ?)|, ss.to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_postgres_strips_after_where
|
34
|
-
raw_sql = %q|SELECT DISTINCT ON (flagged_traces.metric_name) flagged_traces.metric_name, "flagged_traces"."trace_id", "flagged_traces"."trace_type", "flagged_traces"."trace_occurred_at", flagged_traces.details ->> 'uri' as uri, (flagged_traces.details ->> 'n_sum_millis')::float as potential_savings, (flagged_traces.details ->> 'n_count')::float as num_queries FROM "flagged_traces" WHERE "flagged_traces"."app_id" = 5 AND "flagged_traces"."trace_type" = 'Request' AND ("flagged_traces"."trace_occurred_at" BETWEEN '2019-04-17 12:28:00.000000' AND '2019-04-18 12:28:00.000000') AND "flagged_traces"."flag_type" = 'nplusone' ORDER BY "flagged_traces"."metric_name" ASC, potential_savings DESC|
|
35
|
-
sanitized_sql = SqlSanitizer.new(raw_sql).tap { |it| it.database_engine = :postgres}
|
36
|
-
expected_sql = %q|SELECT DISTINCT ON (flagged_traces.metric_name) flagged_traces.metric_name, "flagged_traces"."trace_id", "flagged_traces"."trace_type", "flagged_traces"."trace_occurred_at", flagged_traces.details ->> 'uri' as uri, (flagged_traces.details ->> 'n_sum_millis')::float as potential_savings, (flagged_traces.details ->> 'n_count')::float as num_queries FROM "flagged_traces" WHERE "flagged_traces"."app_id" = ? AND "flagged_traces"."trace_type" = ? AND ("flagged_traces"."trace_occurred_at" BETWEEN ? AND ?) AND "flagged_traces"."flag_type" = ? ORDER BY "flagged_traces"."metric_name" ASC, potential_savings DESC|
|
37
|
-
assert_equal expected_sql, sanitized_sql.to_s
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_postgres_strips_subquery_strings
|
41
|
-
raw_sql = %q|"SELECT 'orgs'.* FROM "orgs" WHERE "orgs"."name" = 'Scout' AND "orgs"."created_by_user_id" IN (SELECT 'users'.'id' FROM "users" WHERE (id > AVG(id)) AND "type" = 'USER' AND "created_at" BETWEEN '2019-04-17 12:28:00.000000' AND '2019-04-18 12:28:00.000000')"|
|
42
|
-
sanitized_sql = SqlSanitizer.new(raw_sql).tap { |it| it.database_engine = :postgres}
|
43
|
-
expected_sql = %q|"SELECT 'orgs'.* FROM "orgs" WHERE "orgs"."name" = ? AND "orgs"."created_by_user_id" IN (SELECT 'users'.'id' FROM "users" WHERE (id > AVG(id)) AND "type" = ? AND "created_at" BETWEEN ? AND ?)"|
|
44
|
-
assert_equal expected_sql, sanitized_sql.to_s
|
45
|
-
end
|
46
35
|
|
47
|
-
def test_postgres_strips_integers
|
48
36
|
# Strip integers
|
49
37
|
sql = %q|SELECT "blogs".* FROM "blogs" WHERE (view_count > 10)|
|
50
38
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
|
@@ -73,8 +61,6 @@ module ScoutApm
|
|
73
61
|
end
|
74
62
|
|
75
63
|
def test_mysql_limit
|
76
|
-
skip "Broken on Ruby 1.8.7 because regular expressions do not support look-behinds" if RUBY_VERSION.start_with?("1.8.")
|
77
|
-
|
78
64
|
sql = %q|SELECT `blogs`.* FROM `blogs` ORDER BY `blogs`.`id` ASC LIMIT 1|
|
79
65
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :mysql }
|
80
66
|
assert_equal %q|SELECT `blogs`.* FROM `blogs` ORDER BY `blogs`.`id` ASC LIMIT 1|, ss.to_s
|
@@ -105,33 +91,7 @@ module ScoutApm
|
|
105
91
|
assert_equal %q|INSERT INTO `users` VALUES (?, ?)|, ss.to_s
|
106
92
|
end
|
107
93
|
|
108
|
-
def test_sqlserver_integers
|
109
|
-
skip "SQLServer Support requires Ruby 1.9+ For Regexes"
|
110
|
-
|
111
|
-
sql = "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (age > 50) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
|
112
|
-
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
|
113
|
-
assert_equal %q|SELECT [users].* FROM [users] WHERE (age > ?) ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @0 ROWS ONLY|, ss.to_s
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_sqlserver_strings
|
117
|
-
skip "SQLServer Support requires Ruby 1.9+ For Regexes"
|
118
|
-
|
119
|
-
sql = "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE [users].[email] = @0 ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @1 ROWS ONLY', N'@0 nvarchar(4000), @1 int', @0 = N'foo', @1 = 10"
|
120
|
-
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
|
121
|
-
assert_equal %q|SELECT [users].* FROM [users] WHERE [users].[email] = @0 ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @1 ROWS ONLY|, ss.to_s
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_sqlserver_in_clause
|
125
|
-
skip "SQLServer Support requires Ruby 1.9+ For Regexes"
|
126
|
-
|
127
|
-
sql = "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (id IN (1,2,3)) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
|
128
|
-
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
|
129
|
-
assert_equal %q|SELECT [users].* FROM [users] WHERE (id IN (?)) ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @0 ROWS ONLY|, ss.to_s
|
130
|
-
end
|
131
|
-
|
132
94
|
def test_scrubs_invalid_encoding
|
133
|
-
skip "Ruby 1.8.7 has no concept of encoding" if RUBY_VERSION.start_with?("1.8.")
|
134
|
-
|
135
95
|
sql = "SELECT `blogs`.* FROM `blogs` WHERE (title = 'a\255c')".force_encoding('UTF-8')
|
136
96
|
assert_equal false, sql.valid_encoding?
|
137
97
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :mysql }
|
@@ -139,13 +99,6 @@ module ScoutApm
|
|
139
99
|
assert_equal %q|SELECT `blogs`.* FROM `blogs` WHERE (title = ?)|, ss.to_s
|
140
100
|
end
|
141
101
|
|
142
|
-
def test_set_columns
|
143
|
-
sql = %q|UPDATE "mytable" SET "myfield" = 'fieldcontent', "countofthings" = 10 WHERE "user_id" = 10|
|
144
|
-
|
145
|
-
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
|
146
|
-
assert_equal %q|UPDATE "mytable" SET "myfield" = ?, "countofthings" = ? WHERE "user_id" = ?|, ss.to_s
|
147
|
-
end
|
148
|
-
|
149
102
|
def assert_faster_than(target_seconds)
|
150
103
|
t1 = ::Time.now
|
151
104
|
yield
|
data/test/unit/store_test.rb
CHANGED
@@ -3,90 +3,21 @@ require 'test_helper'
|
|
3
3
|
require 'scout_apm/store'
|
4
4
|
|
5
5
|
class FakeFailingLayaway
|
6
|
-
attr_reader :rps_written
|
7
6
|
def write_reporting_period(rp)
|
8
|
-
|
9
|
-
@rps_written << rp
|
7
|
+
raise "Always fails. Sucks."
|
10
8
|
end
|
11
9
|
end
|
12
10
|
|
13
11
|
class StoreTest < Minitest::Test
|
14
12
|
# TODO: Introduce a clock object to avoid having to use 'force'
|
15
13
|
def test_writing_layaway_removes_timestamps
|
16
|
-
s = ScoutApm::Store.new
|
14
|
+
s = ScoutApm::Store.new
|
17
15
|
s.track_one!("Controller", "user/show", 10)
|
18
16
|
|
19
|
-
assert_equal(1, s.
|
17
|
+
assert_equal(1, s.reporting_periods.size)
|
20
18
|
|
21
19
|
s.write_to_layaway(FakeFailingLayaway.new, true)
|
22
20
|
|
23
|
-
assert_equal({}, s.
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_writing_layaway_removes_stale_timestamps
|
27
|
-
context = ScoutApm::AgentContext.new
|
28
|
-
current_time = Time.now.utc
|
29
|
-
current_rp = ScoutApm::StoreReportingPeriod.new(current_time, context)
|
30
|
-
stale_rp = ScoutApm::StoreReportingPeriod.new(current_time - current_time.sec - 120, context)
|
31
|
-
|
32
|
-
s = ScoutApm::Store.new(context)
|
33
|
-
ScoutApm::Instruments::Process::ProcessMemory.new(context).metrics(stale_rp.timestamp, s)
|
34
|
-
ScoutApm::Instruments::Process::ProcessMemory.new(context).metrics(current_rp.timestamp, s)
|
35
|
-
assert_equal 2, s.instance_variable_get('@reporting_periods').size
|
36
|
-
|
37
|
-
s.write_to_layaway(FakeFailingLayaway.new, true)
|
38
|
-
|
39
|
-
assert_equal({}, s.instance_variable_get('@reporting_periods'))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class StoreReportingPeriodTest < Minitest::Test
|
44
|
-
HistogramReport = ScoutApm::Instruments::HistogramReport
|
45
|
-
|
46
|
-
attr_reader :subject
|
47
|
-
|
48
|
-
def setup
|
49
|
-
@subject = ScoutApm::StoreReportingPeriod.new(ScoutApm::StoreReportingPeriodTimestamp.new(Time.now), ScoutApm::AgentContext.new)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Check default values at creation time
|
53
|
-
def test_empty_values
|
54
|
-
assert_equal [], subject.histograms
|
55
|
-
assert_equal ScoutApm::ScoredItemSet.new, subject.request_traces
|
56
|
-
assert_equal ScoutApm::ScoredItemSet.new, subject.job_traces
|
57
|
-
assert_equal ScoutApm::MetricSet.new, subject.metric_set
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_merge_histograms
|
61
|
-
histogramFoo1 = histogram
|
62
|
-
histogramFoo2 = histogram
|
63
|
-
histogramBar1 = histogram
|
64
|
-
histogramBar2 = histogram
|
65
|
-
|
66
|
-
# This assertion may be fragile to reordering in the merge_histograms! function.
|
67
|
-
histogramFoo1.expects(:combine!).with(histogramFoo2)
|
68
|
-
histogramBar1.expects(:combine!).with(histogramBar2)
|
69
|
-
|
70
|
-
subject.merge_histograms!([
|
71
|
-
HistogramReport.new("foo", histogramFoo1),
|
72
|
-
HistogramReport.new("bar", histogramBar1),
|
73
|
-
])
|
74
|
-
|
75
|
-
subject.merge_histograms!([
|
76
|
-
HistogramReport.new("foo", histogramFoo2),
|
77
|
-
HistogramReport.new("bar", histogramBar2),
|
78
|
-
])
|
79
|
-
|
80
|
-
result = subject.histograms
|
81
|
-
assert_equal 2, result.length
|
82
|
-
assert_equal ["bar", "foo"], result.map(&:name).sort
|
83
|
-
end
|
84
|
-
|
85
|
-
###############################################################################
|
86
|
-
# Helpers
|
87
|
-
###############################################################################
|
88
|
-
def histogram
|
89
|
-
max_bins = 20
|
90
|
-
ScoutApm::NumericHistogram.new(max_bins)
|
21
|
+
assert_equal({}, s.reporting_periods)
|
91
22
|
end
|
92
23
|
end
|