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 +5 -5
- data/CHANGELOG.md +5 -0
- data/heimdall_apm.gemspec +1 -1
- data/lib/heimdall_apm.rb +0 -5
- data/lib/heimdall_apm/agent.rb +17 -13
- data/lib/heimdall_apm/agent_context.rb +16 -0
- data/lib/heimdall_apm/instruments/action_controller.rb +13 -0
- data/lib/heimdall_apm/instruments/sidekiq.rb +41 -0
- data/lib/heimdall_apm/points_collection.rb +4 -0
- data/lib/heimdall_apm/reporting.rb +3 -2
- data/lib/heimdall_apm/tracked_transaction.rb +4 -1
- data/lib/heimdall_apm/uri_matcher.rb +11 -0
- data/lib/heimdall_apm/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eac3ebfde6ef8035d0178d14eab1923154711c8059df48d5837a85d746dc829e
|
4
|
+
data.tar.gz: 64c57c8f8f47f3ad09f779beb9d5942efbe72695c0803be905563e26b23606bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b1c593c535eb5019e2ea53ce7f1c4f16526e53ef302ddb6a2a5533549b1413269ccde39ec15da3cdc16ee28966d8eedb6f542892293c674886f9ea92f071495
|
7
|
+
data.tar.gz: 5d676be2b3bb5280440ad64ba33404a972ac4d033ec3a4fa00f09f090d674297fd15f369661aff396277d44b29b54802db4cd56836b1bfa6a67b6701d8c94b6b
|
data/CHANGELOG.md
ADDED
data/heimdall_apm.gemspec
CHANGED
@@ -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) }
|
data/lib/heimdall_apm.rb
CHANGED
data/lib/heimdall_apm/agent.rb
CHANGED
@@ -29,15 +29,15 @@ module HeimdallApm
|
|
29
29
|
context.config = ::HeimdallApm::Config.new
|
30
30
|
|
31
31
|
if context.interactive?
|
32
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
17
|
+
@context.logger.debug "Nothing to report"
|
17
18
|
end
|
18
19
|
rescue => e
|
19
|
-
|
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
|
-
|
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)
|
data/lib/heimdall_apm/version.rb
CHANGED
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.
|
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-
|
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
|
115
|
+
rubygems_version: 2.7.6
|
113
116
|
signing_key:
|
114
117
|
specification_version: 4
|
115
118
|
summary: Open source monitoring for Rails applications
|