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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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