heimdall_apm 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9ca420677755ff0041326907530a7887a2f8a328
4
- data.tar.gz: 6dc9025653e4cf087d16cc94d4c69be7e841879a
2
+ SHA256:
3
+ metadata.gz: eac3ebfde6ef8035d0178d14eab1923154711c8059df48d5837a85d746dc829e
4
+ data.tar.gz: 64c57c8f8f47f3ad09f779beb9d5942efbe72695c0803be905563e26b23606bd
5
5
  SHA512:
6
- metadata.gz: bae5184971387ed286e27d9fd7ed4ef8f988f85853fa50fe6f72a64fa7fbd61fcd9868e405a957c5ca7b40598a25de510fff765a5454e04f949379ec4bf0867e
7
- data.tar.gz: cca579bdcd94979119200aaee7ecba688f1e17d26386fefa7635551effdeb54f1180a6a6b46be20dde089b59cc0091067608333d70898225defa3d1baa8dc695
6
+ metadata.gz: 6b1c593c535eb5019e2ea53ce7f1c4f16526e53ef302ddb6a2a5533549b1413269ccde39ec15da3cdc16ee28966d8eedb6f542892293c674886f9ea92f071495
7
+ data.tar.gz: 5d676be2b3bb5280440ad64ba33404a972ac4d033ec3a4fa00f09f090d674297fd15f369661aff396277d44b29b54802db4cd56836b1bfa6a67b6701d8c94b6b
@@ -0,0 +1,5 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.1.3
4
+ * Add configure option to completely ignore endpoints
5
+ * Add Sidekiq support
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/ccocchi/heimdall"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.start_with?('test', 'bin')
16
+ f.start_with?('test', 'bin', 'config')
17
17
  end
18
18
  spec.bindir = "exe"
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -5,10 +5,5 @@ require 'heimdall_apm/probe'
5
5
  require 'heimdall_apm/agent'
6
6
  require 'heimdall_apm/railtie' if defined?(Rails)
7
7
 
8
- require 'logger'
9
-
10
8
  module HeimdallApm
11
- def self.logger
12
- @logger ||= Logger.new('log/heimdall_apm.log')
13
- end
14
9
  end
@@ -29,15 +29,15 @@ module HeimdallApm
29
29
  context.config = ::HeimdallApm::Config.new
30
30
 
31
31
  if context.interactive?
32
- HeimdallApm.logger.info 'Preventing agent to start in interactive mode'
32
+ context.logger.info 'Preventing agent to start in interactive mode'
33
33
  return
34
34
  end
35
35
 
36
- if defined?(Sidekiq) && Sidekiq.server?
37
- # TODO: handle custom instrumentation disabling
38
- HeimdallApm.logger.info 'Preventing agent to start in sidekiq server'
39
- return
40
- end
36
+ # if defined?(Sidekiq) && Sidekiq.server?
37
+ # # TODO: handle custom instrumentation disabling
38
+ # HeimdallApm.logger.info 'Preventing agent to start in sidekiq server'
39
+ # return
40
+ # end
41
41
 
42
42
  start(options)
43
43
  end
@@ -46,9 +46,13 @@ module HeimdallApm
46
46
  return unless context.config.value('enabled')
47
47
 
48
48
  # TODO: use instruments manager
49
- require 'heimdall_apm/instruments/active_record' if defined?(ActiveRecord)
50
- require 'heimdall_apm/instruments/action_controller' if defined?(ActionController)
51
- require 'heimdall_apm/instruments/elasticsearch' if defined?(Elasticsearch)
49
+ if !defined?(Sidekiq) || !Sidekiq.server?
50
+ require 'heimdall_apm/instruments/active_record' if defined?(ActiveRecord)
51
+ require 'heimdall_apm/instruments/action_controller' if defined?(ActionController)
52
+ require 'heimdall_apm/instruments/elasticsearch' if defined?(Elasticsearch)
53
+ end
54
+
55
+ require 'heimdall_apm/instruments/sidekiq' if defined?(Sidekiq) && Sidekiq.server?
52
56
 
53
57
  if (options[:app])
54
58
  require 'heimdall_apm/instruments/middleware'
@@ -64,7 +68,7 @@ module HeimdallApm
64
68
  end
65
69
 
66
70
  def stop
67
- HeimdallApm.logger.info 'Stopping agent...'
71
+ context.logger.info 'Stopping agent...'
68
72
  @stopped = true
69
73
  context.stopped!
70
74
  if @background_thread.alive?
@@ -76,7 +80,7 @@ module HeimdallApm
76
80
  private
