appsignal 3.0.15-java → 3.0.19-java

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -3
  3. data/.semaphore/semaphore.yml +513 -104
  4. data/CHANGELOG.md +57 -0
  5. data/appsignal.gemspec +0 -2
  6. data/build_matrix.yml +45 -17
  7. data/ext/agent.yml +25 -25
  8. data/ext/appsignal_extension.c +201 -0
  9. data/ext/base.rb +2 -1
  10. data/gemfiles/rails-6.1.gemfile +7 -0
  11. data/gemfiles/rails-7.0.gemfile +7 -0
  12. data/lib/appsignal/cli/diagnose/utils.rb +0 -14
  13. data/lib/appsignal/cli/diagnose.rb +19 -8
  14. data/lib/appsignal/config.rb +89 -57
  15. data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +24 -0
  16. data/lib/appsignal/extension/jruby.rb +147 -0
  17. data/lib/appsignal/extension.rb +5 -0
  18. data/lib/appsignal/integrations/sidekiq.rb +5 -1
  19. data/lib/appsignal/span.rb +92 -0
  20. data/lib/appsignal/system.rb +0 -4
  21. data/lib/appsignal/transaction.rb +12 -1
  22. data/lib/appsignal/version.rb +1 -1
  23. data/lib/appsignal.rb +4 -10
  24. data/script/lint_git +1 -1
  25. data/spec/lib/appsignal/cli/diagnose_spec.rb +18 -13
  26. data/spec/lib/appsignal/config_spec.rb +104 -20
  27. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +2 -2
  28. data/spec/lib/appsignal/event_formatter/sequel/sql_formatter_spec.rb +30 -0
  29. data/spec/lib/appsignal/event_formatter_spec.rb +2 -2
  30. data/spec/lib/appsignal/hooks/activejob_spec.rb +17 -6
  31. data/spec/lib/appsignal/hooks/sequel_spec.rb +1 -1
  32. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -2
  33. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +23 -5
  34. data/spec/lib/appsignal/span_spec.rb +141 -0
  35. data/spec/lib/appsignal/transaction_spec.rb +25 -0
  36. data/spec/lib/appsignal/utils/data_spec.rb +0 -2
  37. data/spec/lib/appsignal/utils/json_spec.rb +0 -2
  38. data/spec/lib/appsignal_spec.rb +2 -3
  39. data/spec/support/helpers/activejob_helpers.rb +27 -0
  40. data/spec/support/helpers/dependency_helper.rb +13 -1
  41. metadata +13 -3
@@ -11,15 +11,25 @@ module Appsignal
11
11
  include Appsignal::Utils::DeprecationMessage
12
12
 
13
13
  DEFAULT_CONFIG = {
14
+ :ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
14
15
  :debug => false,
15
- :log => "file",
16
+ :dns_servers => [],
17
+ :enable_allocation_tracking => true,
18
+ :enable_gc_instrumentation => false,
19
+ :enable_host_metrics => true,
20
+ :enable_minutely_probes => true,
21
+ :enable_statsd => true,
22
+ :endpoint => "https://push.appsignal.com",
23
+ :files_world_accessible => true,
24
+ :filter_parameters => [],
25
+ :filter_session_data => [],
16
26
  :ignore_actions => [],
17
27
  :ignore_errors => [],
18
28
  :ignore_namespaces => [],
19
- :filter_parameters => [],
20
- :filter_session_data => [],
21
- :send_environment_metadata => true,
22
- :send_params => true,
29
+ :instrument_net_http => true,
30
+ :instrument_redis => true,
31
+ :instrument_sequel => true,
32
+ :log => "file",
23
33
  :request_headers => %w[
24
34
  HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
25
35
  HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_CONNECTION
@@ -27,56 +37,61 @@ module Appsignal
27
37
  REQUEST_METHOD REQUEST_URI SERVER_NAME SERVER_PORT
28
38
  SERVER_PROTOCOL
29
39
  ],
30
- :endpoint => "https://push.appsignal.com",
31
- :instrument_net_http => true,
32
- :instrument_redis => true,
33
- :instrument_sequel => true,
40
+ :send_environment_metadata => true,
41
+ :send_params => true,
34
42
  :skip_session_data => false,
35
- :enable_allocation_tracking => true,
36
- :enable_gc_instrumentation => false,
37
- :enable_host_metrics => true,
38
- :enable_minutely_probes => true,
39
- :enable_statsd => true,
40
- :ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
41
- :dns_servers => [],
42
- :files_world_accessible => true,
43
43
  :transaction_debug_mode => false
44
44
  }.freeze
