stackify-ruby-apm 1.0.1 → 1.1.0

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 (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