77
81
 
78
82
  def background_run
79
- HeimdallApm.logger.info "Start background thread"
83
+ context.logger.info "Start background thread"
80
84
  reporting = ::HeimdallApm::Reporting.new(@context)
81
85
  next_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + DEFAULT_PUSH_INTERVAL
82
86
 
@@ -91,7 +95,7 @@ module HeimdallApm
91
95
 
92
96
  if now < next_time
93
97
  remaining = next_time - now
94
- HeimdallApm.logger.debug "Sleeping for #{remaining}"
98
+ context.logger.debug { "Sleeping for #{remaining}" }
95
99
  sleep(remaining)
96
100
  next
97
101
  end
@@ -100,7 +104,7 @@ module HeimdallApm
100
104
  next_time = now + DEFAULT_PUSH_INTERVAL
101
105
  end
102
106
  rescue => e
103
- HeimdallApm.logger.error e.message
107
+ context.logger.error e.message
104
108
  end
105
109
  end
106
110
  end
@@ -1,6 +1,10 @@
1
+ require 'set'
2
+ require 'logger'
3
+
1
4
  require 'heimdall_apm/vault'
2
5
  require 'heimdall_apm/recorder'
3
6
  require 'heimdall_apm/config'
7
+ require 'heimdall_apm/uri_matcher'
4
8
 
5
9
  module HeimdallApm
6
10
  # Global context in which the agent is run. One context is assigned per
@@ -27,6 +31,14 @@ module HeimdallApm
27
31
  @config ||= ::HeimdallApm::Config.new
28
32
  end
29
33
 
34
+ def logger
35
+ @logger ||= begin
36
+ logger = Logger.new('log/heimdall_apm.log')
37
+ logger.level = config['log_level'].presence || :debug
38
+ logger
39
+ end
40
+ end
41
+
30
42
  def vault
31
43
  @vault ||= ::HeimdallApm::Vault.new(self)
32
44
  end
@@ -35,6 +47,10 @@ module HeimdallApm
35
47
  @recorder ||= ::HeimdallApm::Recorder.new
36
48
  end
37
49
 
50
+ def ignored_uris
51
+ @ignored_uris ||= ::HeimdallApm::UriMatcher.new(config.value('ignore'))
52
+ end
53
+
38
54
  def interactive?
39
55
  defined?(::Rails::Console) && $stdout.isatty && $stdin.isatty
40
56
  end
@@ -6,7 +6,13 @@ module HeimdallApm
6
6
  scope = -"#{payload[:controller]}##{payload[:action]}"
7
7
  segment = ::HeimdallApm::Segment.new('Controller'.freeze, scope)
8
8
 
9
+ # Don't override scope if already set. Should never happen in practice
10
+ # unless a controller calls another action.
9
11
  txn.scope = scope unless txn.scope
12
+
13
+ # Rails gives us Request#fullpath
14
+ txn.annotate({ uri: extract_path(payload[:path]) })
15
+
10
16
  txn.start_segment(segment)
11
17
  end
12
18
 
@@ -14,6 +20,13 @@ module HeimdallApm
14
20
  txn = ::HeimdallApm::TransactionManager.current
15
21
  txn.stop_segment
16
22
  end
23
+
24
+ private
25
+
26
+ def extract_path(fullpath)
27
+ i = fullpath.index('?'.freeze)
28
+ i ? fullpath.slice(0, i) : fullpath
29
+ end
17
30
  end
18
31
  end
19
32
  end
@@ -0,0 +1,41 @@
1
+ module HeimdallApm
2
+ module Instruments
3
+ class SidekiqMiddleware
4
+ def call(_worker, item, queue, redis_pool = nil)
5
+ txn = ::HeimdallApm::TransactionManager.current
6
+ txn.annotate(latency: latency(item))
7
+ txn.scope = unwrapped_worker_name(item)
8
+
9
+ segment = ::HeimdallApm::Segment.new('Job'.freeze, 'all'.freeze)
10
+ txn.start_segment(segment)
11
+
12
+ yield
13
+ ensure
14
+ txn.stop_segment
15
+ end
16
+
17
+ private
18
+
19
+ def unwrapped_worker_name(item)
20
+ item['wrapped'] || item['class']
21
+ end
22
+
23
+ def latency(item)
24
+ created_at = item['enqueued_at'] || item['created_at']
25
+ if created_at
26
+ (Time.now.to_f - created_at)
27
+ else
28
+ 0.0
29
+ end
30
+ rescue
31
+ 0.0
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ Sidekiq.configure_server do |config|
38
+ config.server_middleware do |chain|
39
+ chain.add HeimdallApm::Instruments::SidekiqMiddleware
40
+ end
41
+ end
@@ -27,6 +27,8 @@ module HeimdallApm
27
27
  @points
