instana 0.1.0 → 0.8.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -2
- data/README.md +15 -6
- data/Rakefile +5 -0
- data/instana.gemspec +8 -2
- data/lib/instana.rb +37 -4
- data/lib/instana/agent.rb +159 -7
- data/lib/instana/collectors.rb +47 -0
- data/lib/instana/collectors/gc.rb +63 -0
- data/lib/instana/collectors/memory.rb +41 -0
- data/lib/instana/collectors/thread.rb +39 -0
- data/lib/instana/config.rb +24 -0
- data/lib/instana/util.rb +52 -0
- data/lib/instana/version.rb +1 -1
- metadata +55 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c7002d4134c228c245a364723eaca19b0f1f46c
|
4
|
+
data.tar.gz: 72ed46de39b20562edd678d53c41440807255bf9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6334386fa5f9088f80156783cee4c4c6416fa87bdc376b9cda97f275d19759a1f581501a81560f8647952e3cab6c58e9e8a82542222c9ff776f3b7dc0b5ee5c4
|
7
|
+
data.tar.gz: 81077cde159bfe0fac9a95ced6287d3e797a8dce11c360a711ccbe6039e81d756337b4092a169a9086eafa2920a4f2c615144639427fbbf864d88a33673c18b2
|
data/Gemfile
CHANGED
@@ -3,9 +3,8 @@ source 'https://rubygems.org'
|
|
3
3
|
group :development, :test do
|
4
4
|
gem 'rake'
|
5
5
|
gem 'minitest'
|
6
|
-
gem 'minitest-reporters'
|
6
|
+
gem 'minitest-reporters'
|
7
7
|
gem 'minitest-debugger', :require => false
|
8
|
-
gem 'rack-test'
|
9
8
|
end
|
10
9
|
|
11
10
|
group :development do
|
@@ -20,5 +19,9 @@ group :development do
|
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
22
|
+
gem 'get_process_mem'
|
23
|
+
gem 'sys-proctable'
|
24
|
+
gem 'timers'
|
25
|
+
|
23
26
|
# instana.gemspec
|
24
27
|
gemspec
|
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# Instana
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
The Instana gem provides Ruby metrics for [Instana](https://www.instana.com/).
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
9
|
-
|
7
|
+
The gem is available on [Rubygems](https://rubygems.org/gems/instana). To install, add this line to _the end_ of your application's Gemfile:
|
10
8
|
|
11
9
|
```ruby
|
12
10
|
gem 'instana'
|
@@ -22,7 +20,18 @@ Or install it yourself as:
|
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
The instana gem is a zero configuration tool that will automatically collect key metrics from your Ruby processes. Just install and go.
|
24
|
+
|
25
|
+
## Configuration
|
26
|
+
|
27
|
+
Although the gem has no configuration required for metrics, individual components can be disabled with a local config.
|
28
|
+
|
29
|
+
To disable a single component in the gem, you can disable a single component with the following code:
|
30
|
+
|
31
|
+
```Ruby
|
32
|
+
::Instana.config[:metrics][:gc][:enabled] = false
|
33
|
+
```
|
34
|
+
Current components are `:gc`, `:memory` and `:thread`.
|
26
35
|
|
27
36
|
## Development
|
28
37
|
|
@@ -32,5 +41,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
41
|
|
33
42
|
## Contributing
|
34
43
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
44
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/instana/ruby-sensor.
|
36
45
|
|
data/Rakefile
CHANGED
@@ -2,12 +2,17 @@ require "bundler/gem_tasks"
|
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
4
|
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.verbose = false
|
6
|
+
t.warning = false
|
7
|
+
t.ruby_opts = []
|
8
|
+
|
5
9
|
t.libs << "test"
|
6
10
|
t.libs << "lib"
|
7
11
|
t.test_files = FileList['test/**/*_test.rb']
|
8
12
|
end
|
9
13
|
|
10
14
|
task :environment do
|
15
|
+
ENV['INSTANA_GEM_DEV'] = 'true'
|
11
16
|
Bundler.require(:default, :development)
|
12
17
|
end
|
13
18
|
|
data/instana.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Peter Giacomo Lombardo"]
|
10
10
|
spec.email = ["pglombardo@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{
|
12
|
+
spec.summary = %q{Ruby sensor for Instana}
|
13
|
+
spec.description = %q{Provides Ruby sensor instrumentation for Instana.}
|
14
14
|
spec.homepage = "https://www.instana.com/"
|
15
15
|
|
16
16
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
@@ -26,7 +26,13 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
+
spec.required_ruby_version = '>= 2.0'
|
30
|
+
|
29
31
|
spec.add_development_dependency "bundler", "~> 1.11"
|
30
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
33
|
spec.add_development_dependency "minitest", "~> 5.0"
|
34
|
+
|
35
|
+
spec.add_runtime_dependency('sys-proctable', '>= 1.1.3')
|
36
|
+
spec.add_runtime_dependency('get_process_mem', '>= 0.2.1')
|
37
|
+
spec.add_runtime_dependency('timers', '>= 4.1.0')
|
32
38
|
end
|
data/lib/instana.rb
CHANGED
@@ -1,13 +1,46 @@
|
|
1
|
-
|
2
|
-
require "instana/agent"
|
1
|
+
|
3
2
|
require 'logger'
|
3
|
+
require "instana/version"
|
4
|
+
require "instana/util"
|
4
5
|
|
5
6
|
module Instana
|
6
7
|
class << self
|
7
8
|
attr_accessor :agent
|
9
|
+
attr_accessor :collectors
|
10
|
+
attr_accessor :config
|
8
11
|
attr_accessor :logger
|
12
|
+
attr_accessor :pid
|
13
|
+
|
14
|
+
##
|
15
|
+
# start
|
16
|
+
#
|
17
|
+
# Initialize the Instana language agent
|
18
|
+
#
|
19
|
+
def start
|
20
|
+
Instana.agent = Instana::Agent.new
|
21
|
+
Instana.collectors = []
|
22
|
+
Instana.logger = Logger.new(STDOUT)
|
23
|
+
Instana.logger.info "Stan is on the scene. Starting Instana instrumentation."
|
24
|
+
|
25
|
+
# Store the current pid so we can detect a potential fork
|
26
|
+
# later on
|
27
|
+
Instana.pid = Process.pid
|
28
|
+
end
|
29
|
+
|
30
|
+
def pid_change?
|
31
|
+
@pid != Process.pid
|
32
|
+
end
|
9
33
|
end
|
10
34
|
end
|
11
35
|
|
12
|
-
|
13
|
-
|
36
|
+
require "instana/config"
|
37
|
+
require "instana/agent"
|
38
|
+
|
39
|
+
::Instana.start
|
40
|
+
|
41
|
+
if ::Instana.agent.host_agent_ready?
|
42
|
+
::Instana.agent.announce_sensor
|
43
|
+
require "instana/collectors"
|
44
|
+
else
|
45
|
+
::Instana.logger.info "Instana host agent not available. Going to sit in a corner quietly."
|
46
|
+
end
|
data/lib/instana/agent.rb
CHANGED
@@ -1,33 +1,185 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'uri'
|
3
3
|
require 'json'
|
4
|
+
require 'sys/proctable'
|
5
|
+
include Sys
|
4
6
|
|
5
7
|
module Instana
|
6
8
|
class Agent
|
7
|
-
|
9
|
+
attr_accessor :last_entity_response
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
# Host agent defaults. Can be configured via Instana.config
|
8
13
|
@request_timeout = 5000
|
9
14
|
@host = '127.0.0.1'
|
10
15
|
@port = 42699
|
11
16
|
@server_header = 'Instana Agent'
|
12
|
-
|
17
|
+
|
18
|
+
# Snapshot data is collected once per process but resent
|
19
|
+
# every 10 minutes along side process metrics.
|
20
|
+
@snapshot = take_snapshot
|
21
|
+
|
22
|
+
# Set last snapshot to 10 minutes ago
|
23
|
+
# so we send a snapshot on first report
|
24
|
+
@last_snapshot = Time.now - 601
|
13
25
|
end
|
14
26
|
|
27
|
+
##
|
28
|
+
# take_snapshot
|
29
|
+
#
|
30
|
+
# Method to collect up process info for snapshots. This
|
31
|
+
# is generally used once per process.
|
32
|
+
#
|
33
|
+
def take_snapshot
|
34
|
+
data = {}
|
35
|
+
|
36
|
+
data[:sensorVersion] = ::Instana::VERSION
|
37
|
+
data[:pid] = Process.pid
|
38
|
+
data[:ruby_version] = RUBY_VERSION
|
39
|
+
|
40
|
+
process = ProcTable.ps(Process.pid)
|
41
|
+
arguments = process.cmdline.split(' ')
|
42
|
+
data[:name] = arguments.shift
|
43
|
+
data[:exec_args] = arguments
|
44
|
+
|
45
|
+
# Since a snapshot is only taken on process boot,
|
46
|
+
# this is ok here.
|
47
|
+
data[:start_time] = Time.now.to_s
|
48
|
+
|
49
|
+
# Framework Detection
|
50
|
+
if defined?(::RailsLts::VERSION)
|
51
|
+
data[:framework] = "Rails on Rails LTS-#{::RailsLts::VERSION}"
|
52
|
+
|
53
|
+
elsif defined?(::Rails.version)
|
54
|
+
data[:framework] = "Ruby on Rails #{::Rails.version}"
|
55
|
+
|
56
|
+
elsif defined?(::Grape::VERSION)
|
57
|
+
data[:framework] = "Grape #{::Grape::VERSION}"
|
58
|
+
|
59
|
+
elsif defined?(::Padrino::VERSION)
|
60
|
+
data[:framework] = "Padrino #{::Padrino::VERSION}"
|
61
|
+
|
62
|
+
elsif defined?(::Sinatra::VERSION)
|
63
|
+
data[:framework] = "Sinatra #{::Sinatra::VERSION}"
|
64
|
+
end
|
65
|
+
|
66
|
+
data
|
67
|
+
rescue => e
|
68
|
+
::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
69
|
+
::Instana.logger.debug e.backtrace.join("\r\n")
|
70
|
+
return data
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# announce_sensor
|
75
|
+
#
|
76
|
+
# Collect process ID, name and arguments to notify
|
77
|
+
# the host agent.
|
78
|
+
#
|
15
79
|
def announce_sensor
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
payload[:name] = $0
|
80
|
+
process = ProcTable.ps(Process.pid)
|
81
|
+
announce_payload = {}
|
82
|
+
announce_payload[:pid] = Process.pid
|
20
83
|
|
84
|
+
arguments = process.cmdline.split(' ')
|
85
|
+
arguments.shift
|
86
|
+
announce_payload[:args] = arguments
|
87
|
+
|
88
|
+
path = 'com.instana.plugin.ruby.discovery'
|
89
|
+
uri = URI.parse("http://#{@host}:#{@port}/#{path}")
|
21
90
|
req = Net::HTTP::Put.new(uri)
|
91
|
+
|
92
|
+
req['Accept'] = 'application/json'
|
93
|
+
req['Content-Type'] = 'application/json'
|
94
|
+
req.body = announce_payload.to_json
|
95
|
+
|
96
|
+
::Instana.logger.debug "Announcing sensor to #{path} for pid #{Process.pid}: #{announce_payload.to_json}"
|
97
|
+
|
98
|
+
response = nil
|
99
|
+
Net::HTTP.start(uri.hostname, uri.port) do |http|
|
100
|
+
response = http.request(req)
|
101
|
+
end
|
102
|
+
Instana.logger.debug response.code
|
103
|
+
rescue => e
|
104
|
+
Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
105
|
+
Instana.logger.debug e.backtrace.join("\r\n")
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# report_entity_data
|
110
|
+
#
|
111
|
+
# Method to report metrics data to the host agent. Every 10 minutes, this
|
112
|
+
# method will also send a process snapshot data.
|
113
|
+
#
|
114
|
+
def report_entity_data(payload)
|
115
|
+
path = "com.instana.plugin.ruby.#{Process.pid}"
|
116
|
+
uri = URI.parse("http://#{@host}:#{@port}/#{path}")
|
117
|
+
req = Net::HTTP::Post.new(uri)
|
118
|
+
|
119
|
+
# Every 5 minutes, send snapshot data as well
|
120
|
+
if (Time.now - @last_snapshot) > 600
|
121
|
+
payload.merge!(@snapshot)
|
122
|
+
@last_snapshot = Time.now
|
123
|
+
end
|
124
|
+
|
22
125
|
req['Accept'] = 'application/json'
|
23
126
|
req['Content-Type'] = 'application/json'
|
24
127
|
req.body = payload.to_json
|
25
128
|
|
129
|
+
#Instana.logger.debug "Posting metrics to #{path}: #{payload.to_json}"
|
130
|
+
|
26
131
|
response = nil
|
27
132
|
Net::HTTP.start(uri.hostname, uri.port) do |http|
|
28
133
|
response = http.request(req)
|
29
134
|
end
|
30
|
-
|
135
|
+
|
136
|
+
# If snapshot data is in the payload and last response
|
137
|
+
# was ok then delete the snapshot data. Otherwise let it
|
138
|
+
# ride for another run.
|
139
|
+
if response.code.to_i == 200
|
140
|
+
@snapshot.each do |k, v|
|
141
|
+
payload.delete(k)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
Instana.logger.debug response.code unless response.code.to_i == 200
|
145
|
+
@last_entity_response = response.code.to_i
|
146
|
+
rescue => e
|
147
|
+
Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
148
|
+
Instana.logger.debug e.backtrace.join("\r\n")
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# host_agent_ready?
|
153
|
+
#
|
154
|
+
# Check that the host agent is available and can be contacted.
|
155
|
+
#
|
156
|
+
def host_agent_ready?
|
157
|
+
uri = URI.parse("http://#{@host}:#{@port}/")
|
158
|
+
req = Net::HTTP::Get.new(uri)
|
159
|
+
|
160
|
+
req['Accept'] = 'application/json'
|
161
|
+
req['Content-Type'] = 'application/json'
|
162
|
+
|
163
|
+
::Instana.logger.debug "Checking agent availability...."
|
164
|
+
|
165
|
+
response = nil
|
166
|
+
Net::HTTP.start(uri.hostname, uri.port) do |http|
|
167
|
+
response = http.request(req)
|
168
|
+
end
|
169
|
+
|
170
|
+
if response.code.to_i != 200
|
171
|
+
Instana.logger.debug "Host agent returned #{response.code}"
|
172
|
+
false
|
173
|
+
else
|
174
|
+
true
|
175
|
+
end
|
176
|
+
rescue Errno::ECONNREFUSED => e
|
177
|
+
Instana.logger.debug "Agent not responding: #{e.inspect}"
|
178
|
+
return false
|
179
|
+
rescue => e
|
180
|
+
Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
181
|
+
Instana.logger.debug e.backtrace.join("\r\n")
|
182
|
+
return false
|
31
183
|
end
|
32
184
|
end
|
33
185
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'timers'
|
2
|
+
require 'instana/collectors/gc'
|
3
|
+
require 'instana/collectors/memory'
|
4
|
+
require 'instana/collectors/thread'
|
5
|
+
|
6
|
+
module Instana
|
7
|
+
module Collector
|
8
|
+
class << self
|
9
|
+
attr_accessor :interval
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if ENV.key?('INSTANA_GEM_DEV')
|
15
|
+
::Instana::Collector.interval = 3
|
16
|
+
else
|
17
|
+
::Instana::Collector.interval = 1
|
18
|
+
end
|
19
|
+
|
20
|
+
::Thread.new do
|
21
|
+
timers = ::Timers::Group.new
|
22
|
+
payload = {}
|
23
|
+
|
24
|
+
timers.every(::Instana::Collector.interval) {
|
25
|
+
|
26
|
+
# Check if we forked (unicorn, puma) and
|
27
|
+
# if so, re-announce the process sensor
|
28
|
+
if ::Instana.pid_change?
|
29
|
+
::Instana.logger.debug "Detected a fork (old: #{::Instana.pid} new: #{::Process.pid}). Re-announcing sensor."
|
30
|
+
::Instana.pid = Process.pid
|
31
|
+
Instana.agent.announce_sensor
|
32
|
+
end
|
33
|
+
|
34
|
+
::Instana.collectors.each do |c|
|
35
|
+
metrics = c.collect
|
36
|
+
if metrics
|
37
|
+
payload[c.payload_key] = metrics
|
38
|
+
else
|
39
|
+
payload.delete(c.payload_key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Report all the collected goodies
|
44
|
+
::Instana.agent.report_entity_data(payload)
|
45
|
+
}
|
46
|
+
loop { timers.wait }
|
47
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Instana
|
2
|
+
module Collector
|
3
|
+
class GC
|
4
|
+
attr_accessor :payload_key
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@payload_key = :gc
|
8
|
+
@last_report = {}
|
9
|
+
@this_gc = {}
|
10
|
+
@last_major_count = 0
|
11
|
+
@last_minor_count = 0
|
12
|
+
::GC::Profiler.enable
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# collect
|
17
|
+
#
|
18
|
+
# To collect garbage collector related metrics.
|
19
|
+
#
|
20
|
+
def collect
|
21
|
+
@this_gc.clear
|
22
|
+
stats = ::GC.stat
|
23
|
+
|
24
|
+
# Time spent in GC. Report in milliseconds
|
25
|
+
@this_gc[:totalTime] = ::GC::Profiler.total_time * 1000
|
26
|
+
::GC::Profiler.clear
|
27
|
+
|
28
|
+
# GC metrics only available on newer Ruby versions
|
29
|
+
if RUBY_VERSION >= '2.1'
|
30
|
+
# GC runs. Calculate how many have occurred since the last call
|
31
|
+
@this_gc[:minorGcs] = stats[:minor_gc_count] - @last_minor_count
|
32
|
+
@this_gc[:majorGcs] = stats[:major_gc_count] - @last_major_count
|
33
|
+
|
34
|
+
# Store these counts so that we have something to compare to next
|
35
|
+
# time around.
|
36
|
+
@last_major_count = stats[:major_gc_count]
|
37
|
+
@last_minor_count = stats[:minor_gc_count]
|
38
|
+
end
|
39
|
+
|
40
|
+
# GC Heap
|
41
|
+
@this_gc[:heap_live] = stats[:heap_live_slot] || stats[:heap_live_slots] || stats[:heap_live_num]
|
42
|
+
@this_gc[:heap_free] = stats[:heap_free_slot] || stats[:heap_free_slots] || stats[:heap_free_num]
|
43
|
+
|
44
|
+
@this_gc = ::Instana::Util.enforce_deltas(@this_gc, @last_report)
|
45
|
+
|
46
|
+
unless @this_gc.empty?
|
47
|
+
@last_report.merge!(@this_gc)
|
48
|
+
@this_gc
|
49
|
+
else
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
rescue => e
|
53
|
+
::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
54
|
+
::Instana.logger.debug e.backtrace.join("\r\n")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Register the metrics collector if enabled
|
61
|
+
if ::Instana.config[:metrics][:gc][:enabled]
|
62
|
+
::Instana.collectors << ::Instana::Collector::GC.new
|
63
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'get_process_mem'
|
2
|
+
|
3
|
+
module Instana
|
4
|
+
module Collector
|
5
|
+
class Memory
|
6
|
+
attr_accessor :payload_key
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@payload_key = :memory
|
10
|
+
@last_report = {}
|
11
|
+
@this_mem = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# collect
|
16
|
+
#
|
17
|
+
# To collect process memory usage.
|
18
|
+
#
|
19
|
+
def collect
|
20
|
+
@this_mem.clear
|
21
|
+
@this_mem[:rss_size] = ::GetProcessMem.new(Process.pid).kb
|
22
|
+
|
23
|
+
@this_mem = ::Instana::Util.enforce_deltas(@this_mem, @last_report)
|
24
|
+
unless @this_mem.empty?
|
25
|
+
@last_report.merge!(@this_mem)
|
26
|
+
@this_mem
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
rescue => e
|
31
|
+
::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
32
|
+
::Instana.logger.debug e.backtrace.join("\r\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Register the metrics collector if enabled
|
39
|
+
if ::Instana.config[:metrics][:memory][:enabled]
|
40
|
+
::Instana.collectors << ::Instana::Collector::Memory.new
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Instana
|
2
|
+
module Collector
|
3
|
+
class Thread
|
4
|
+
attr_accessor :payload_key
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@payload_key = :thread
|
8
|
+
@last_report = {}
|
9
|
+
@this_count = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# collect
|
14
|
+
#
|
15
|
+
# To collect thread count
|
16
|
+
#
|
17
|
+
def collect
|
18
|
+
@this_count[:count] = ::Thread.list.count
|
19
|
+
|
20
|
+
@this_count = ::Instana::Util.enforce_deltas(@this_count, @last_report)
|
21
|
+
|
22
|
+
unless @this_count.empty?
|
23
|
+
@last_report.merge!(@this_count)
|
24
|
+
@this_count
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
|
30
|
+
::Instana.logger.debug e.backtrace.join("\r\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Register the metrics collector if enabled
|
37
|
+
if ::Instana.config[:metrics][:thread][:enabled]
|
38
|
+
::Instana.collectors << ::Instana::Collector::Thread.new
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Instana
|
2
|
+
class Config
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@config = {}
|
6
|
+
@config[:agent_host] = '127.0.0.1'
|
7
|
+
@config[:agent_port] = 42699
|
8
|
+
@config[:metrics] = {}
|
9
|
+
@config[:metrics][:gc] = { :enabled => true }
|
10
|
+
@config[:metrics][:memory] = { :enabled => true }
|
11
|
+
@config[:metrics][:thread] = { :enabled => true }
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@config[key.to_sym]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@config[key.to_sym] = value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
::Instana.config = ::Instana::Config.new
|
data/lib/instana/util.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Instana
|
2
|
+
module Util
|
3
|
+
##
|
4
|
+
# enforce_deltas
|
5
|
+
#
|
6
|
+
# Take two hashes, and make sure candidate does not have
|
7
|
+
# any of the same values as `last`. We only report
|
8
|
+
# when values change.
|
9
|
+
#
|
10
|
+
# Note this is not recursive, so only pass in the single
|
11
|
+
# hashes that you want delta reporting with.
|
12
|
+
#
|
13
|
+
def self.enforce_deltas(candidate, last)
|
14
|
+
return unless last.is_a?(Hash)
|
15
|
+
|
16
|
+
candidate.each do |k,v|
|
17
|
+
if candidate[k] == last[k]
|
18
|
+
candidate.delete(k)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
candidate
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Debugging helper method
|
27
|
+
#
|
28
|
+
def self.pry!
|
29
|
+
# Only valid for development or test environments
|
30
|
+
#env = ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
31
|
+
#return unless %w(development, test).include? env
|
32
|
+
|
33
|
+
if RUBY_VERSION > '1.8.7'
|
34
|
+
require 'pry-byebug'
|
35
|
+
|
36
|
+
if defined?(PryByebug)
|
37
|
+
Pry.commands.alias_command 'c', 'continue'
|
38
|
+
Pry.commands.alias_command 's', 'step'
|
39
|
+
Pry.commands.alias_command 'n', 'next'
|
40
|
+
Pry.commands.alias_command 'f', 'finish'
|
41
|
+
|
42
|
+
Pry::Commands.command(/^$/, 'repeat last command') do
|
43
|
+
_pry_.run_command Pry.history.to_a.last
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
binding.pry
|
48
|
+
else
|
49
|
+
require 'ruby-debug'; debugger
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/instana/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: instana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Giacomo Lombardo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,49 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
-
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sys-proctable
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.1.3
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.1.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: get_process_mem
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.2.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.2.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: timers
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.1.0
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.1.0
|
97
|
+
description: Provides Ruby sensor instrumentation for Instana.
|
56
98
|
email:
|
57
99
|
- pglombardo@gmail.com
|
58
100
|
executables: []
|
@@ -69,6 +111,12 @@ files:
|
|
69
111
|
- instana.gemspec
|
70
112
|
- lib/instana.rb
|
71
113
|
- lib/instana/agent.rb
|
114
|
+
- lib/instana/collectors.rb
|
115
|
+
- lib/instana/collectors/gc.rb
|
116
|
+
- lib/instana/collectors/memory.rb
|
117
|
+
- lib/instana/collectors/thread.rb
|
118
|
+
- lib/instana/config.rb
|
119
|
+
- lib/instana/util.rb
|
72
120
|
- lib/instana/version.rb
|
73
121
|
homepage: https://www.instana.com/
|
74
122
|
licenses: []
|
@@ -81,16 +129,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
129
|
requirements:
|
82
130
|
- - ">="
|
83
131
|
- !ruby/object:Gem::Version
|
84
|
-
version: '0'
|
132
|
+
version: '2.0'
|
85
133
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
134
|
requirements:
|
87
|
-
- - "
|
135
|
+
- - ">"
|
88
136
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
137
|
+
version: 1.3.1
|
90
138
|
requirements: []
|
91
139
|
rubyforge_project:
|
92
140
|
rubygems_version: 2.5.1
|
93
141
|
signing_key:
|
94
142
|
specification_version: 4
|
95
|
-
summary:
|
143
|
+
summary: Ruby sensor for Instana
|
96
144
|
test_files: []
|