appsignal 2.8.4.beta.1 → 2.9.18.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- data/.github/ISSUE_TEMPLATE/chore.md +14 -0
- data/.gitignore +2 -3
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +7 -16
- data/.travis.yml +28 -27
- data/CHANGELOG.md +657 -533
- data/README.md +31 -3
- data/Rakefile +128 -129
- data/SUPPORT.md +16 -0
- data/appsignal.gemspec +17 -4
- data/build_matrix.yml +21 -9
- data/ext/Rakefile +23 -17
- data/ext/agent.yml +40 -37
- data/ext/base.rb +116 -31
- data/ext/extconf.rb +34 -28
- data/gemfiles/capistrano2.gemfile +5 -0
- data/gemfiles/capistrano3.gemfile +5 -0
- data/gemfiles/grape.gemfile +5 -0
- data/gemfiles/no_dependencies.gemfile +5 -0
- data/gemfiles/padrino.gemfile +5 -0
- data/gemfiles/que.gemfile +5 -0
- data/gemfiles/que_beta.gemfile +10 -0
- data/gemfiles/rails-3.2.gemfile +5 -0
- data/gemfiles/rails-4.0.gemfile +5 -0
- data/gemfiles/rails-4.1.gemfile +5 -0
- data/gemfiles/rails-4.2.gemfile +5 -0
- data/gemfiles/rails-6.0.gemfile +5 -0
- data/gemfiles/resque.gemfile +5 -0
- data/lib/appsignal.rb +14 -492
- data/lib/appsignal/cli/demo.rb +5 -2
- data/lib/appsignal/cli/diagnose.rb +84 -4
- data/lib/appsignal/cli/diagnose/paths.rb +0 -5
- data/lib/appsignal/cli/diagnose/utils.rb +19 -0
- data/lib/appsignal/cli/helpers.rb +6 -0
- data/lib/appsignal/cli/install.rb +45 -15
- data/lib/appsignal/cli/notify_of_deploy.rb +10 -0
- data/lib/appsignal/config.rb +1 -2
- data/lib/appsignal/event_formatter.rb +4 -5
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +10 -8
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +60 -59
- data/lib/appsignal/extension.rb +2 -2
- data/lib/appsignal/helpers/instrumentation.rb +494 -0
- data/lib/appsignal/helpers/metrics.rb +54 -0
- data/lib/appsignal/hooks.rb +11 -8
- data/lib/appsignal/hooks/active_support_notifications.rb +2 -5
- data/lib/appsignal/hooks/puma.rb +74 -11
- data/lib/appsignal/hooks/sequel.rb +1 -1
- data/lib/appsignal/hooks/sidekiq.rb +115 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +7 -0
- data/lib/appsignal/integrations/que.rb +9 -8
- data/lib/appsignal/integrations/railtie.rb +2 -1
- data/lib/appsignal/marker.rb +2 -3
- data/lib/appsignal/minutely.rb +188 -19
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -1
- data/lib/appsignal/system.rb +16 -18
- data/lib/appsignal/transaction.rb +8 -0
- data/lib/appsignal/utils/rails_helper.rb +20 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/puma/plugin/appsignal.rb +26 -0
- data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +40 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +129 -22
- data/spec/lib/appsignal/cli/install_spec.rb +57 -8
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +10 -0
- data/spec/lib/appsignal/config_spec.rb +13 -11
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +38 -28
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +6 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +168 -69
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +104 -25
- data/spec/lib/appsignal/hooks/puma_spec.rb +251 -34
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +209 -0
- data/spec/lib/appsignal/hooks_spec.rb +4 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +24 -1
- data/spec/lib/appsignal/minutely_spec.rb +318 -26
- data/spec/lib/appsignal/system_spec.rb +0 -35
- data/spec/lib/appsignal/transaction_spec.rb +68 -10
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +39 -31
- data/spec/lib/appsignal/utils/json_spec.rb +7 -3
- data/spec/lib/appsignal_spec.rb +98 -22
- data/spec/lib/puma/appsignal_spec.rb +91 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/application.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/appsignal.yml +1 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/development.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/production.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/test.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/log/.gitkeep +0 -0
- data/spec/support/helpers/config_helpers.rb +1 -1
- data/spec/support/helpers/log_helpers.rb +6 -0
- data/spec/support/helpers/wait_for_helper.rb +28 -0
- data/spec/support/mocks/mock_probe.rb +11 -0
- data/spec/support/stubs/sidekiq/api.rb +4 -0
- metadata +43 -31
- data/spec/support/fixtures/containers/cgroups/docker +0 -14
- data/spec/support/fixtures/containers/cgroups/docker_systemd +0 -8
- data/spec/support/fixtures/containers/cgroups/lxc +0 -10
- data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
- data/spec/support/fixtures/containers/cgroups/none +0 -1
@@ -116,6 +116,9 @@ describe Appsignal::CLI::NotifyOfDeploy do
|
|
116
116
|
|
117
117
|
context "with required options" do
|
118
118
|
let(:options) { { :environment => "production", :revision => "aaaaa", :user => "thijs" } }
|
119
|
+
let(:log_stream) { std_stream }
|
120
|
+
let(:log) { log_contents(log_stream) }
|
121
|
+
before { Appsignal.logger = test_logger(log_stream) }
|
119
122
|
|
120
123
|
it "notifies of a deploy" do
|
121
124
|
run
|
@@ -124,6 +127,13 @@ describe Appsignal::CLI::NotifyOfDeploy do
|
|
124
127
|
expect(output).to include_deploy_notification_with(options)
|
125
128
|
end
|
126
129
|
|
130
|
+
it "prints a deprecation message" do
|
131
|
+
run
|
132
|
+
deprecation_message = "This command (appsignal notify_of_deploy) has been deprecated"
|
133
|
+
expect(output).to include("appsignal WARNING: #{deprecation_message}")
|
134
|
+
expect(log).to contains_log :warn, deprecation_message
|
135
|
+
end
|
136
|
+
|
127
137
|
context "with no app name configured" do
|
128
138
|
before { ENV["APPSIGNAL_APP_NAME"] = "" }
|
129
139
|
|
@@ -130,7 +130,7 @@ describe Appsignal::Config do
|
|
130
130
|
:enable_allocation_tracking => true,
|
131
131
|
:enable_gc_instrumentation => false,
|
132
132
|
:enable_host_metrics => true,
|
133
|
-
:enable_minutely_probes =>
|
133
|
+
:enable_minutely_probes => true,
|
134
134
|
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
135
135
|
:dns_servers => [],
|
136
136
|
:files_world_accessible => true,
|
@@ -202,14 +202,16 @@ describe Appsignal::Config do
|
|
202
202
|
context "with a config file" do
|
203
203
|
let(:config) { project_fixture_config("production") }
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
205
|
+
context "with valid config" do
|
206
|
+
it "is valid and active" do
|
207
|
+
expect(config.valid?).to be_truthy
|
208
|
+
expect(config.active?).to be_truthy
|
209
|
+
end
|
209
210
|
|
210
|
-
|
211
|
-
|
212
|
-
|
211
|
+
it "does not log an error" do
|
212
|
+
log = capture_logs { config }
|
213
|
+
expect(log).to_not contains_log(:error)
|
214
|
+
end
|
213
215
|
end
|
214
216
|
|
215
217
|
it "sets the file_config" do
|
@@ -218,7 +220,8 @@ describe Appsignal::Config do
|
|
218
220
|
:active => true,
|
219
221
|
:push_api_key => "abc",
|
220
222
|
:name => "TestApp",
|
221
|
-
:request_headers => kind_of(Array)
|
223
|
+
:request_headers => kind_of(Array),
|
224
|
+
:enable_minutely_probes => false
|
222
225
|
)
|
223
226
|
end
|
224
227
|
|
@@ -476,7 +479,7 @@ describe Appsignal::Config do
|
|
476
479
|
|
477
480
|
it "writes the current config to environment variables" do
|
478
481
|
expect(ENV["_APPSIGNAL_ACTIVE"]).to eq "true"
|
479
|
-
expect(ENV["_APPSIGNAL_APP_PATH"]).to end_with("spec/support/
|
482
|
+
expect(ENV["_APPSIGNAL_APP_PATH"]).to end_with("spec/support/fixtures/projects/valid")
|
480
483
|
expect(ENV["_APPSIGNAL_AGENT_PATH"]).to end_with("/ext")
|
481
484
|
expect(ENV["_APPSIGNAL_DEBUG_LOGGING"]).to eq "false"
|
482
485
|
expect(ENV["_APPSIGNAL_LOG"]).to eq "stdout"
|
@@ -492,7 +495,6 @@ describe Appsignal::Config do
|
|
492
495
|
expect(ENV["_APPSIGNAL_IGNORE_NAMESPACES"]).to eq "admin,private_namespace"
|
493
496
|
expect(ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"]).to eq "false"
|
494
497
|
expect(ENV["_APPSIGNAL_ENABLE_HOST_METRICS"]).to eq "true"
|
495
|
-
expect(ENV["_APPSIGNAL_ENABLE_MINUTELY_PROBES"]).to eq "false"
|
496
498
|
expect(ENV["_APPSIGNAL_HOSTNAME"]).to eq ""
|
497
499
|
expect(ENV["_APPSIGNAL_PROCESS_NAME"]).to include "rspec"
|
498
500
|
expect(ENV["_APPSIGNAL_CA_FILE_PATH"]).to eq File.join(resources_dir, "cacert.pem")
|
@@ -1,43 +1,53 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
describe Appsignal::EventFormatter::ActionView::RenderFormatter do
|
2
|
+
let(:klass) { Appsignal::EventFormatter::ActionView::RenderFormatter }
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
let(:klass) { Appsignal::EventFormatter::ActionView::RenderFormatter }
|
7
|
-
let(:formatter) { klass.new }
|
4
|
+
if DependencyHelper.rails_present?
|
5
|
+
require "action_view"
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
context "when in a Rails app" do
|
8
|
+
let(:formatter) { klass.new }
|
9
|
+
before { allow(Rails.root).to receive(:to_s).and_return("/var/www/app/20130101") }
|
10
|
+
|
11
|
+
it "registers render_partial.action_view and render_template.action_view" do
|
12
|
+
expect(Appsignal::EventFormatter.registered?("render_partial.action_view", klass)).to be_truthy
|
13
|
+
expect(Appsignal::EventFormatter.registered?("render_template.action_view", klass)).to be_truthy
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
describe "#root_path" do
|
17
|
+
subject { formatter.root_path }
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
it "returns Rails root path" do
|
20
|
+
is_expected.to eq "/var/www/app/20130101/"
|
21
|
+
end
|
19
22
|
end
|
20
|
-
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
describe "#format" do
|
25
|
+
subject { formatter.format(payload) }
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
context "with an identifier" do
|
28
|
+
let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb" } }
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
+
context "with a frozen identifier" do
|
34
|
+
let(:payload) { { :identifier => "/var/www/app/20130101/app/views/home/index/html.erb".freeze } }
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
it { is_expected.to eq ["app/views/home/index/html.erb", nil] }
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
+
context "without an identifier" do
|
40
|
+
let(:payload) { {} }
|
39
41
|
|
40
|
-
|
42
|
+
it { is_expected.to be_nil }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
else
|
47
|
+
context "when not in a Rails app" do
|
48
|
+
it "does not register the event formatter" do
|
49
|
+
expect(Appsignal::EventFormatter.registered?("render_partial.action_view", klass)).to be_falsy
|
50
|
+
expect(Appsignal::EventFormatter.registered?("render_template.action_view", klass)).to be_falsy
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
@@ -16,6 +16,12 @@ describe Appsignal::EventFormatter::Moped::QueryFormatter do
|
|
16
16
|
it { is_expected.to be_nil }
|
17
17
|
end
|
18
18
|
|
19
|
+
context "when ops is nil in the payload" do
|
20
|
+
let(:payload) { { :ops => nil } }
|
21
|
+
|
22
|
+
it { is_expected.to be_nil }
|
23
|
+
end
|
24
|
+
|
19
25
|
context "Moped::Protocol::Command" do
|
20
26
|
let(:op) do
|
21
27
|
double(
|
@@ -10,9 +10,10 @@ class MockFormatter < Appsignal::EventFormatter
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
class
|
14
|
-
|
15
|
-
|
13
|
+
class MockFormatterDouble < MockFormatter
|
14
|
+
end
|
15
|
+
|
16
|
+
class MissingFormatMockFormatter
|
16
17
|
end
|
17
18
|
|
18
19
|
class IncorrectFormatMockFormatter < Appsignal::EventFormatter
|
@@ -20,109 +21,207 @@ class IncorrectFormatMockFormatter < Appsignal::EventFormatter
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
24
|
+
class IncorrectFormatMock2Formatter < Appsignal::EventFormatter
|
25
|
+
def format(_payload, _foo = nil)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
23
29
|
class MockDependentFormatter < Appsignal::EventFormatter
|
24
30
|
def initialize
|
25
31
|
NonsenseDependency.something
|
26
32
|
end
|
27
|
-
end
|
28
33
|
|
29
|
-
|
30
|
-
|
34
|
+
def format(_payload)
|
35
|
+
end
|
36
|
+
end
|
31
37
|
|
32
38
|
describe Appsignal::EventFormatter do
|
33
|
-
|
34
|
-
|
39
|
+
let(:klass) { described_class }
|
40
|
+
around do |example|
|
41
|
+
original_formatters = described_class.formatters
|
42
|
+
example.run
|
43
|
+
described_class.class_variable_set(:@@formatters, original_formatters)
|
35
44
|
end
|
36
45
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
Class.new(Appsignal::EventFormatter) do
|
41
|
-
register "mock.deprecated"
|
42
|
-
|
43
|
-
def format(_payload)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
46
|
+
describe ".register" do
|
47
|
+
it "registers a formatter" do
|
48
|
+
expect(klass.registered?("mock")).to be_falsy
|
47
49
|
|
48
|
-
|
49
|
-
let(:out_stream) { std_stream }
|
50
|
-
let(:output) { out_stream.read }
|
50
|
+
klass.register "mock", MockFormatter
|
51
51
|
|
52
|
-
it "registers a formatter" do
|
53
52
|
expect(klass.formatters["mock"]).to be_instance_of(MockFormatter)
|
53
|
+
expect(klass.formatter_classes["mock"]).to eq MockFormatter
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
context "when a formatter with the name already exists" do
|
57
|
+
it "does not register the formatter again" do
|
58
|
+
logs = capture_logs do
|
59
|
+
klass.register("mock.twice", MockFormatter)
|
60
|
+
klass.register("mock.twice", MockFormatter)
|
61
|
+
end
|
62
|
+
expect(klass.registered?("mock.twice")).to be_truthy
|
63
|
+
expect(logs).to contains_log :warn, \
|
64
|
+
"Formatter for 'mock.twice' already registered, not registering 'MockFormatter'"
|
65
|
+
end
|
61
66
|
end
|
62
67
|
|
63
|
-
|
64
|
-
|
68
|
+
context "when there is an error initializing the formatter" do
|
69
|
+
it "does not register the formatter and logs an error" do
|
70
|
+
logs = capture_logs do
|
71
|
+
described_class.register "mock.dependent", MockDependentFormatter
|
72
|
+
end
|
73
|
+
expect(klass.registered?("mock.dependent")).to be_falsy
|
74
|
+
expect(logs).to contains_log :error, \
|
75
|
+
"'uninitialized constant MockDependentFormatter::NonsenseDependency' " \
|
76
|
+
"when initializing mock.dependent event formatter"
|
77
|
+
end
|
65
78
|
end
|
66
79
|
|
67
|
-
|
68
|
-
|
80
|
+
context "when formatter has no format/1 method" do
|
81
|
+
context "when the formatter has no format method" do
|
82
|
+
it "does not register the formatter and logs an error" do
|
83
|
+
logs = capture_logs do
|
84
|
+
described_class.register "mock.missing", MissingFormatMockFormatter
|
85
|
+
end
|
86
|
+
expect(klass.registered?("mock.missing")).to be_falsy
|
87
|
+
expect(logs).to contains_log :error, \
|
88
|
+
"'MissingFormatMockFormatter does not have a format(payload) " \
|
89
|
+
"method' when initializing mock.missing event formatter"
|
90
|
+
end
|
91
|
+
end
|
69
92
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
93
|
+
context "when the formatter has an format/0 method" do
|
94
|
+
it "does not register the formatter and logs an error" do
|
95
|
+
logs = capture_logs do
|
96
|
+
described_class.register "mock.incorrect", IncorrectFormatMockFormatter
|
97
|
+
end
|
98
|
+
expect(klass.registered?("mock.incorrect")).to be_falsy
|
99
|
+
expect(logs).to contains_log :error, \
|
100
|
+
"'IncorrectFormatMockFormatter does not have a format(payload) " \
|
101
|
+
"method' when initializing mock.incorrect event formatter"
|
102
|
+
end
|
103
|
+
end
|
75
104
|
|
76
|
-
|
77
|
-
|
105
|
+
context "when formatter has an format/2 method" do
|
106
|
+
it "does not register the formatter and logs an error" do
|
107
|
+
logs = capture_logs do
|
108
|
+
described_class.register "mock.incorrect", IncorrectFormatMock2Formatter
|
109
|
+
end
|
110
|
+
expect(klass.registered?("mock.incorrect")).to be_falsy
|
111
|
+
expect(logs).to contains_log :error, \
|
112
|
+
"'IncorrectFormatMock2Formatter does not have a format(payload) " \
|
113
|
+
"method' when initializing mock.incorrect event formatter"
|
114
|
+
end
|
115
|
+
end
|
78
116
|
end
|
79
117
|
|
80
|
-
|
81
|
-
|
118
|
+
context "when registering deprecated formatters" do
|
119
|
+
let(:stdout_stream) { std_stream }
|
120
|
+
let(:deprecated_formatter) do
|
121
|
+
Class.new(Appsignal::EventFormatter) do
|
122
|
+
register "mock.deprecated"
|
82
123
|
|
83
|
-
|
84
|
-
|
124
|
+
def format(_payload)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
85
128
|
|
86
|
-
|
87
|
-
|
88
|
-
|
129
|
+
it "registers deprecated formatters and logs & prints a warning" do
|
130
|
+
message = "Formatter for 'mock.deprecated' is using a deprecated registration method. " \
|
131
|
+
"This event formatter will not be loaded. " \
|
132
|
+
"Please update the formatter according to the documentation at: " \
|
133
|
+
"https://docs.appsignal.com/ruby/instrumentation/event-formatters.html"
|
134
|
+
|
135
|
+
logs = capture_logs do
|
136
|
+
capture_stdout(stdout_stream) { deprecated_formatter }
|
137
|
+
end
|
138
|
+
expect(logs).to contains_log :warn, message
|
139
|
+
expect(stdout_stream.read).to include "appsignal WARNING: #{message}"
|
140
|
+
|
141
|
+
expect(klass.deprecated_formatter_classes.keys).to include("mock.deprecated")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "initializes deprecated formatters" do
|
145
|
+
capture_stdout(stdout_stream) { deprecated_formatter }
|
146
|
+
klass.initialize_deprecated_formatters
|
89
147
|
|
90
|
-
|
91
|
-
|
92
|
-
.
|
93
|
-
|
94
|
-
klass.register("mock.twice", MockFormatter)
|
148
|
+
expect(klass.registered?("mock.deprecated")).to be_truthy
|
149
|
+
expect(klass.formatters["mock.deprecated"]).to be_instance_of(deprecated_formatter)
|
150
|
+
expect(klass.deprecated_formatter_classes["mock.deprecated"]).to eq(deprecated_formatter)
|
151
|
+
end
|
95
152
|
end
|
153
|
+
end
|
96
154
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
"
|
101
|
-
|
102
|
-
|
155
|
+
describe ".registered?" do
|
156
|
+
context "when checking by name" do
|
157
|
+
context "when there is a formatter with that name" do
|
158
|
+
it "returns true" do
|
159
|
+
klass.register "mock", MockFormatter
|
160
|
+
expect(klass.registered?("mock")).to be_truthy
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when there is no formatter with that name" do
|
165
|
+
it "returns false" do
|
166
|
+
expect(klass.registered?("nonsense")).to be_falsy
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
103
170
|
|
104
|
-
|
105
|
-
|
171
|
+
context "when checking by name and class" do
|
172
|
+
context "when there is a formatter with that name and class" do
|
173
|
+
it "returns true" do
|
174
|
+
klass.register "mock", MockFormatter
|
175
|
+
expect(klass.registered?("mock", MockFormatter)).to be_truthy
|
176
|
+
end
|
177
|
+
end
|
106
178
|
|
107
|
-
|
179
|
+
context "when there is no formatter with that name and class" do
|
180
|
+
it "returns false" do
|
181
|
+
klass.register "mock", MockFormatterDouble
|
182
|
+
expect(klass.registered?("mock", MockFormatter)).to be_falsy
|
183
|
+
end
|
184
|
+
end
|
108
185
|
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe ".unregister" do
|
189
|
+
context "when a formatter with the name is registered" do
|
190
|
+
it "unregisters the formatter has the same class" do
|
191
|
+
klass.register("mock.unregister", MockFormatter)
|
192
|
+
expect(klass.registered?("mock.unregister")).to be_truthy
|
109
193
|
|
110
|
-
|
111
|
-
|
112
|
-
capture_stdout(out_stream) { deprecated_formatter }
|
113
|
-
Appsignal::EventFormatter.initialize_deprecated_formatters
|
194
|
+
klass.unregister("mock.unregister", Hash)
|
195
|
+
expect(klass.registered?("mock.unregister")).to be_truthy
|
114
196
|
|
115
|
-
|
197
|
+
klass.unregister("mock.unregister", MockFormatter)
|
198
|
+
expect(klass.registered?("mock.unregister")).to be_falsy
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "when a formatter with the same name and class is not registered" do
|
203
|
+
it "unregisters nothing" do
|
204
|
+
expect do
|
205
|
+
expect do
|
206
|
+
klass.unregister("nonse.unregister", MockFormatter)
|
207
|
+
end.to_not(change { klass.formatters })
|
208
|
+
end.to_not(change { klass.formatter_classes })
|
209
|
+
end
|
116
210
|
end
|
117
211
|
end
|
118
212
|
|
119
|
-
|
120
|
-
|
121
|
-
|
213
|
+
describe ".format" do
|
214
|
+
context "when no formatter with the name is registered" do
|
215
|
+
it "returns nil" do
|
216
|
+
expect(klass.format("nonsense", {})).to be_nil
|
217
|
+
end
|
122
218
|
end
|
123
219
|
|
124
|
-
|
125
|
-
|
220
|
+
context "when a formatter with the name is registered" do
|
221
|
+
it "calls the formatter and use a value set in the initializer" do
|
222
|
+
klass.register "mock", MockFormatter
|
223
|
+
expect(klass.format("mock", {})).to eq ["title", "some value"]
|
224
|
+
end
|
126
225
|
end
|
127
226
|
end
|
128
227
|
end
|