28
28
  end
29
29
 
30
+ # TODO: this looks very custom, need to find a way to better map a txn and
31
+ # its segment into InfluxDB.
30
32
  def append(txn, metrics)
31
33
  timestamp = txn.root_segment.stop_time
32
34
  series_name = txn.custom_series_name || (txn.web? ? 'app' : 'job')
@@ -48,6 +50,8 @@ module HeimdallApm
48
50
  values['total_time'] += stat.total_exclusive_time
49
51
  end
50
52
 
53
+ values['latency'] = txn.annotations[:latency] if txn.annotations[:latency]
54
+
51
55
  # Segment time are in seconds, store them in milliseconds
52
56
  values.transform_values! { |v| v.is_a?(Integer) ? v : v * 1000 }
53
57
 
@@ -4,6 +4,7 @@ module HeimdallApm
4
4
  @context = context
5
5
  end
6
6
 
7
+ # TODO: make this configurable
7
8
  def influx
8
9
  @client ||= InfluxDB::Client.new("#{Rails.env}_metrics", time_precision: 'ms', retry: 0)
9
10
  end
@@ -13,10 +14,10 @@ module HeimdallApm
13
14
  if span && !span.points_collection.empty?
14
15
  influx.write_points(span.points_collection.to_a)
15
16
  else
16
- HeimdallApm.logger.debug "Nothing to report"
17
+ @context.logger.debug "Nothing to report"
17
18
  end
18
19
  rescue => e
19
- HeimdallApm.logger.error "#{e.message} during reporting to InfluxDB"
20
+ @context.logger.error "#{e.message} during reporting to InfluxDB"
20
21
  end
21
22
  end
22
23
  end
@@ -72,7 +72,10 @@ module HeimdallApm
72
72
  }
73
73
 
74
74
  def record
75
- return unless root_segment
75
+ # TODO: investigate on why mode can be nil sometimes
76
+ return unless root_segment && @mode
77
+ # TODO: doesn't feel like it should be done here
78
+ return if annotations[:uri] && @context.ignored_uris.match?(annotations[:uri])
76
79
 
77
80
  VISITORS.each do |_, klass|
78
81
  visitor = klass.new(@vault, self)
@@ -0,0 +1,11 @@
1
+ module HeimdallApm
2
+ class UriMatcher
3
+ def initialize(prefixes)
4
+ @prefixes = Array(prefixes)
5
+ end
6
+
7
+ def match?(uri)
8
+ @prefixes.empty? ? false : uri.start_with?(*@prefixes)
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module HeimdallApm
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heimdall_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Cocchi-Perrier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-13 00:00:00.000000000 Z
11
+ date: 2018-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -61,6 +61,7 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - ".gitignore"
63
63
  - ".travis.yml"
64
+ - CHANGELOG.md
64
65
  - Gemfile
65
66
  - Gemfile.lock
66
67
  - LICENSE
@@ -75,6 +76,7 @@ files:
75
76
  - lib/heimdall_apm/instruments/active_record.rb
76
77
  - lib/heimdall_apm/instruments/elasticsearch.rb
77
78
  - lib/heimdall_apm/instruments/middleware.rb
79
+ - lib/heimdall_apm/instruments/sidekiq.rb
78
80
  - lib/heimdall_apm/metric_name.rb
79
81
  - lib/heimdall_apm/metric_stats.rb
80
82
  - lib/heimdall_apm/points_collection.rb
@@ -85,6 +87,7 @@ files:
85
87
  - lib/heimdall_apm/segment.rb
86
88
  - lib/heimdall_apm/tracked_transaction.rb
87
89
  - lib/heimdall_apm/transaction_manager.rb
90
+ - lib/heimdall_apm/uri_matcher.rb
88
91
  - lib/heimdall_apm/vault.rb
89
92
  - lib/heimdall_apm/version.rb
90
93
  - lib/heimdall_apm/visitors/pretty_print_visitor.rb
@@ -109,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
112
  version: '0'
110
113
  requirements: []
111
114
  rubyforge_project:
112
- rubygems_version: 2.6.13
115
+ rubygems_version: 2.7.6
113
116
  signing_key:
114
117
  specification_version: 4
115
118
  summary: Open source monitoring for Rails applications