45
45
 
46
+ # @api private
47
+ DEFAULT_LOG_LEVEL = Logger::INFO
48
+ # Map from the `log_level` config option to Ruby's Logger level value.
49
+ #
50
+ # The trace level doesn't exist in the Ruby logger so it's mapped to debug.
51
+ # @api private
52
+ LOG_LEVEL_MAP = {
53
+ "error" => Logger::ERROR,
54
+ "warn" => Logger::WARN,
55
+ "info" => Logger::INFO,
56
+ "debug" => Logger::DEBUG,
57
+ "trace" => Logger::DEBUG
58
+ }.freeze
59
+
46
60
  ENV_TO_KEY_MAPPING = {
47
61
  "APPSIGNAL_ACTIVE" => :active,
48
- "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
49
62
  "APPSIGNAL_APP_NAME" => :name,
50
- "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
63
+ "APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
51
64
  "APPSIGNAL_DEBUG" => :debug,
52
- "APPSIGNAL_LOG" => :log,
53
- "APPSIGNAL_LOG_PATH" => :log_path,
54
- "APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
55
- "APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
56
- "APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
57
- "APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
58
- "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
59
- "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
60
- "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
61
- "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
62
- "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
63
- "APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
64
- "APPSIGNAL_SEND_PARAMS" => :send_params,
65
- "APPSIGNAL_HTTP_PROXY" => :http_proxy,
65
+ "APPSIGNAL_DNS_SERVERS" => :dns_servers,
66
66
  "APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
67
67
  "APPSIGNAL_ENABLE_GC_INSTRUMENTATION" => :enable_gc_instrumentation,
68
- "APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
69
- "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
70
- "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
71
68
  "APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
72
69
  "APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
73
70
  "APPSIGNAL_ENABLE_STATSD" => :enable_statsd,
74
- "APPSIGNAL_HOSTNAME" => :hostname,
75
- "APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
76
- "APPSIGNAL_DNS_SERVERS" => :dns_servers,
77
71
  "APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible,
72
+ "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
73
+ "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
74
+ "APPSIGNAL_HOSTNAME" => :hostname,
75
+ "APPSIGNAL_HTTP_PROXY" => :http_proxy,
76
+ "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
77
+ "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
78
+ "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
79
+ "APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
80
+ "APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
81
+ "APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
82
+ "APPSIGNAL_LOG" => :log,
83
+ "APPSIGNAL_LOG_LEVEL" => :log_level,
84
+ "APPSIGNAL_LOG_PATH" => :log_path,
85
+ "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
86
+ "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
78
87
  "APPSIGNAL_REQUEST_HEADERS" => :request_headers,
88
+ "APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
89
+ "APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
90
+ "APPSIGNAL_SEND_PARAMS" => :send_params,
91
+ "APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
79
92
  "APPSIGNAL_TRANSACTION_DEBUG_MODE" => :transaction_debug_mode,
93
+ "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
94
+ "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
80
95
  "APP_REVISION" => :revision
81
96
  }.freeze
82
97
  # @api private
@@ -86,6 +101,7 @@ module Appsignal
86
101
  APPSIGNAL_HOSTNAME
87
102
  APPSIGNAL_HTTP_PROXY
88
103
  APPSIGNAL_LOG
104
+ APPSIGNAL_LOG_LEVEL
89
105
  APPSIGNAL_LOG_PATH
90
106
  APPSIGNAL_PUSH_API_ENDPOINT
91
107
  APPSIGNAL_PUSH_API_KEY
@@ -239,6 +255,18 @@ module Appsignal
239
255
  config_hash[key] = value
240
256
  end
241
257
 
258
+ def log_level
259
+ if config_hash[:debug] || config_hash[:transaction_debug_mode]
260
+ level = Logger::DEBUG
261
+ end
262
+ option = config_hash[:log_level]
263
+ if option
264
+ log_level_option = LOG_LEVEL_MAP[option]
265
+ level = log_level_option if log_level_option
266
+ end
267
+ level.nil? ? Appsignal::Config::DEFAULT_LOG_LEVEL : level
268
+ end
269
+
242
270
  def log_file_path
