appsignal 3.0.15-java → 3.0.19-java

Sign up to get free protection for your applications and to get access to all the features.
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