appsignal 3.0.15-java → 3.0.16-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +1 -1
- data/CHANGELOG.md +35 -0
- data/build_matrix.yml +1 -1
- data/ext/agent.yml +25 -25
- data/ext/appsignal_extension.c +201 -0
- data/lib/appsignal/cli/diagnose.rb +16 -5
- data/lib/appsignal/config.rb +62 -56
- data/lib/appsignal/extension/jruby.rb +147 -0
- data/lib/appsignal/extension.rb +5 -0
- data/lib/appsignal/span.rb +92 -0
- data/lib/appsignal/transaction.rb +12 -1
- data/lib/appsignal/version.rb +1 -1
- data/script/lint_git +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +14 -9
- data/spec/lib/appsignal/config_spec.rb +26 -20
- data/spec/lib/appsignal/span_spec.rb +141 -0
- data/spec/lib/appsignal/transaction_spec.rb +25 -0
- metadata +6 -3
@@ -131,6 +131,65 @@ module Appsignal
|
|
131
131
|
[:pointer],
|
132
132
|
:appsignal_string
|
133
133
|
|
134
|
+
# Span methods
|
135
|
+
attach_function :appsignal_create_root_span,
|
136
|
+
[:appsignal_string],
|
137
|
+
:pointer
|
138
|
+
attach_function :appsignal_create_root_span_with_timestamp,
|
139
|
+
[:appsignal_string, :int64, :int64],
|
140
|
+
:pointer
|
141
|
+
attach_function :appsignal_create_child_span,
|
142
|
+
[:pointer],
|
143
|
+
:pointer
|
144
|
+
attach_function :appsignal_create_child_span_with_timestamp,
|
145
|
+
[:pointer, :int64, :int64],
|
146
|
+
:pointer
|
147
|
+
attach_function :appsignal_create_span_from_traceparent,
|
148
|
+
[:appsignal_string],
|
149
|
+
:pointer
|
150
|
+
attach_function :appsignal_span_id,
|
151
|
+
[:pointer],
|
152
|
+
:appsignal_string
|
153
|
+
attach_function :appsignal_span_to_json,
|
154
|
+
[:pointer],
|
155
|
+
:appsignal_string
|
156
|
+
attach_function :appsignal_set_span_name,
|
157
|
+
[:pointer, :appsignal_string],
|
158
|
+
:void
|
159
|
+
attach_function :appsignal_set_span_namespace,
|
160
|
+
[:pointer, :appsignal_string],
|
161
|
+
:void
|
162
|
+
attach_function :appsignal_add_span_error,
|
163
|
+
[:pointer, :appsignal_string, :appsignal_string, :pointer],
|
164
|
+
:void
|
165
|
+
attach_function :appsignal_set_span_sample_data,
|
166
|
+
[:pointer, :appsignal_string, :pointer],
|
167
|
+
:void
|
168
|
+
attach_function :appsignal_set_span_attribute_string,
|
169
|
+
[:pointer, :appsignal_string, :appsignal_string],
|
170
|
+
:void
|
171
|
+
attach_function :appsignal_set_span_attribute_sql_string,
|
172
|
+
[:pointer, :appsignal_string, :appsignal_string],
|
173
|
+
:void
|
174
|
+
attach_function :appsignal_set_span_attribute_int,
|
175
|
+
[:pointer, :appsignal_string, :int64],
|
176
|
+
:void
|
177
|
+
attach_function :appsignal_set_span_attribute_bool,
|
178
|
+
[:pointer, :appsignal_string, :bool],
|
179
|
+
:void
|
180
|
+
attach_function :appsignal_set_span_attribute_double,
|
181
|
+
[:pointer, :appsignal_string, :double],
|
182
|
+
:void
|
183
|
+
attach_function :appsignal_close_span,
|
184
|
+
[:pointer],
|
185
|
+
:void
|
186
|
+
attach_function :appsignal_close_span_with_timestamp,
|
187
|
+
[:pointer, :int64, :int64],
|
188
|
+
:void
|
189
|
+
attach_function :appsignal_free_span,
|
190
|
+
[:pointer],
|
191
|
+
:void
|
192
|
+
|
134
193
|
# Data struct methods
|
135
194
|
attach_function :appsignal_free_data, [], :void
|
136
195
|
attach_function :appsignal_data_map_new, [], :pointer
|
@@ -375,6 +434,94 @@ module Appsignal
|
|
375
434
|
end
|
376
435
|
end
|
377
436
|
|
437
|
+
class Span
|
438
|
+
include StringHelpers
|
439
|
+
extend StringHelpers
|
440
|
+
|
441
|
+
attr_reader :pointer
|
442
|
+
|
443
|
+
def initialize(pointer)
|
444
|
+
@pointer = FFI::AutoPointer.new(
|
445
|
+
pointer,
|
446
|
+
Extension.method(:appsignal_free_span)
|
447
|
+
)
|
448
|
+
end
|
449
|
+
|
450
|
+
def self.root(namespace)
|
451
|
+
namespace = make_appsignal_string(namespace)
|
452
|
+
Span.new(Extension.appsignal_create_root_span(namespace))
|
453
|
+
end
|
454
|
+
|
455
|
+
def child
|
456
|
+
Span.new(Extension.appsignal_create_child_span(pointer))
|
457
|
+
end
|
458
|
+
|
459
|
+
def add_error(name, message, backtrace)
|
460
|
+
Extension.appsignal_add_span_error(
|
461
|
+
pointer,
|
462
|
+
make_appsignal_string(name),
|
463
|
+
make_appsignal_string(message),
|
464
|
+
backtrace.pointer
|
465
|
+
)
|
466
|
+
end
|
467
|
+
|
468
|
+
def set_sample_data(key, payload)
|
469
|
+
Extension.appsignal_set_span_sample_data(
|
470
|
+
pointer,
|
471
|
+
make_appsignal_string(key),
|
472
|
+
payload.pointer
|
473
|
+
)
|
474
|
+
end
|
475
|
+
|
476
|
+
def set_name(name) # rubocop:disable Naming/AccessorMethodName
|
477
|
+
Extension.appsignal_set_span_name(
|
478
|
+
pointer,
|
479
|
+
make_appsignal_string(name)
|
480
|
+
)
|
481
|
+
end
|
482
|
+
|
483
|
+
def set_attribute_string(key, value)
|
484
|
+
Extension.appsignal_set_span_attribute_string(
|
485
|
+
pointer,
|
486
|
+
make_appsignal_string(key),
|
487
|
+
make_appsignal_string(value)
|
488
|
+
)
|
489
|
+
end
|
490
|
+
|
491
|
+
def set_attribute_int(key, value)
|
492
|
+
Extension.appsignal_set_span_attribute_int(
|
493
|
+
pointer,
|
494
|
+
make_appsignal_string(key),
|
495
|
+
value
|
496
|
+
)
|
497
|
+
end
|
498
|
+
|
499
|
+
def set_attribute_bool(key, value)
|
500
|
+
Extension.appsignal_set_span_attribute_bool(
|
501
|
+
pointer,
|
502
|
+
make_appsignal_string(key),
|
503
|
+
value
|
504
|
+
)
|
505
|
+
end
|
506
|
+
|
507
|
+
def set_attribute_double(key, value)
|
508
|
+
Extension.appsignal_set_span_attribute_double(
|
509
|
+
pointer,
|
510
|
+
make_appsignal_string(key),
|
511
|
+
value
|
512
|
+
)
|
513
|
+
end
|
514
|
+
|
515
|
+
def to_json
|
516
|
+
json = Extension.appsignal_span_to_json(pointer)
|
517
|
+
make_ruby_string(json) if json[:len] > 0
|
518
|
+
end
|
519
|
+
|
520
|
+
def close
|
521
|
+
Extension.appsignal_close_span(pointer)
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
378
525
|
class Data
|
379
526
|
include StringHelpers
|
380
527
|
attr_reader :pointer
|
data/lib/appsignal/extension.rb
CHANGED
@@ -60,6 +60,11 @@ module Appsignal
|
|
60
60
|
# Makes sure the generated docs aren't always overwritten with the JRuby
|
61
61
|
# version.
|
62
62
|
Transaction = Jruby::Transaction
|
63
|
+
# Reassign Span class for JRuby extension usage.
|
64
|
+
#
|
65
|
+
# Makes sure the generated docs aren't always overwritten with the JRuby
|
66
|
+
# version.
|
67
|
+
Span = Jruby::Span
|
63
68
|
# Reassign Data class for JRuby extension usage.
|
64
69
|
#
|
65
70
|
# Makes sure the generated docs aren't always overwritten with the JRuby
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class Span
|
3
|
+
def initialize(namespace = nil, ext = nil)
|
4
|
+
@ext = if ext
|
5
|
+
ext
|
6
|
+
else
|
7
|
+
Appsignal::Extension::Span.root(namespace || "")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def child
|
12
|
+
Span.new(nil, @ext.child)
|
13
|
+
end
|
14
|
+
|
15
|
+
def name=(value)
|
16
|
+
@ext.set_name(value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_error(error)
|
20
|
+
unless error.is_a?(Exception)
|
21
|
+
Appsignal.logger.error "Appsignal::Span#add_error: Cannot add error. " \
|
22
|
+
"The given value is not an exception: #{error.inspect}"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
return unless error
|
26
|
+
|
27
|
+
backtrace = cleaned_backtrace(error.backtrace)
|
28
|
+
@ext.add_error(
|
29
|
+
error.class.name,
|
30
|
+
error.message.to_s,
|
31
|
+
backtrace ? Appsignal::Utils::Data.generate(backtrace) : Appsignal::Extension.data_array_new
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_sample_data(key, data)
|
36
|
+
return unless key && data && (data.is_a?(Array) || data.is_a?(Hash))
|
37
|
+
@ext.set_sample_data(
|
38
|
+
key.to_s,
|
39
|
+
Appsignal::Utils::Data.generate(data)
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def []=(key, value)
|
44
|
+
case value
|
45
|
+
when String
|
46
|
+
@ext.set_attribute_string(key.to_s, value)
|
47
|
+
when Integer
|
48
|
+
begin
|
49
|
+
@ext.set_attribute_int(key.to_s, value)
|
50
|
+
rescue RangeError
|
51
|
+
@ext.set_attribute_string(key.to_s, "bigint:#{value}")
|
52
|
+
end
|
53
|
+
when TrueClass, FalseClass
|
54
|
+
@ext.set_attribute_bool(key.to_s, value)
|
55
|
+
when Float
|
56
|
+
@ext.set_attribute_double(key.to_s, value)
|
57
|
+
else
|
58
|
+
raise TypeError, "value needs to be a string, int, bool or float"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_h
|
63
|
+
json = @ext.to_json
|
64
|
+
return unless json
|
65
|
+
JSON.parse(json)
|
66
|
+
end
|
67
|
+
|
68
|
+
def instrument
|
69
|
+
yield self
|
70
|
+
ensure
|
71
|
+
close
|
72
|
+
end
|
73
|
+
|
74
|
+
def close
|
75
|
+
@ext.close
|
76
|
+
end
|
77
|
+
|
78
|
+
def closed?
|
79
|
+
to_h.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def cleaned_backtrace(backtrace)
|
85
|
+
if defined?(::Rails) && backtrace
|
86
|
+
::Rails.backtrace_cleaner.clean(backtrace, nil)
|
87
|
+
else
|
88
|
+
backtrace
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -333,7 +333,7 @@ module Appsignal
|
|
333
333
|
backtrace = cleaned_backtrace(error.backtrace)
|
334
334
|
@ext.set_error(
|
335
335
|
error.class.name,
|
336
|
-
error
|
336
|
+
cleaned_error_message(error),
|
337
337
|
backtrace ? Appsignal::Utils::Data.generate(backtrace) : Appsignal::Extension.data_array_new
|
338
338
|
)
|
339
339
|
end
|
@@ -533,6 +533,17 @@ module Appsignal
|
|
533
533
|
end
|
534
534
|
end
|
535
535
|
|
536
|
+
# Clean error messages that are known to potentially contain user data.
|
537
|
+
# Returns an unchanged message otherwise.
|
538
|
+
def cleaned_error_message(error)
|
539
|
+
case error.class.to_s
|
540
|
+
when "PG::UniqueViolation"
|
541
|
+
error.message.to_s.gsub(/\)=\(.*\)/, ")=(?)")
|
542
|
+
else
|
543
|
+
error.message.to_s
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
536
547
|
# Stub that is returned by {Transaction.current} if there is no current
|
537
548
|
# transaction, so that it's still safe to call methods on it if there is no
|
538
549
|
# current transaction.
|
data/lib/appsignal/version.rb
CHANGED
data/script/lint_git
CHANGED
@@ -750,13 +750,13 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
750
750
|
end
|
751
751
|
|
752
752
|
it "outputs a warning that no config is loaded" do
|
753
|
-
expect(output).to include "
|
753
|
+
expect(output).to include "environment: \"\"\n#{warning_message}"
|
754
754
|
expect(output).to_not have_color_markers
|
755
755
|
end
|
756
756
|
|
757
757
|
context "with color", :color => true do
|
758
758
|
it "outputs a warning that no config is loaded in color" do
|
759
|
-
expect(output).to include "
|
759
|
+
expect(output).to include "environment: \"\"\n"
|
760
760
|
expect(output).to have_colorized_text :red, warning_message
|
761
761
|
end
|
762
762
|
end
|
@@ -785,7 +785,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
785
785
|
describe "environment" do
|
786
786
|
it "outputs environment" do
|
787
787
|
run
|
788
|
-
expect(output).to include(%(
|
788
|
+
expect(output).to include(%(environment: "production"))
|
789
789
|
end
|
790
790
|
|
791
791
|
context "when the source is a single source" do
|
@@ -793,7 +793,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
793
793
|
|
794
794
|
it "outputs the label source after the value" do
|
795
795
|
expect(output).to include(
|
796
|
-
%(
|
796
|
+
%(environment: "#{Appsignal.config.env}" (Loaded from: initial)\n)
|
797
797
|
)
|
798
798
|
end
|
799
799
|
end
|
@@ -810,7 +810,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
810
810
|
|
811
811
|
it "outputs a list of sources with their values" do
|
812
812
|
expect(output).to include(
|
813
|
-
%(
|
813
|
+
%( environment: "production"\n) +
|
814
814
|
%( Sources:\n) +
|
815
815
|
%( initial: "development"\n) +
|
816
816
|
%( env: "production"\n)
|
@@ -904,7 +904,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
904
904
|
before { run_within_dir tmp_dir }
|
905
905
|
|
906
906
|
it "outputs environment" do
|
907
|
-
expect(output).to include(%(
|
907
|
+
expect(output).to include(%(environment: "foobar"))
|
908
908
|
end
|
909
909
|
|
910
910
|
it "outputs config defaults" do
|
@@ -1007,7 +1007,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
1007
1007
|
|
1008
1008
|
it "outputs failure with status code" do
|
1009
1009
|
expect(output).to include "Validation",
|
1010
|
-
"Validating Push API key: Failed
|
1010
|
+
"Validating Push API key: Failed to validate: status 500\n" +
|
1011
1011
|
%("Could not confirm authorization: 500")
|
1012
1012
|
end
|
1013
1013
|
|
@@ -1015,14 +1015,19 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
1015
1015
|
it "outputs error in color" do
|
1016
1016
|
expect(output).to include "Validation",
|
1017
1017
|
"Validating Push API key: " +
|
1018
|
-
colorize(
|
1018
|
+
colorize(
|
1019
|
+
"Failed to validate: status 500\n" +
|
1020
|
+
%("Could not confirm authorization: 500"),
|
1021
|
+
:red
|
1022
|
+
)
|
1019
1023
|
end
|
1020
1024
|
end
|
1021
1025
|
|
1022
1026
|
it "transmits validation in report" do
|
1023
1027
|
expect(received_report).to include(
|
1024
1028
|
"validation" => {
|
1025
|
-
"push_api_key" =>
|
1029
|
+
"push_api_key" => "Failed to validate: status 500\n" +
|
1030
|
+
%("Could not confirm authorization: 500")
|
1026
1031
|
}
|
1027
1032
|
)
|
1028
1033
|
end
|
@@ -151,34 +151,35 @@ describe Appsignal::Config do
|
|
151
151
|
|
152
152
|
it "merges with the default config" do
|
153
153
|
expect(config.config_hash).to eq(
|
154
|
+
:active => true,
|
155
|
+
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
154
156
|
:debug => false,
|
155
|
-
:
|
157
|
+
:dns_servers => [],
|
158
|
+
:enable_allocation_tracking => true,
|
159
|
+
:enable_gc_instrumentation => false,
|
160
|
+
:enable_host_metrics => true,
|
161
|
+
:enable_minutely_probes => true,
|
162
|
+
:enable_statsd => true,
|
163
|
+
:endpoint => "https://push.appsignal.com",
|
164
|
+
:files_world_accessible => true,
|
165
|
+
:filter_parameters => [],
|
166
|
+
:filter_session_data => [],
|
156
167
|
:ignore_actions => [],
|
157
168
|
:ignore_errors => [],
|
158
169
|
:ignore_namespaces => [],
|
159
|
-
:filter_parameters => [],
|
160
|
-
:filter_session_data => [],
|
161
170
|
:instrument_net_http => true,
|
162
171
|
:instrument_redis => true,
|
163
172
|
:instrument_sequel => true,
|
164
|
-
:
|
165
|
-
:
|
166
|
-
:send_params => true,
|
167
|
-
:endpoint => "https://push.appsignal.com",
|
168
|
-
:push_api_key => "abc",
|
173
|
+
:log => "file",
|
174
|
+
:log_level => "info",
|
169
175
|
:name => "TestApp",
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:enable_gc_instrumentation => false,
|
173
|
-
:enable_host_metrics => true,
|
174
|
-
:enable_minutely_probes => true,
|
175
|
-
:enable_statsd => true,
|
176
|
-
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
177
|
-
:dns_servers => [],
|
178
|
-
:files_world_accessible => true,
|
179
|
-
:transaction_debug_mode => false,
|
176
|
+
:push_api_key => "abc",
|
177
|
+
:request_headers => [],
|
180
178
|
:revision => "v2.5.1",
|
181
|
-
:
|
179
|
+
:send_environment_metadata => true,
|
180
|
+
:send_params => true,
|
181
|
+
:skip_session_data => false,
|
182
|
+
:transaction_debug_mode => false
|
182
183
|
)
|
183
184
|
end
|
184
185
|
|
@@ -319,13 +320,15 @@ describe Appsignal::Config do
|
|
319
320
|
"non-existing-path",
|
320
321
|
"production",
|
321
322
|
:running_in_container => true,
|
322
|
-
:debug => true
|
323
|
+
:debug => true,
|
324
|
+
:log_level => "debug"
|
323
325
|
)
|
324
326
|
end
|
325
327
|
|
326
328
|
it "overrides system detected and defaults config" do
|
327
329
|
expect(config[:running_in_container]).to be_truthy
|
328
330
|
expect(config[:debug]).to be_truthy
|
331
|
+
expect(config[:log_level]).to eq("debug")
|
329
332
|
end
|
330
333
|
end
|
331
334
|
|
@@ -502,6 +505,7 @@ describe Appsignal::Config do
|
|
502
505
|
config[:log] = "stdout"
|
503
506
|
config[:log_path] = "/tmp"
|
504
507
|
config[:filter_parameters] = %w[password confirm_password]
|
508
|
+
config[:filter_session_data] = %w[key1 key2]
|
505
509
|
config[:running_in_container] = false
|
506
510
|
config[:dns_servers] = ["8.8.8.8", "8.8.4.4"]
|
507
511
|
config[:transaction_debug_mode] = true
|
@@ -535,6 +539,8 @@ describe Appsignal::Config do
|
|
535
539
|
expect(ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"]).to eq "true"
|
536
540
|
expect(ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"]).to eq "true"
|
537
541
|
expect(ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"]).to eq "false"
|
542
|
+
expect(ENV["_APPSIGNAL_FILTER_PARAMETERS"]).to eq "password,confirm_password"
|
543
|
+
expect(ENV["_APPSIGNAL_FILTER_SESSION_DATA"]).to eq "key1,key2"
|
538
544
|
expect(ENV["_APP_REVISION"]).to eq "v2.5.1"
|
539
545
|
expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIR_PATH")
|
540
546
|
expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIRECTORY_PATH")
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require "appsignal/span"
|
2
|
+
|
3
|
+
describe Appsignal::Span do
|
4
|
+
before :context do
|
5
|
+
start_agent
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:namespace) { "web" }
|
9
|
+
let(:root) { Appsignal::Span.new(namespace) }
|
10
|
+
|
11
|
+
describe "creating a span" do
|
12
|
+
it "creates an empty span" do
|
13
|
+
expect(root.to_h["namespace"]).to eq "web"
|
14
|
+
expect(root.to_h["trace_id"].length).to eq 16
|
15
|
+
expect(root.to_h["span_id"].length).to eq 8
|
16
|
+
expect(root.to_h["parent_span_id"]).to be_empty
|
17
|
+
expect(root.to_h["name"]).to be_empty
|
18
|
+
expect(root.to_h["start_time"]).to be > 1_600_000_000
|
19
|
+
expect(root.to_h["closed"]).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#child" do
|
24
|
+
let(:child) { root.child }
|
25
|
+
|
26
|
+
it "creates a child span" do
|
27
|
+
expect(child.to_h["namespace"]).to be_empty
|
28
|
+
expect(child.to_h["trace_id"].length).to eq 16
|
29
|
+
expect(child.to_h["span_id"].length).to eq 8
|
30
|
+
expect(child.to_h["parent_span_id"]).to eq root.to_h["span_id"]
|
31
|
+
expect(child.to_h["name"]).to be_empty
|
32
|
+
expect(child.to_h["start_time"]).to be > 1_600_000_000
|
33
|
+
expect(child.to_h["closed"]).to be false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#add_error" do
|
38
|
+
it "adds an error" do
|
39
|
+
begin
|
40
|
+
raise "Error"
|
41
|
+
rescue => error
|
42
|
+
root.add_error(error)
|
43
|
+
end
|
44
|
+
|
45
|
+
error = root.to_h["error"]
|
46
|
+
expect(error["name"]).to eq "RuntimeError"
|
47
|
+
expect(error["message"]).to eq "Error"
|
48
|
+
expect(error["backtrace"]).not_to be_empty
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "set_sample_data" do
|
53
|
+
it "sets sample data" do
|
54
|
+
root.set_sample_data(:params, "key" => "value")
|
55
|
+
|
56
|
+
sample_data = root.to_h["sample_data"]
|
57
|
+
expect(sample_data["params"]).to eq "{\"key\":\"value\"}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#name=" do
|
62
|
+
it "sets the name" do
|
63
|
+
root.name = "Span name"
|
64
|
+
|
65
|
+
expect(root.to_h["name"]).to eq "Span name"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#[]=" do
|
70
|
+
let(:attributes) { root.to_h["attributes"] }
|
71
|
+
|
72
|
+
it "sets a string attribute" do
|
73
|
+
root["string"] = "attribute"
|
74
|
+
|
75
|
+
expect(attributes["string"]).to eq "attribute"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sets an integer attribute" do
|
79
|
+
root["integer"] = 1001
|
80
|
+
|
81
|
+
expect(attributes["integer"]).to eq 1001
|
82
|
+
end
|
83
|
+
|
84
|
+
it "sets a bigint attribute" do
|
85
|
+
root["bigint"] = 1 << 64
|
86
|
+
|
87
|
+
expect(attributes["bigint"]).to eq "bigint:#{1 << 64}"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets a boolean attribute" do
|
91
|
+
root["true"] = true
|
92
|
+
root["false"] = false
|
93
|
+
|
94
|
+
expect(attributes["true"]).to eq true
|
95
|
+
expect(attributes["false"]).to eq false
|
96
|
+
end
|
97
|
+
|
98
|
+
it "sets a float attribute" do
|
99
|
+
root["float"] = 10.01
|
100
|
+
|
101
|
+
expect(attributes["float"]).to eq 10.01
|
102
|
+
end
|
103
|
+
|
104
|
+
it "raises an error for other types" do
|
105
|
+
expect do
|
106
|
+
root["something"] = Object.new
|
107
|
+
end.to raise_error TypeError
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#instrument" do
|
112
|
+
it "closes the span after yielding" do
|
113
|
+
root.instrument do
|
114
|
+
# Nothing happening
|
115
|
+
end
|
116
|
+
expect(root.closed?).to eq true
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with an error raised in the passed block" do
|
120
|
+
it "closes the span after yielding" do
|
121
|
+
expect do
|
122
|
+
root.instrument do
|
123
|
+
raise ExampleException, "foo"
|
124
|
+
end
|
125
|
+
end.to raise_error(ExampleException, "foo")
|
126
|
+
expect(root.closed?).to eq true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#close" do
|
132
|
+
it "closes a span" do
|
133
|
+
expect(root.closed?).to eq false
|
134
|
+
|
135
|
+
root.close
|
136
|
+
|
137
|
+
expect(root.to_h).to be_nil
|
138
|
+
expect(root.closed?).to eq true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -1341,6 +1341,31 @@ describe Appsignal::Transaction do
|
|
1341
1341
|
end
|
1342
1342
|
end
|
1343
1343
|
|
1344
|
+
describe "#cleaned_error_message" do
|
1345
|
+
let(:error) { StandardError.new("Error message") }
|
1346
|
+
subject { transaction.send(:cleaned_error_message, error) }
|
1347
|
+
|
1348
|
+
it "returns the error message" do
|
1349
|
+
expect(subject).to eq "Error message"
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
context "with a PG::UniqueViolation" do
|
1353
|
+
module PG
|
1354
|
+
class UniqueViolation < StandardError; end
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
let(:error) do
|
1358
|
+
PG::UniqueViolation.new(
|
1359
|
+
"ERROR: duplicate key value violates unique constraint \"index_users_on_email\" DETAIL: Key (email)=(test@test.com) already exists."
|
1360
|
+
)
|
1361
|
+
end
|
1362
|
+
|
1363
|
+
it "returns a sanizited error message" do
|
1364
|
+
expect(subject).to eq "ERROR: duplicate key value violates unique constraint \"index_users_on_email\" DETAIL: Key (email)=(?) already exists."
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
end
|
1368
|
+
|
1344
1369
|
describe ".to_hash / .to_h" do
|
1345
1370
|
subject { transaction.to_hash }
|
1346
1371
|
|