243
271
  path = config_hash[:log_path] || root_path && File.join(root_path, "log")
244
272
  if path && File.writable?(path)
@@ -268,32 +296,35 @@ module Appsignal
268
296
 
269
297
  def write_to_environment # rubocop:disable Metrics/AbcSize
270
298
  ENV["_APPSIGNAL_ACTIVE"] = active?.to_s
271
- ENV["_APPSIGNAL_APP_PATH"] = root_path.to_s
272
299
  ENV["_APPSIGNAL_AGENT_PATH"] = File.expand_path("../../../ext", __FILE__).to_s
300
+ ENV["_APPSIGNAL_APP_NAME"] = config_hash[:name]
301
+ ENV["_APPSIGNAL_APP_PATH"] = root_path.to_s
302
+ ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
303
+ ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
304
+ ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
305
+ ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
306
+ ENV["_APPSIGNAL_ENABLE_STATSD"] = config_hash[:enable_statsd].to_s
273
307
  ENV["_APPSIGNAL_ENVIRONMENT"] = env
308
+ ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = config_hash[:files_world_accessible].to_s
309
+ ENV["_APPSIGNAL_FILTER_PARAMETERS"] = config_hash[:filter_parameters].join(",")
310
+ ENV["_APPSIGNAL_FILTER_SESSION_DATA"] = config_hash[:filter_session_data].join(",")
311
+ ENV["_APPSIGNAL_HOSTNAME"] = config_hash[:hostname].to_s
312
+ ENV["_APPSIGNAL_HTTP_PROXY"] = config_hash[:http_proxy]
313
+ ENV["_APPSIGNAL_IGNORE_ACTIONS"] = config_hash[:ignore_actions].join(",")
314
+ ENV["_APPSIGNAL_IGNORE_ERRORS"] = config_hash[:ignore_errors].join(",")
315
+ ENV["_APPSIGNAL_IGNORE_NAMESPACES"] = config_hash[:ignore_namespaces].join(",")
274
316
  ENV["_APPSIGNAL_LANGUAGE_INTEGRATION_VERSION"] = "ruby-#{Appsignal::VERSION}"
275
- ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
276
317
  ENV["_APPSIGNAL_LOG"] = config_hash[:log]
318
+ ENV["_APPSIGNAL_LOG_LEVEL"] = config_hash[:log_level]
277
319
  ENV["_APPSIGNAL_LOG_FILE_PATH"] = log_file_path.to_s if log_file_path
320
+ ENV["_APPSIGNAL_PROCESS_NAME"] = $PROGRAM_NAME
278
321
  ENV["_APPSIGNAL_PUSH_API_ENDPOINT"] = config_hash[:endpoint]
279
322
  ENV["_APPSIGNAL_PUSH_API_KEY"] = config_hash[:push_api_key]
280
- ENV["_APPSIGNAL_APP_NAME"] = config_hash[:name]
281
- ENV["_APPSIGNAL_HTTP_PROXY"] = config_hash[:http_proxy]
282
- ENV["_APPSIGNAL_IGNORE_ACTIONS"] = config_hash[:ignore_actions].join(",")
283
- ENV["_APPSIGNAL_IGNORE_ERRORS"] = config_hash[:ignore_errors].join(",")
284
- ENV["_APPSIGNAL_IGNORE_NAMESPACES"] = config_hash[:ignore_namespaces].join(",")
285
323
  ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"] = config_hash[:running_in_container].to_s
286
- ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path] if config_hash[:working_dir_path]
287
- ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"] = config_hash[:working_directory_path] if config_hash[:working_directory_path]
288
- ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
289
- ENV["_APPSIGNAL_HOSTNAME"] = config_hash[:hostname].to_s
290
- ENV["_APPSIGNAL_PROCESS_NAME"] = $PROGRAM_NAME
291
- ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
292
- ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
293
- ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = config_hash[:files_world_accessible].to_s
294
- ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"] = config_hash[:transaction_debug_mode].to_s
295
324
  ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"] = config_hash[:send_environment_metadata].to_s
