stackify-ruby-apm 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +38 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +17 -11
  5. data/Gemfile.lock +98 -95
  6. data/Rakefile +7 -5
  7. data/docker/stackify-ruby +8 -0
  8. data/docker/stackify-ruby-rvm +10 -0
  9. data/docker/stackify-ruby-test +28 -0
  10. data/lib/{stackify → stackify_apm}/agent.rb +42 -33
  11. data/lib/{stackify → stackify_apm}/config.rb +56 -39
  12. data/lib/{stackify → stackify_apm}/context.rb +5 -6
  13. data/lib/{stackify → stackify_apm}/context/request.rb +0 -0
  14. data/lib/{stackify → stackify_apm}/context/request/socket.rb +0 -0
  15. data/lib/{stackify → stackify_apm}/context/request/url.rb +2 -6
  16. data/lib/stackify_apm/context/response.rb +33 -0
  17. data/lib/{stackify → stackify_apm}/context_builder.rb +2 -5
  18. data/lib/{stackify → stackify_apm}/error.rb +7 -6
  19. data/lib/stackify_apm/error/exception.rb +37 -0
  20. data/lib/stackify_apm/error/log.rb +24 -0
  21. data/lib/stackify_apm/error_builder.rb +61 -0
  22. data/lib/stackify_apm/helper/database_helper.rb +27 -0
  23. data/lib/{stackify → stackify_apm}/instrumenter.rb +12 -19
  24. data/lib/{stackify → stackify_apm}/internal_error.rb +0 -0
  25. data/lib/{stackify → stackify_apm}/log.rb +0 -0
  26. data/lib/{stackify → stackify_apm}/logger/log_device.rb +22 -11
  27. data/lib/{stackify → stackify_apm}/logger/logger_high_version.rb +1 -6
  28. data/lib/{stackify → stackify_apm}/logger/logger_lower_version.rb +2 -1
  29. data/lib/stackify_apm/middleware.rb +70 -0
  30. data/lib/{stackify → stackify_apm}/naively_hashable.rb +1 -3
  31. data/lib/{stackify → stackify_apm}/normalizers.rb +3 -2
  32. data/lib/{stackify → stackify_apm}/normalizers/action_controller.rb +0 -0
  33. data/lib/{stackify → stackify_apm}/normalizers/action_mailer.rb +0 -0
  34. data/lib/{stackify → stackify_apm}/normalizers/action_view.rb +0 -0
  35. data/lib/{stackify → stackify_apm}/normalizers/active_record.rb +3 -25
  36. data/lib/{stackify → stackify_apm}/railtie.rb +5 -7
  37. data/lib/{stackify → stackify_apm}/root_info.rb +2 -6
  38. data/lib/{stackify → stackify_apm}/serializers.rb +3 -2
  39. data/lib/{stackify → stackify_apm}/serializers/errors.rb +7 -10
  40. data/lib/{stackify → stackify_apm}/serializers/transactions.rb +11 -18
  41. data/lib/{stackify → stackify_apm}/span.rb +8 -9
  42. data/lib/{stackify → stackify_apm}/span/context.rb +3 -1
  43. data/lib/{stackify → stackify_apm}/spies.rb +3 -2
  44. data/lib/{stackify → stackify_apm}/spies/action_dispatch.rb +3 -4
  45. data/lib/stackify_apm/spies/curb.rb +49 -0
  46. data/lib/stackify_apm/spies/curb/easy.rb +157 -0
  47. data/lib/stackify_apm/spies/curb/multi.rb +43 -0
  48. data/lib/{stackify → stackify_apm}/spies/httpclient.rb +10 -8
  49. data/lib/{stackify → stackify_apm}/spies/httprb.rb +7 -9
  50. data/lib/{stackify → stackify_apm}/spies/mongo.rb +5 -3
  51. data/lib/{stackify → stackify_apm}/spies/net_http.rb +4 -5
  52. data/lib/{stackify → stackify_apm}/spies/redis.rb +19 -18
  53. data/lib/stackify_apm/spies/sequel.rb +65 -0
  54. data/lib/{stackify → stackify_apm}/spies/sinatra.rb +7 -10
  55. data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +201 -0
  56. data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +94 -0
  57. data/lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb +46 -0
  58. data/lib/stackify_apm/spies/stackify_logger.rb +60 -0
  59. data/lib/{stackify → stackify_apm}/spies/tilt.rb +3 -3
  60. data/lib/stackify_apm/stacktrace.rb +18 -0
  61. data/lib/stackify_apm/stacktrace/frame.rb +47 -0
  62. data/lib/{stackify → stackify_apm}/stacktrace_builder.rb +10 -11
  63. data/lib/{stackify → stackify_apm}/subscriber.rb +20 -14
  64. data/lib/{stackify → stackify_apm}/trace_logger.rb +10 -16
  65. data/lib/stackify_apm/transaction.rb +127 -0
  66. data/lib/{stackify → stackify_apm}/util.rb +3 -1
  67. data/lib/{stackify → stackify_apm}/util/dig.rb +1 -1
  68. data/lib/{stackify → stackify_apm}/util/inflector.rb +0 -0
  69. data/lib/{stackify → stackify_apm}/util/inspector.rb +1 -3
  70. data/lib/stackify_apm/util/lru_cache.rb +49 -0
  71. data/lib/stackify_apm/util/trace_log_watcher.rb +37 -0
  72. data/lib/stackify_apm/version.rb +6 -0
  73. data/lib/{stackify → stackify_apm}/worker.rb +8 -7
  74. data/lib/stackify_ruby_apm.rb +18 -15
  75. data/run-test-docker.sh +50 -0
  76. data/run-test.sh +1 -3
  77. data/stackify-ruby-apm.gemspec +14 -11
  78. metadata +86 -59
  79. data/lib/stackify/context/response.rb +0 -37
  80. data/lib/stackify/error/exception.rb +0 -36
  81. data/lib/stackify/error/log.rb +0 -25
  82. data/lib/stackify/error_builder.rb +0 -65
  83. data/lib/stackify/middleware.rb +0 -74
  84. data/lib/stackify/spies/sinatra_activerecord/mysql_adapter.rb +0 -177
  85. data/lib/stackify/spies/sinatra_activerecord/postgresql_adapter.rb +0 -96
  86. data/lib/stackify/spies/sinatra_activerecord/sqlite_adapter.rb +0 -48
  87. data/lib/stackify/stacktrace.rb +0 -19
  88. data/lib/stackify/stacktrace/frame.rb +0 -50
  89. data/lib/stackify/transaction.rb +0 -132
  90. data/lib/stackify/util/lru_cache.rb +0 -49
  91. data/lib/stackify/version.rb +0 -4
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
- # Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
3
- #
4
- module StackifyRubyAPM
5
- # @api private
6
- module Spies
7
- # @api private
8
- class SqliteAdapterSpy
9
- TYPE = 'db.sinatra_active_record.sql'.freeze
10
-
11
- # rubocop:disable Metrics/MethodLength
12
- def install
13
- ActiveRecord::ConnectionAdapters::SQLite3Adapter.class_eval do
14
- alias exec_query_without_apm exec_query
15
-
16
-
17
- def exec_query(sql, name = "SQL", binds = [], prepare: false)
18
- result = nil
19
-
20
- unless StackifyRubyAPM.current_transaction
21
- exec_query_without_apm(sql, name, binds)
22
- end
23
-
24
- ctx = Span::Context.new(
25
- CATEGORY: 'Database',
26
- SUBCATEGORY: 'Execute',
27
- COMPONENT_CATEGORY: 'DB Query',
28
- COMPONENT_DETAIL: 'Execute SQL Query',
29
- SQL: sql,
30
- PROVIDER: "sqlite"
31
- )
32
-
33
- result = exec_query_without_apm(sql, name, binds)
34
-
35
- StackifyRubyAPM.span name, TYPE, context: ctx do
36
- return result
37
- end
38
- end
39
-
40
- end
41
- end
42
- # rubocop:enable Metrics/MethodLength
43
- end
44
-
45
- register 'ActiveRecord::ConnectionAdapters::SQLite3Adapter', 'active_record/connection_adapters/sqlite3_adapter', SqliteAdapterSpy.new
46
- end
47
- end
48
-
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This module starts creation for frames
4
- #
5
- module StackifyRubyAPM
6
- # @api private
7
- class Stacktrace
8
- attr_accessor :frames
9
-
10
- def length
11
- frames.length
12
- end
13
-
14
- def to_a
15
- frames.map(&:to_h)
16
- end
17
- end
18
- end
19
-
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StackifyRubyAPM
4
- class Stacktrace
5
- # @api private
6
- class Frame
7
- include NaivelyHashable
8
-
9
- attr_accessor(
10
- :abs_path,
11
- :filename,
12
- :function,
13
- :vars,
14
- :pre_context,
15
- :context_line,
16
- :post_context,
17
- :library_frame,
18
- :lineno,
19
- :module,
20
- :Method,
21
- :colno
22
- )
23
-
24
- # rubocop:disable Metrics/AbcSize
25
- def build_context(context_line_count)
26
- return unless abs_path && context_line_count > 0
27
-
28
- padding = (context_line_count - 1) / 2
29
- from = lineno - padding - 1
30
- from = 0 if from < 0
31
- to = lineno + padding - 1
32
- file_lines = read_lines(abs_path, from..to)
33
-
34
- self.context_line = file_lines[padding]
35
- self.pre_context = file_lines.first(padding)
36
- self.post_context = file_lines.last(padding)
37
- end
38
- # rubocop:enable Metrics/AbcSize
39
-
40
- private
41
-
42
- def read_lines(path, range)
43
- File.readlines(path)[range]
44
- rescue Errno::ENOENT
45
- []
46
- end
47
- end
48
- end
49
- end
50
-
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # This class creates and initializes a new transaction.
4
- #
5
-
6
- module StackifyRubyAPM
7
- require 'securerandom'
8
- # @api private
9
- class Transaction
10
- DEFAULT_TYPE = 'custom'.freeze
11
-
12
- # rubocop:disable Metrics/MethodLength
13
- def initialize instrumenter, name = nil, type = nil, context: nil
14
- # puts "Loads transaction new initialize instrumenter, name = nil, type = nil, context: nil"
15
- @id = SecureRandom.uuid
16
- @instrumenter = instrumenter
17
- @name = name
18
- @type = type || DEFAULT_TYPE
19
- @timestamp = (Time.now).to_f * 1000
20
-
21
- @spans = []
22
- @span_id_ticker = -1
23
- @dropped_spans = 0
24
-
25
- @notifications = [] # for AS::Notifications
26
- @context = context || Context.new
27
- @exceptions = []
28
-
29
- yield self if block_given?
30
- end
31
- # rubocop:enable Metrics/MethodLength
32
-
33
- attr_accessor :name, :type, :http_status
34
- attr_reader :id, :context, :duration, :dropped_spans,
35
- :timestamp, :spans, :result, :notifications, :instrumenter, :exceptions
36
-
37
- def add_exception exception
38
- @exceptions << exception
39
- end
40
-
41
- def release
42
- @instrumenter.current_transaction = nil
43
- end
44
-
45
- def done result = nil
46
- @duration = (Time.now).to_f * 1000
47
- @result = result
48
- @http_status = result
49
-
50
- self
51
- end
52
-
53
- def done?
54
- !!@duration
55
- end
56
-
57
- def submit result = nil, status: nil, headers: {}
58
- done result unless duration
59
- if status
60
- context.response = Context::Response.new(status, headers: headers)
61
- end
62
-
63
- release
64
- @instrumenter.submit_transaction self
65
-
66
- self
67
- end
68
- # This method is being used in unit testing
69
- def running_spans
70
- spans.select(&:running?)
71
- end
72
- # rubocop:disable Metrics/MethodLength
73
- def span name, type = nil, backtrace: nil, context: nil
74
- span = build_and_start_span(name, type, context, backtrace)
75
- return span unless block_given?
76
-
77
- begin
78
- result = yield span
79
- ensure
80
- span.done
81
- end
82
-
83
- result
84
- end
85
- # rubocop:enable Metrics/MethodLength
86
-
87
- def current_span
88
- spans.reverse.lazy.find(&:running?)
89
- end
90
-
91
- def inspect
92
- "<StackifyRubyAPM::Transaction id:#{id}" \
93
- " name:#{name.inspect}" \
94
- " type:#{type.inspect}" \
95
- '>'
96
- end
97
-
98
- private
99
-
100
- def next_span_id
101
- @span_id_ticker += 1
102
- end
103
-
104
- def next_span name, type, context
105
- Span.new(
106
- self,
107
- next_span_id,
108
- name,
109
- type,
110
- parent_id: current_span.nil? ? -1 : current_span.id,
111
- context: context,
112
- http_status: @http_status
113
- )
114
- end
115
-
116
- def span_frames_min_duration?
117
- @instrumenter.agent.config.span_frames_min_duration != 0
118
- end
119
-
120
- def build_and_start_span name, type, context, backtrace
121
- span = next_span(name, type, context)
122
- spans << span
123
-
124
- if backtrace && span_frames_min_duration?
125
- span.original_backtrace = backtrace
126
- end
127
-
128
- span.start
129
- end
130
-
131
- end
132
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StackifyRubyAPM
4
- module Util
5
- # @api private
6
- class LruCache
7
- def initialize(max_size = 512, &block)
8
- @max_size = max_size
9
- @data = Hash.new(&block)
10
- @mutex = Mutex.new
11
- end
12
-
13
- def [](key)
14
- @mutex.synchronize do
15
- val = @data[key]
16
- return unless val
17
- add(key, val)
18
- val
19
- end
20
- end
21
-
22
- def []=(key, val)
23
- @mutex.synchronize do
24
- add(key, val)
25
- end
26
- end
27
-
28
- def length
29
- @data.length
30
- end
31
-
32
- def to_a
33
- @data.to_a
34
- end
35
-
36
- private
37
-
38
- def add(key, val)
39
- @data.delete(key)
40
- @data[key] = val
41
-
42
- return unless @data.length > @max_size
43
-
44
- @data.delete(@data.first[0])
45
- end
46
- end
47
- end
48
- end
49
-
@@ -1,4 +0,0 @@
1
- # Sets the version of the APM
2
- module StackifyRubyAPM
3
- VERSION = '1.0.1'.freeze
4
- end