appsignal 3.9.3-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +22 -19
  3. data/CHANGELOG.md +92 -0
  4. data/README.md +0 -1
  5. data/Rakefile +1 -1
  6. data/build_matrix.yml +10 -12
  7. data/gemfiles/webmachine1.gemfile +5 -4
  8. data/lib/appsignal/config.rb +4 -0
  9. data/lib/appsignal/environment.rb +6 -1
  10. data/lib/appsignal/helpers/instrumentation.rb +163 -1
  11. data/lib/appsignal/hooks/active_job.rb +1 -6
  12. data/lib/appsignal/integrations/padrino.rb +21 -25
  13. data/lib/appsignal/integrations/rake.rb +46 -12
  14. data/lib/appsignal/integrations/sidekiq.rb +1 -11
  15. data/lib/appsignal/integrations/webmachine.rb +15 -9
  16. data/lib/appsignal/rack/abstract_middleware.rb +49 -12
  17. data/lib/appsignal/rack/body_wrapper.rb +143 -0
  18. data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
  19. data/lib/appsignal/rack/grape_middleware.rb +1 -1
  20. data/lib/appsignal/rack/hanami_middleware.rb +1 -1
  21. data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
  22. data/lib/appsignal/rack/rails_instrumentation.rb +1 -3
  23. data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
  24. data/lib/appsignal/rack/streaming_listener.rb +13 -59
  25. data/lib/appsignal/rack.rb +31 -0
  26. data/lib/appsignal/transaction.rb +50 -8
  27. data/lib/appsignal/version.rb +1 -1
  28. data/lib/appsignal.rb +3 -1
  29. data/spec/lib/appsignal/config_spec.rb +1 -0
  30. data/spec/lib/appsignal/hooks/rake_spec.rb +100 -17
  31. data/spec/lib/appsignal/integrations/padrino_spec.rb +181 -131
  32. data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -2
  33. data/spec/lib/appsignal/integrations/webmachine_spec.rb +65 -17
  34. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +96 -8
  35. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
  36. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -17
  37. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +1 -1
  38. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
  39. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +43 -120
  40. data/spec/lib/appsignal/transaction_spec.rb +163 -4
  41. data/spec/lib/appsignal_spec.rb +197 -6
  42. data/spec/support/mocks/dummy_app.rb +1 -1
  43. metadata +8 -4
  44. data/support/check_versions +0 -22
@@ -1,146 +1,69 @@
1
- require "appsignal/rack/streaming_listener"
2
-
3
- describe Appsignal::Rack::StreamingListener do
4
- let(:env) do
5
- {
6
- "rack.input" => StringIO.new,
7
- "REQUEST_METHOD" => "GET",
8
- "PATH_INFO" => "/homepage",
9
- "QUERY_STRING" => "param=something"
10
- }
1
+ describe "Appsignal::Rack::StreamingListener" do
2
+ def load_middleware
3
+ load "lib/appsignal/rack/streaming_listener.rb"
11
4
  end
12
- let(:app) { DummyApp.new }
13
- let(:listener) { Appsignal::Rack::StreamingListener.new(app, {}) }
14
- before(:context) { start_agent }
15
- around { |example| keep_transactions { example.run } }
16
5
 
17
- describe "#call" do
18
- context "when Appsignal is not active" do
19
- before { allow(Appsignal).to receive(:active?).and_return(false) }
6
+ describe "loading the streaming_listener integrations file" do
7
+ let(:err_stream) { std_stream }
8
+ let(:stderr) { err_stream.read }
9
+ after { Appsignal::Rack.send(:remove_const, :StreamingListener) }
20
10
 
21
- it "does not create a transaction" do
22
- expect do
23
- listener.call(env)
24
- end.to_not(change { created_transactions.count })
11
+ it "prints a deprecation warning to STDERR" do
12
+ capture_std_streams(std_stream, err_stream) do
13
+ load_middleware
25
14
  end
26
15
 
27
- it "calls the app" do
28
- listener.call(env)
29
-
30
- expect(app).to be_called
31
- end
16
+ expect(stderr).to include(
17
+ "appsignal WARNING: The constant Appsignal::Rack::StreamingListener " \
18
+ "has been deprecated."
19
+ )
32
20
  end