296
- ENV["_APPSIGNAL_ENABLE_STATSD"] = config_hash[:enable_statsd].to_s
325
+ ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"] = config_hash[:transaction_debug_mode].to_s
326
+ ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"] = config_hash[:working_directory_path] if config_hash[:working_directory_path]
327
+ ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path] if config_hash[:working_dir_path]
297
328
  ENV["_APP_REVISION"] = config_hash[:revision].to_s
298
329
  end
299
330
 
@@ -339,7 +370,8 @@ module Appsignal
339
370
  def load_from_disk
340
371
  return if !config_file || !File.exist?(config_file)
341
372
 
342
- configurations = YAML.load(ERB.new(IO.read(config_file)).result)
373
+ read_options = RUBY_VERSION >= "3.1.0" ? { :aliases => true } : {}
374
+ configurations = YAML.load(ERB.new(IO.read(config_file)).result, **read_options)
343
375
  config_for_this_env = configurations[env]
344
376
  if config_for_this_env
345
377
  config_for_this_env =
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ class EventFormatter
5
+ # @api private
6
+ module Sequel
7
+ # Compatability with the sequel-rails gem.
8
+ # The sequel-rails gem adds its own ActiveSupport::Notifications events
9
+ # that conflict with our own sequel instrumentor. Without this event
10
+ # formatter the sequel-rails events are recorded without the SQL query
11
+ # that's being executed.
12
+ class SqlFormatter
13
+ def format(payload)
14
+ [payload[:name].to_s, payload[:sql], SQL_BODY_FORMAT]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ Appsignal::EventFormatter.register(
22
+ "sql.sequel",
23
+ Appsignal::EventFormatter::Sequel::SqlFormatter
24
+ )
@@ -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
@@ -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
@@ -158,7 +158,11 @@ module Appsignal
158
158
 
159
159
  # Based on: https://github.com/mperham/sidekiq/blob/63ee43353bd3b753beb0233f64865e658abeb1c3/lib/sidekiq/api.rb#L403-L412
160
160
  def safe_load(content, default)
161
- yield(*YAML.load(content))
161
+ if RUBY_VERSION >= "3.1.0"
162
+ yield(*YAML.unsafe_load(content))
163
+ else
164
+ yield(*YAML.load(content))
165
+ end
162
166
  rescue => error
163
167
  # Sidekiq issue #1761: in dev mode, it's possible to have jobs enqueued
164
168
  # which haven't been loaded into memory yet so the YAML can't be
@@ -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
@@ -106,9 +106,5 @@ module Appsignal
106
106
  def self.jruby?
107
107
  RUBY_PLATFORM == "java"
108
108
  end
109
-
110
- def self.ruby_2_7_or_newer?
111
- RUBY_VERSION > "2.7"
112
- end
113
109
  end
114
110
  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.message.to_s,
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.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.0.15".freeze
4
+ VERSION = "3.0.19".freeze
5
5
  end
data/lib/appsignal.rb CHANGED
@@ -116,12 +116,7 @@ module Appsignal
116
116
  )
117
117
 
118
118
  if config.valid?
119
- logger.level =
120
- if config[:debug]
121
- Logger::DEBUG
122
- else
123
- Logger::INFO
124
- end
119
+ logger.level = config.log_level
125
120
  if config.active?
126
121
  logger.info "Starting AppSignal #{Appsignal::VERSION} "\
127
122
  "(#{$PROGRAM_NAME}, Ruby #{RUBY_VERSION}, #{RUBY_PLATFORM})"
@@ -230,12 +225,11 @@ module Appsignal
230
225
  end
231
226
 
232
227
  logger.level =
233
- if config && config[:debug]
234
- Logger::DEBUG
228
+ if config
229
+ config.log_level
235
230
  else
236
- Logger::INFO
231
+ Appsignal::Config::DEFAULT_LOG_LEVEL
237
232
  end
238
-
239
233
  logger << @in_memory_log.string if @in_memory_log
240
234
  end
241
235
 
data/script/lint_git CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  set -eu
4
4
 
5
- LINTJE_VERSION="0.5.0"
5
+ LINTJE_VERSION="0.6.1"
6
6
 
7
7
  mkdir -p $HOME/bin
8
8
  cache_key=v1-lintje-$LINTJE_VERSION