appsignal 3.0.0.beta.1 → 3.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -686,6 +686,9 @@ describe Appsignal do
686
686
  )
687
687
  end
688
688
  let(:error) { ExampleException.new }
689
+ let(:err_stream) { std_stream }
690
+ let(:stderr) { err_stream.read }
691
+ around { |example| keep_transactions { example.run } }
689
692
 
690
693
  it "sends the error to AppSignal" do
691
694
  expect(Appsignal::Transaction).to receive(:new).with(
@@ -719,30 +722,60 @@ describe Appsignal do
719
722
 
720
723
  context "with tags" do
721
724
  let(:tags) { { :a => "a", :b => "b" } }
722
- before do
723
- allow(Appsignal::Transaction).to receive(:new).and_return(transaction)
724
- end
725
725
 
726
- it "tags the request before sending it" do
727
- expect(transaction).to receive(:set_tags).with(tags).and_call_original
728
- expect(transaction).to receive(:complete)
726
+ it "prints a deprecation warning and tags the transaction" do
727
+ logs = capture_logs do
728
+ expect do
729
+ capture_std_streams(std_stream, err_stream) do
730
+ Appsignal.send_error(error, tags)
731
+ end
732
+ end.to change { created_transactions.count }.by(1)
733
+ end
734
+
735
+ transaction = last_transaction
736
+ transaction_hash = transaction.to_h
737
+ expect(transaction_hash).to include(
738
+ "sample_data" => hash_including(
739
+ "tags" => { "a" => "a", "b" => "b" }
740
+ )
741
+ )
729
742
 
730
- Appsignal.send_error(error, tags)
743
+ message = "The tags argument for `Appsignal.send_error` is deprecated. " \
744
+ "Please use the block method to set tags instead.\n\n" \
745
+ " Appsignal.send_error(error) do |transaction|\n" \
746
+ " transaction.set_tags(#{tags.inspect})\n" \
747
+ " end\n\n" \
748
+ "Appsignal.send_error called on location: #{__FILE__}:"
749
+ expect(stderr).to include("appsignal WARNING: #{message}")
750
+ expect(logs).to include(message)
731
751
  end
732
752
  end
733
753
 
734
754
  context "with namespace" do
735
755
  let(:namespace) { "admin" }
736
756
 
737
- it "sets the namespace on the transaction" do
738
- expect(Appsignal::Transaction).to receive(:new).with(
739
- kind_of(String),
740
- "admin",
741
- kind_of(Appsignal::Transaction::GenericRequest)
742
- ).and_call_original
743
- end
757
+ it "prints a deprecation warning and sets the namespace on the transaction" do
758
+ logs = capture_logs do
759
+ expect do
760
+ capture_std_streams(std_stream, err_stream) do
761
+ Appsignal.send_error(error, nil, namespace)
762
+ end
763
+ end.to change { created_transactions.count }.by(1)
764
+ end
765
+
766
+ transaction = last_transaction
767
+ transaction_hash = transaction.to_h
768
+ expect(transaction_hash).to include("namespace" => namespace)
744
769
 
745
- after { Appsignal.send_error(error, nil, namespace) }
770
+ message = "The namespace argument for `Appsignal.send_error` is deprecated. " \
771
+ "Please use the block method to set the namespace instead.\n\n" \
772
+ " Appsignal.send_error(error) do |transaction|\n" \
773
+ " transaction.namespace(#{namespace.inspect})\n" \
774
+ " end\n\n" \
775
+ "Appsignal.send_error called on location: #{__FILE__}:"
776
+ expect(stderr).to include("appsignal WARNING: #{message}")
777
+ expect(logs).to include(message)
778
+ end
746
779
  end
747
780
 
748
781
  context "when given a block" do
@@ -769,53 +802,85 @@ describe Appsignal do
769
802
  end
770
803
 
771
804
  describe ".listen_for_error" do
805
+ around { |example| keep_transactions { example.run } }
806
+
772
807
  it "records the error and re-raise it" do
773
- expect(Appsignal).to receive(:send_error).with(
774
- kind_of(ExampleException),
775
- nil,
776
- Appsignal::Transaction::HTTP_REQUEST
777
- )
778
808
  expect do
779
- Appsignal.listen_for_error do
780
- raise ExampleException, "I am an exception"
781
- end
782
- end.to raise_error(ExampleException, "I am an exception")
809
+ expect do
810
+ Appsignal.listen_for_error do
811
+ raise ExampleException, "I am an exception"
812
+ end
813
+ end.to raise_error(ExampleException, "I am an exception")
814
+ end.to change { created_transactions.count }.by(1)
815
+
816
+ expect(last_transaction.to_h).to include(
817
+ "error" => {
818
+ "name" => "ExampleException",
819
+ "message" => "I am an exception",
820
+ "backtrace" => kind_of(String)
821
+ },
822
+ "namespace" => Appsignal::Transaction::HTTP_REQUEST, # Default namespace
823
+ "sample_data" => hash_including(
824
+ "tags" => {}
825
+ )
826
+ )
783
827
  end
784
828
 
785
829
  context "with tags" do
786
830
  it "adds tags to the transaction" do
787
- expect(Appsignal).to receive(:send_error).with(
788
- kind_of(ExampleException),
789
- { "foo" => "bar" },
790
- Appsignal::Transaction::HTTP_REQUEST
791
- )
792
831
  expect do
793
- Appsignal.listen_for_error("foo" => "bar") do
794
- raise ExampleException, "I am an exception"
795
- end
796
- end.to raise_error(ExampleException, "I am an exception")
832
+ expect do
833
+ Appsignal.listen_for_error("foo" => "bar") do
834
+ raise ExampleException, "I am an exception"
835
+ end
836
+ end.to raise_error(ExampleException, "I am an exception")
837
+ end.to change { created_transactions.count }.by(1)
838
+
839
+ expect(last_transaction.to_h).to include(
840
+ "error" => {
841
+ "name" => "ExampleException",
842
+ "message" => "I am an exception",
843
+ "backtrace" => kind_of(String)
844
+ },
845
+ "namespace" => Appsignal::Transaction::HTTP_REQUEST, # Default namespace
846
+ "sample_data" => hash_including(
847
+ "tags" => { "foo" => "bar" }
848
+ )
849
+ )
797
850
  end
798
851
  end
799
852
 
800
853
  context "with a custom namespace" do
801
854
  it "adds the namespace to the transaction" do
802
- expect(Appsignal).to receive(:send_error).with(
803
- kind_of(ExampleException),
804
- nil,
805
- "custom_namespace"
806
- )
807
855
  expect do
808
- Appsignal.listen_for_error(nil, "custom_namespace") do
809
- raise ExampleException, "I am an exception"
810
- end
811
- end.to raise_error(ExampleException, "I am an exception")
856
+ expect do
857
+ Appsignal.listen_for_error(nil, "custom_namespace") do
858
+ raise ExampleException, "I am an exception"
859
+ end
860
+ end.to raise_error(ExampleException, "I am an exception")
861
+ end.to change { created_transactions.count }.by(1)
862
+
863
+ expect(last_transaction.to_h).to include(
864
+ "error" => {
865
+ "name" => "ExampleException",
866
+ "message" => "I am an exception",
867
+ "backtrace" => kind_of(String)
868
+ },
869
+ "namespace" => "custom_namespace",
870
+ "sample_data" => hash_including(
871
+ "tags" => {}
872
+ )
873
+ )
812
874
  end
813
875
  end
814
876
  end
815
877
 
816
878
  describe ".set_error" do
879
+ let(:err_stream) { std_stream }
880
+ let(:stderr) { err_stream.read }
881
+ let(:error) { ExampleException.new("I am an exception") }
817
882
  before { allow(Appsignal::Transaction).to receive(:current).and_return(transaction) }
818
- let(:error) { RuntimeError.new("I am an exception") }
883
+ around { |example| keep_transactions { example.run } }
819
884
 
820
885
  context "when there is an active transaction" do
821
886
  it "adds the error to the active transaction" do
@@ -845,24 +910,74 @@ describe Appsignal do
845
910
  context "with tags" do
846
911
  let(:tags) { { "foo" => "bar" } }
847
912
 
848
- it "sets the tags on the transaction" do
913
+ it "prints a deprecation warning and tags the transaction" do
849
914
  expect(transaction).to receive(:set_error).with(error)
850
915
  expect(transaction).to receive(:set_tags).with(tags)
851
916
  expect(transaction).to_not receive(:set_namespace)
852
917
 
853
- Appsignal.set_error(error, tags)
918
+ logs = capture_logs do
919
+ capture_std_streams(std_stream, err_stream) do
920
+ Appsignal.set_error(error, tags)
921
+ end
922
+ end
923
+
924
+ message = "The tags argument for `Appsignal.set_error` is deprecated. " \
925
+ "Please use the block method to set tags instead.\n\n" \
926
+ " Appsignal.set_error(error) do |transaction|\n" \
927
+ " transaction.set_tags(#{tags.inspect})\n" \
928
+ " end\n\n" \
929
+ "Appsignal.set_error called on location: #{__FILE__}:"
930
+ expect(stderr).to include("appsignal WARNING: #{message}")
931
+ expect(logs).to include(message)
854
932
  end
855
933
  end
856
934
 
857
935
  context "with namespace" do
858
936
  let(:namespace) { "admin" }
859
937
 
860
- it "sets the namespace on the transaction" do
938
+ it "prints a deprecation warning andsets the namespace on the transaction" do
861
939
  expect(transaction).to receive(:set_error).with(error)
862
940
  expect(transaction).to_not receive(:set_tags)
863
941
  expect(transaction).to receive(:set_namespace).with(namespace)
864
942
 
865
- Appsignal.set_error(error, nil, namespace)
943
+ logs = capture_logs do
944
+ capture_std_streams(std_stream, err_stream) do
945
+ Appsignal.set_error(error, nil, namespace)
946
+ end
947
+ end
948
+
949
+ message = "The namespace argument for `Appsignal.set_error` is deprecated. " \
950
+ "Please use the block method to set the namespace instead.\n\n" \
951
+ " Appsignal.set_error(error) do |transaction|\n" \
952
+ " transaction.namespace(#{namespace.inspect})\n" \
953
+ " end\n\n" \
954
+ "Appsignal.set_error called on location: #{__FILE__}:"
955
+ expect(stderr).to include("appsignal WARNING: #{message}")
956
+ expect(logs).to include(message)
957
+ end
958
+ end
959
+
960
+ context "when given a block" do
961
+ it "yields the transaction and allows additional metadata to be set" do
962
+ captured_transaction = nil
963
+ keep_transactions do
964
+ Appsignal.set_error(StandardError.new("my_error")) do |transaction|
965
+ captured_transaction = transaction
966
+ transaction.set_action("my_action")
967
+ transaction.set_namespace("my_namespace")
968
+ end
969
+ end
970
+
971
+ expect(transaction).to eql(captured_transaction)
972
+ expect(captured_transaction.to_h).to include(
973
+ "namespace" => "my_namespace",
974
+ "action" => "my_action",
975
+ "error" => {
976
+ "name" => "StandardError",
977
+ "message" => "my_error",
978
+ "backtrace" => kind_of(String)
979
+ }
980
+ )
866
981
  end
867
982
  end
868
983
  end
@@ -23,6 +23,27 @@ RSpec.describe "Puma plugin" do
23
23
  def self.stats
24
24
  end
25
25
 
26
+ def self.run
27
+ # Capture threads running before application is preloaded
28
+ before = Thread.list.reject { |t| t.thread_variable_get(:fork_safe) }
29
+
30
+ # An abbreviated version of what happens in Puma::Cluster#run
31
+ launcher = MockPumaLauncher.new
32
+ plugin = Plugin.plugin.new
33
+ plugin.start(launcher)
34
+ launcher.events.on_booted.call
35
+
36
+ # Wait for minutely probe thread to finish starting
37
+ sleep 0.005
38
+
39
+ # Capture any new threads running after application is preloaded.
40
+ # Any threads created during the preloading phase will not be
41
+ # carried over into the forked workers. Puma warns about these
42
+ # but the minutely probe thread should only exist in the main process.
43
+ after = Thread.list.reject { |t| t.thread_variable_get(:fork_safe) }
44
+ $stdout.puts "! WARNING: Detected #{after.size - before.size} Thread(s) started in app boot" if after.size > before.size
45
+ end
46
+
26
47
  class Plugin
27
48
  class << self
28
49
  attr_reader :plugin
@@ -68,6 +89,13 @@ RSpec.describe "Puma plugin" do
68
89
  wait_for("enough probe calls") { probe.calls >= 2 }
69
90
  end
70
91
 
92
+ it "marks the PumaProbe thread as fork-safe", :not_ruby19 do
93
+ out_stream = std_stream
94
+ capture_stdout(out_stream) { Puma.run }
95
+
96
+ expect(out_stream.read).not_to include("WARNING: Detected 1 Thread")
97
+ end
98
+
71
99
  context "without Puma.stats" do
72
100
  before { Puma.singleton_class.send(:remove_method, :stats) }
73
101
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.beta.1
4
+ version: 3.0.0.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Beekman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-01-28 00:00:00.000000000 Z
13
+ date: 2021-02-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -241,6 +241,7 @@ files:
241
241
  - lib/appsignal/integrations/rake.rb
242
242
  - lib/appsignal/integrations/redis.rb
243
243
  - lib/appsignal/integrations/resque.rb
244
+ - lib/appsignal/integrations/sidekiq.rb
244
245
  - lib/appsignal/integrations/sinatra.rb
245
246
  - lib/appsignal/integrations/unicorn.rb
246
247
  - lib/appsignal/integrations/webmachine.rb
@@ -326,6 +327,7 @@ files:
326
327
  - spec/lib/appsignal/integrations/padrino_spec.rb
327
328
  - spec/lib/appsignal/integrations/que_spec.rb
328
329
  - spec/lib/appsignal/integrations/railtie_spec.rb
330
+ - spec/lib/appsignal/integrations/sidekiq_spec.rb
329
331
  - spec/lib/appsignal/integrations/sinatra_spec.rb
330
332
  - spec/lib/appsignal/integrations/webmachine_spec.rb
331
333
  - spec/lib/appsignal/logger_spec.rb
@@ -404,14 +406,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
404
406
  requirements:
405
407
  - - ">="
406
408
  - !ruby/object:Gem::Version
407
- version: '1.9'
409
+ version: '2.0'
408
410
  required_rubygems_version: !ruby/object:Gem::Requirement
409
411
  requirements:
410
412
  - - ">"
411
413
  - !ruby/object:Gem::Version
412
414
  version: 1.3.1
413
415
  requirements: []
414
- rubygems_version: 3.2.6
416
+ rubygems_version: 3.2.8
415
417
  signing_key:
416
418
  specification_version: 4
417
419
  summary: Logs performance and exception data from your app to appsignal.com
@@ -473,6 +475,7 @@ test_files:
473
475
  - spec/lib/appsignal/integrations/padrino_spec.rb
474
476
  - spec/lib/appsignal/integrations/que_spec.rb
475
477
  - spec/lib/appsignal/integrations/railtie_spec.rb
478
+ - spec/lib/appsignal/integrations/sidekiq_spec.rb
476
479
  - spec/lib/appsignal/integrations/sinatra_spec.rb
477
480
  - spec/lib/appsignal/integrations/webmachine_spec.rb
478
481
  - spec/lib/appsignal/logger_spec.rb