33
21
 
34
- context "when Appsignal is active" do
35
- before { allow(Appsignal).to receive(:active?).and_return(true) }
36
-
37
- let(:wrapper) { Appsignal::StreamWrapper.new("body", transaction) }
38
- let(:raw_payload) { { :foo => :bar } }
39
- before { allow(listener).to receive(:raw_payload).and_return(raw_payload) }
40
-
41
- it "creates a transaction" do
42
- expect do
43
- listener.call(env)
44
- end.to(change { created_transactions.count }.by(1))
45
- end
46
-
47
- it "instruments the call" do
48
- listener.call(env)
49
-
50
- expect(last_transaction).to include_event("name" => "process_action.rack")
51
- end
52
-
53
- it "set `appsignal.action` to the action name" do
54
- env["appsignal.action"] = "Action"
55
-
56
- listener.call(env)
57
-
58
- expect(last_transaction).to have_action("Action")
59
- end
60
-
61
- it "adds the path, method and queue start to the transaction" do
62
- listener.call(env)
63
-
64
- expect(last_transaction).to include_metadata(
65
- "path" => "/homepage",
66
- "method" => "GET"
67
- )
68
- expect(last_transaction).to have_queue_start
69
- end
70
-
71
- context "with an exception in the instrumentation call" do
72
- let(:error) { ExampleException.new("error message") }
73
- let(:app) { DummyApp.new { raise error } }
74
-
75
- it "adds the exception to the transaction" do
76
- expect do
77
- listener.call(env)
78
- end.to raise_error(error)
79
-
80
- expect(last_transaction).to have_error("ExampleException", "error message")
22
+ it "logs a warning" do
23
+ logs =
24
+ capture_logs do
25
+ silence do
26
+ load_middleware
27
+ end
81
28
  end
82
- end
83
29
 
84
- it "wraps the body in a wrapper" do
85
- _, _, body = listener.call(env)
86
-
87
- expect(body).to be_a(Appsignal::StreamWrapper)
88
- end
30
+ expect(logs).to contains_log(
31
+ :warn,
32
+ "The constant Appsignal::Rack::StreamingListener has been deprecated."
33
+ )
89
34
  end
90
35
  end
91
- end
92
-
93
- describe Appsignal::StreamWrapper do
94
- let(:stream) { double }
95
- let(:transaction) { http_request_transaction }
96
- let(:wrapper) { Appsignal::StreamWrapper.new(stream, transaction) }
97
- before do
98
- start_agent
99
- set_current_transaction(transaction)
100
- end
101
- around { |example| keep_transactions { example.run } }
102
36
 
103
- describe "#each" do
104
- it "calls the original stream" do
105
- expect(stream).to receive(:each)
37
+ describe "middleware" do
38
+ let(:env) { {} }
39
+ let(:app) { DummyApp.new }
40
+ let(:middleware) { Appsignal::Rack::StreamingListener.new(app, {}) }
41
+ around { |example| keep_transactions { example.run } }
42
+ before(:context) { load_middleware }
43
+ before { start_agent }
106
44
 
107
- wrapper.each
45
+ def make_request
46
+ middleware.call(env)
108
47
  end
109
48
 
110
- context "when #each raises an error" do
111
- let(:error) { ExampleException.new("error message") }
112
-
113
- it "records the exception" do
114
- allow(stream).to receive(:each).and_raise(error)
49
+ it "instruments the call" do
50
+ make_request
115
51
 
116
- expect { wrapper.send(:each) }.to raise_error(error)
117
-
118
- expect(transaction).to have_error("ExampleException", "error message")
119
- end
52
+ expect(last_transaction).to include_event("name" => "process_streaming_request.rack")
120
53
  end
121
- end
122
-
123
- describe "#close" do
124
- it "closes the original stream and completes the transaction" do
125
- expect(stream).to receive(:close)
126
54
 
127
- wrapper.close
55
+ it "set no action by default" do
56
+ make_request
128
57
 
129
- expect(current_transaction?).to be_falsy
130
- expect(transaction).to be_completed
58
+ expect(last_transaction).to_not have_action
131
59
  end
132
60
 
133
- context "when #close raises an error" do
134
- let(:error) { ExampleException.new("error message") }
61
+ it "set `appsignal.action` to the action name" do
62
+ env["appsignal.action"] = "Action"
135
63
 
136
- it "records the exception and completes the transaction" do
137
- allow(stream).to receive(:close).and_raise(error)
64
+ make_request
138
65
 
139
- expect { wrapper.send(:close) }.to raise_error(error)
140
-
141
- expect(transaction).to have_error("ExampleException", "error message")
142
- expect(transaction).to be_completed
143
- end
66
+ expect(last_transaction).to have_action("Action")
144
67
  end
145
68
  end
146
69
  end
@@ -326,6 +326,16 @@ describe Appsignal::Transaction do
326
326
  it "returns custom parameters" do
327
327
  expect(subject).to eq(:foo => "bar")
328
328
  end
329
+
330
+ context "when params is a callable object" do
331
+ it "calls the params object and sets the return value as parametesr" do
332
+ transaction.set_params { { "param1" => "value1" } }
333
+
334
+ expect(transaction.params).to eq(
335
+ "param1" => "value1"
336
+ )
337
+ end
338
+ end
329
339
  end
330
340
 
331
341
  context "without custom params set on transaction" do
@@ -374,6 +384,25 @@ describe Appsignal::Transaction do
374
384
  expect(transaction.params).to eq(params)
375
385
  expect(transaction).to include_params(params)
376
386
  end
387
+
388
+ it "updates the params on the transaction with a block" do
389
+ params = { "key" => "value" }
390
+ transaction.set_params { params }
391
+
392
+ transaction._sample
393
+ expect(transaction.params).to eq(params)
394
+ expect(transaction).to include_params(params)
395
+ end
396
+
397
+ it "updates with the params argument when both an argument and block are given" do
398
+ arg_params = { "argument" => "value" }
399
+ block_params = { "block" => "value" }
400
+ transaction.set_params(arg_params) { block_params }
401
+
402
+ transaction._sample
403
+ expect(transaction.params).to eq(arg_params)
404
+ expect(transaction).to include_params(arg_params)
405
+ end
377
406
  end
378
407
 
379
408
  context "when the given params is nil" do
@@ -402,6 +431,25 @@ describe Appsignal::Transaction do
402
431
  expect(transaction).to include_params(params)
403
432
  end
404
433
 
434
+ it "updates the params on the transaction with a block" do
435
+ params = { "key" => "value" }
436
+ transaction.set_params_if_nil { params }
437
+
438
+ transaction._sample
439
+ expect(transaction.params).to eq(params)
440
+ expect(transaction).to include_params(params)
441
+ end
442
+
443
+ it "updates with the params argument when both an argument and block are given" do
444
+ arg_params = { "argument" => "value" }
445
+ block_params = { "block" => "value" }
446
+ transaction.set_params_if_nil(arg_params) { block_params }
447
+
448
+ transaction._sample
449
+ expect(transaction.params).to eq(arg_params)
450
+ expect(transaction).to include_params(arg_params)
451
+ end
452
+
405
453
  context "when the given params is nil" do
406
454
  it "does not update the params on the transaction" do
407
455
  params = { "key" => "value" }
@@ -426,12 +474,24 @@ describe Appsignal::Transaction do
426
474
  expect(transaction.params).to eq(preset_params)
427
475
  expect(transaction).to include_params(preset_params)
428
476
  end
477
+
478
+ it "does not update the params with a block on the transaction" do
479
+ preset_params = { "other" => "params" }
480
+ params = { "key" => "value" }
481
+ transaction.set_params(preset_params)
482
+ transaction.set_params_if_nil { params }
483
+
484
+ transaction._sample
485
+ expect(transaction.params).to eq(preset_params)
486
+ expect(transaction).to include_params(preset_params)
487
+ end
429
488
  end
430
489
  end
431
490
 
432
491
  describe "#set_tags" do
433
492
  let(:long_string) { "a" * 10_001 }
434
- before do
493
+
494
+ it "stores tags on the transaction" do
435
495
  transaction.set_tags(
436
496
  :valid_key => "valid_value",
437
497
  "valid_string_key" => "valid_value",
@@ -443,10 +503,8 @@ describe Appsignal::Transaction do
443
503
  :too_long_value => long_string,
444
504
  long_string => "too_long_key"
445
505
  )
446
- transaction.sample_data
447
- end
506
+ transaction._sample
448
507
 
449
- it "stores tags on the transaction" do
450
508
  expect(transaction).to include_tags(
451
509
  "valid_key" => "valid_value",
452
510
  "valid_string_key" => "valid_value",
@@ -456,6 +514,96 @@ describe Appsignal::Transaction do
456
514
  long_string => "too_long_key"
457
515
  )
458
516
  end
517
+
518
+ it "merges the tags when called multiple times" do
519
+ transaction.set_tags(:key1 => "value1")
520
+ transaction.set_tags(:key2 => "value2")
521
+ transaction._sample
522
+
523
+ expect(transaction).to include_tags(
524
+ "key1" => "value1",
525
+ "key2" => "value2"
526
+ )
527
+ end
528
+ end
529
+
530
+ describe "#set_custom_data" do
531
+ let(:log_stream) { std_stream }
532
+ let(:logs) { log_contents(log_stream) }
533
+ around { |example| use_logger_with(log_stream) { example.run } }
534
+
535
+ it "stores custom Hash data on the transaction" do
536
+ transaction.set_custom_data(
537
+ :user => {
538
+ :id => 123,
539
+ :locale => "abc"
540
+ },
541
+ :organization => {
542
+ :slug => "appsignal",
543
+ :plan => "enterprise"
544
+ }
545
+ )
546
+
547
+ transaction._sample
548
+ expect(transaction).to include_custom_data(
549
+ "user" => {
550
+ "id" => 123,
551
+ "locale" => "abc"
552
+ },
553
+ "organization" => {
554
+ "slug" => "appsignal",
555
+ "plan" => "enterprise"
556
+ }
557
+ )
558
+ end
559
+
560
+ it "stores custom Array data on the transaction" do
561
+ transaction.set_custom_data([
562
+ [123, "abc"],
563
+ ["appsignal", "enterprise"]
564
+ ])
565
+
566
+ transaction._sample
567
+ expect(transaction).to include_custom_data([
568
+ [123, "abc"],
569
+ ["appsignal", "enterprise"]
570
+ ])
571
+ end
572
+
573
+ it "does not store non Hash or Array custom data" do
574
+ transaction.set_custom_data("abc")
575
+ transaction._sample
576
+ expect(transaction).to_not include_custom_data
577
+
578
+ transaction.set_custom_data(123)
579
+ transaction._sample
580
+ expect(transaction).to_not include_custom_data
581
+
582
+ transaction.set_custom_data(Object.new)
583
+ transaction._sample
584
+ expect(transaction).to_not include_custom_data
585
+
586
+ expect(logs).to contains_log(
587
+ :error,
588
+ "set_custom_data: Unsupported data type String received."
589
+ )
590
+ expect(logs).to contains_log(
591
+ :error,
592
+ "set_custom_data: Unsupported data type Integer received."
593
+ )
594
+ expect(logs).to contains_log(
595
+ :error,
596
+ "set_custom_data: Unsupported data type String received."
597
+ )
598
+ end
599
+
600
+ it "overwrites the custom data if called multiple times" do
601
+ transaction.set_custom_data("user" => { "id" => 123 })
602
+ transaction.set_custom_data("user" => { "id" => 456 })
603
+
604
+ transaction._sample
605
+ expect(transaction).to include_custom_data("user" => { "id" => 456 })
606
+ end
459
607
  end
460
608
 
461
609
  describe "#add_breadcrumb" do
@@ -811,6 +959,17 @@ describe Appsignal::Transaction do
811
959
  kind_of(Integer)
812
960
  )
813
961
  end
962
+
963
+ context "when params is a callable object" do
964
+ it "calls the params object and sets the return value as parametesr" do
965
+ transaction.set_params { { "param1" => "value1" } }
966
+
967
+ transaction.sample_data
968
+ expect(transaction).to include_params(
969
+ "param1" => "value1"
970
+ )
971
+ end
972
+ end
814
973
  end
815
974
 
816
975
  describe "#set_error" do
@@ -321,6 +321,20 @@ describe Appsignal do
321
321
  end
322
322
  end
323
323
 
324
+ describe ".report_error" do
325
+ let(:error) { ExampleException.new("specific error") }
326
+
327
+ it "does not raise an error" do
328
+ Appsignal.report_error(error)
329
+ end
330
+
331
+ it "does not create a transaction" do
332
+ expect do
333
+ Appsignal.report_error(error)
334
+ end.to_not(change { created_transactions.count })
335
+ end
336
+ end
337
+
324
338
  describe ".set_namespace" do
325
339
  it "does not raise an error" do
326
340
  Appsignal.set_namespace("custom")
@@ -332,6 +346,12 @@ describe Appsignal do
332
346
  Appsignal.tag_request(:tag => "tag")
333
347
  end
334
348
  end
349
+
350
+ describe ".set_custom_data" do
351
+ it "does not raise an error" do
352
+ Appsignal.set_custom_data(:data => "value")
353
+ end
354
+ end
335
355
  end
336
356
 
337
357
  context "with config and started" do
@@ -466,15 +486,13 @@ describe Appsignal do
466
486
  end
467
487
 
468
488
  describe ".tag_request" do
469
- around do |example|
470
- start_agent
471
- with_current_transaction(transaction) { example.run }
472
- end
489
+ before { start_agent }
473
490
 
474
491
  context "with transaction" do
475
492
  let(:transaction) { http_request_transaction }
493
+ before { set_current_transaction(transaction) }
476
494
 
477
- it "calls set_tags on the current transaction" do
495
+ it "sets tags on the current transaction" do
478
496
  Appsignal.tag_request("a" => "b")
479
497
 
480
498
  transaction._sample
@@ -494,7 +512,85 @@ describe Appsignal do
494
512
  end
495
513
 
496
514
  it "also listens to tag_job" do
497
- expect(Appsignal).to respond_to(:tag_job)
515
+ expect(Appsignal.method(:tag_job)).to eq(Appsignal.method(:tag_request))
516
+ end
517
+
518
+ it "also listens to set_tags" do
519
+ expect(Appsignal.method(:set_tags)).to eq(Appsignal.method(:tag_request))
520
+ end
521
+ end
522
+
523
+ describe ".set_params" do
524
+ before do
525
+ start_agent
526
+ end
527
+
528
+ context "with transaction" do
529
+ let(:transaction) { http_request_transaction }
530
+ before { set_current_transaction(transaction) }
531
+
532
+ it "sets parameters on the transaction" do
533
+ Appsignal.set_params("param1" => "value1")
534
+
535
+ transaction._sample
536
+ expect(transaction).to include_params("param1" => "value1")
537
+ end
538
+
539
+ it "overwrites the params if called multiple times" do
540
+ Appsignal.set_params("param1" => "value1")
541
+ Appsignal.set_params("param2" => "value2")
542
+
543
+ transaction._sample
544
+ expect(transaction).to include_params("param2" => "value2")
545
+ end
546
+
547
+ it "sets parameters with a block on the transaction" do
548
+ Appsignal.set_params { { "param1" => "value1" } }
549
+
550
+ transaction._sample
551
+ expect(transaction).to include_params("param1" => "value1")
552
+ end
553
+ end
554
+
555
+ context "without transaction" do
556
+ it "does not set tags on the transaction" do
557
+ Appsignal.set_params("a" => "b")
558
+
559
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_params)
560
+ end
561
+ end
562
+ end
563
+
564
+ describe ".set_custom_data" do
565
+ before { start_agent }
566
+
567
+ context "with transaction" do
568
+ let(:transaction) { http_request_transaction }
569
+ before { set_current_transaction transaction }
570
+
571
+ it "sets custom data on the current transaction" do
572
+ Appsignal.set_custom_data(
573
+ :user => { :id => 123 },
574
+ :organization => { :slug => "appsignal" }
575
+ )
576
+
577
+ transaction._sample
578
+ expect(transaction).to include_custom_data(
579
+ "user" => { "id" => 123 },
580
+ "organization" => { "slug" => "appsignal" }
581
+ )
582
+ end
583
+ end
584
+
585
+ context "without transaction" do
586
+ it "does not set tags on the transaction" do
587
+ Appsignal.set_custom_data(
588
+ :user => { :id => 123 },
589
+ :organization => { :slug => "appsignal" }
590
+ )
591
+
592
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_custom_data)
593
+ end
498
594
  end
499
595
  end
500
596
 
@@ -993,6 +1089,101 @@ describe Appsignal do
993
1089
  end
994
1090
  end
995
1091
 
1092
+ describe ".report_error" do
1093
+ let(:err_stream) { std_stream }
1094
+ let(:stderr) { err_stream.read }
1095
+ let(:error) { ExampleException.new("error message") }
1096
+ before { start_agent }
1097
+ around { |example| keep_transactions { example.run } }
1098
+
1099
+ context "when the error is not an Exception" do
1100
+ let(:error) { Object.new }
1101
+
1102
+ it "does not set an error" do
1103
+ silence { Appsignal.report_error(error) }
1104
+
1105
+ expect(last_transaction).to_not have_error
1106
+ end
1107
+
1108
+ it "logs an error" do
1109
+ logs = capture_logs { Appsignal.report_error(error) }
1110
+ expect(logs).to contains_log(
1111
+ :error,
1112
+ "Appsignal.report_error: Cannot set error. " \
1113
+ "The given value is not an exception: #{error.inspect}"
1114
+ )
1115
+ end
1116
+ end
1117
+
1118
+ context "when there is no active transaction" do
1119
+ it "creates a new transaction" do
1120
+ expect do
1121
+ Appsignal.report_error(error)
1122
+ end.to(change { created_transactions.count }.by(1))
1123
+ end
1124
+
1125
+ it "completes the transaction" do
1126
+ Appsignal.report_error(error)
1127
+
1128
+ expect(last_transaction).to be_completed
1129
+ end
1130
+
1131
+ context "when given a block" do
1132
+ it "yields the transaction and allows additional metadata to be set" do
1133
+ Appsignal.report_error(error) do |t|
1134
+ t.set_action("my_action")
1135
+ t.set_namespace("my_namespace")
1136
+ t.set_tags(:tag1 => "value1")
1137
+ end
1138
+
1139
+ transaction = last_transaction
1140
+ expect(transaction).to have_namespace("my_namespace")
1141
+ expect(transaction).to have_action("my_action")
1142
+ expect(transaction).to have_error("ExampleException", "error message")
1143
+ expect(transaction).to include_tags("tag1" => "value1")
1144
+ expect(transaction).to be_completed
1145
+ end
1146
+ end
1147
+ end
1148
+
1149
+ context "when there is an active transaction" do
1150
+ let(:transaction) { http_request_transaction }
1151
+ before { set_current_transaction(transaction) }
1152
+
1153
+ it "adds the error to the active transaction" do
1154
+ Appsignal.report_error(error)
1155
+
1156
+ expect(last_transaction).to eq(transaction)
1157
+ transaction._sample
1158
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
1159
+ expect(transaction).to have_error("ExampleException", "error message")
1160
+ end
1161
+
1162
+ it "does not complete the transaction" do
1163
+ Appsignal.report_error(error)
1164
+
1165
+ expect(last_transaction).to_not be_completed
1166
+ end
1167
+
1168
+ context "when given a block" do
1169
+ it "yields the transaction and allows additional metadata to be set" do
1170
+ Appsignal.report_error(error) do |t|
1171
+ t.set_action("my_action")
1172
+ t.set_namespace("my_namespace")
1173
+ t.set_tags(:tag1 => "value1")
1174
+ end
1175
+
1176
+ transaction._sample
1177
+ expect(transaction).to have_namespace("my_namespace")
1178
+ expect(transaction).to have_action("my_action")
1179
+ expect(transaction).to have_error("ExampleException", "error message")
1180
+ expect(transaction).to include_tags("tag1" => "value1")
1181
+ expect(transaction).to_not be_completed
1182
+ end
1183
+ end
1184
+ end
1185
+ end
1186
+
996
1187
  describe ".set_action" do
997
1188
  around { |example| keep_transactions { example.run } }
998
1189
 
@@ -8,7 +8,7 @@ class DummyApp
8
8
  if @app
9
9
  @app&.call(env)
10
10
  else
11
- [200, {}, "body"]
11
+ [200, {}, ["body"]]
12
12
  end
13
13
  ensure
14
14
  @called = true