nightwing 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +17 -3
- data/lib/nightwing.rb +1 -0
- data/lib/nightwing/base.rb +27 -0
- data/lib/nightwing/instrumentation/active_record.rb +37 -0
- data/lib/nightwing/instrumentation/base.rb +17 -0
- data/lib/nightwing/sidekiq/base.rb +3 -21
- data/lib/nightwing/sidekiq/profiler.rb +4 -4
- data/lib/nightwing/version.rb +1 -1
- data/spec/nightwing/instrumentation/active_record_spec.rb +24 -0
- data/spec/nightwing/sidekiq/profiler_spec.rb +2 -2
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1a31b84aa7f3d919e2afa26971a8ed1936efa9c
|
4
|
+
data.tar.gz: d4bd99cef7cb8449ed7e05d5f189053c21fdd695
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2babddd5a3b8c38132211c41fe33c5ceef7d850e4a8a83c32a7267fac271944d1badc830f62e4c676795685b748522b7f724c86c0e710adbf21ed130dfe1d046
|
7
|
+
data.tar.gz: e42a3b39948aaee75c2a9b5450dc421ffda4c5ef74065ea3250a05ef1b85aca3b7c3fdbf73875942ff3abde2ed4806208af74f4290f1a75d6f0db47088dce024
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
- Renamed memory_used metric so that we can utilize the memory namespace for additional metrics
|
4
|
+
|
5
|
+
**Renamed Metrics**
|
6
|
+
|
7
|
+
- `sidekiq.<queue>.<worker>.memory_used` to `sidekiq.<queue>.<worker>.memory.delta`
|
8
|
+
|
9
|
+
**New Metrics**
|
10
|
+
|
11
|
+
- `instrumentation.sql.<table>.<action>.time`
|
12
|
+
|
1
13
|
## 0.1.0
|
2
14
|
|
3
15
|
- Add new Profiler middleware
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,6 +28,14 @@ Sidekiq.configure_server do |config|
|
|
28
28
|
end
|
29
29
|
```
|
30
30
|
|
31
|
+
```ruby
|
32
|
+
# config/initializers/instrumentation.rb
|
33
|
+
ActiveSupport::Notifications.subscribe(
|
34
|
+
'sql.active_record',
|
35
|
+
Nightwing::Instrumentation::ActiveRecord.new(client: Librato),
|
36
|
+
)
|
37
|
+
```
|
38
|
+
|
31
39
|
### Available options
|
32
40
|
|
33
41
|
| Name | Description | Required? | Default |
|
@@ -39,7 +47,13 @@ end
|
|
39
47
|
|
40
48
|
When debug mode is turned on, Nightwing will output the metrics into a parsable format. The output destination is determined by the logger. If no logger is given then we send the debugging output to STDOUT.
|
41
49
|
|
42
|
-
## Metrics
|
50
|
+
## Instrumentation Metrics
|
51
|
+
|
52
|
+
Below are the metrics reported to Librato from instrumentation classes
|
53
|
+
|
54
|
+
- `instrumentation.sql.<table>.<action>.time`: how long the database query took to complete
|
55
|
+
|
56
|
+
## Sidekiq Metrics
|
43
57
|
|
44
58
|
Below are the metrics reported to Librato from the Sidekiq middleware
|
45
59
|
|
@@ -56,7 +70,7 @@ Below are the metrics reported to Librato from the Sidekiq middleware
|
|
56
70
|
- `sidekiq.<queue>.failed`: number of jobs in given queue that raised an error
|
57
71
|
- `sidekiq.<queue>.time`: how long jobs took to process (in milliseconds)
|
58
72
|
- `sidekiq.<queue>.gc.count`: number of times the Ruby GC kicked off
|
59
|
-
- `sidekiq.<queue>.
|
73
|
+
- `sidekiq.<queue>.memory.delta`: the different in the process memory after jobs were processed (in bytes)
|
60
74
|
|
61
75
|
¹: the difference between now and when the oldest job was enqueued (given in seconds)
|
62
76
|
|
@@ -68,4 +82,4 @@ Below are the metrics reported to Librato from the Sidekiq middleware
|
|
68
82
|
- `sidekiq.<queue>.<worker>.time`: how long given worker took to process (in milliseconds)
|
69
83
|
- `sidekiq.<queue>.<worker>.retried`: number of times a given worker retried
|
70
84
|
- `sidekiq.<queue>.<worker>.gc.count`: number of times the Ruby GC kicked off
|
71
|
-
- `sidekiq.<queue>.<worker>.
|
85
|
+
- `sidekiq.<queue>.<worker>.memory.delta`: the different in the process memory after jobs were processed (in bytes)
|
data/lib/nightwing.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "nightwing/metric"
|
2
|
+
require "nightwing/debug_client"
|
3
|
+
require "nightwing/logger"
|
4
|
+
require "nightwing/client_logger"
|
5
|
+
|
6
|
+
module Nightwing
|
7
|
+
class Base
|
8
|
+
attr_reader :namespace, :logger
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@namespace = options.fetch(:namespace)
|
12
|
+
@client = options.fetch(:client, Nightwing::DebugClient.new)
|
13
|
+
@logger = options.fetch(:logger, Nightwing::Logger.new)
|
14
|
+
@debug = options.fetch(:debug, false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def client
|
18
|
+
@client_proxy ||= begin
|
19
|
+
if @debug
|
20
|
+
Nightwing::ClientLogger.new(client: @client, logger: @logger)
|
21
|
+
else
|
22
|
+
@client
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "nightwing/instrumentation/base"
|
2
|
+
|
3
|
+
module Nightwing
|
4
|
+
module Instrumentation
|
5
|
+
# This code was influenced by Matt Aimonetti's awesome blog post: "Practical Guide to StatsD/Graphite Monitoring"
|
6
|
+
# Check it out: https://matt.aimonetti.net/posts/2013/06/26/practical-guide-to-graphite-monitoring
|
7
|
+
class ActiveRecord < Base
|
8
|
+
SQL_INSERT_DELETE_PARSER_REGEXP = /^(\w+)\s(\w+)\s\W*(\w+)/
|
9
|
+
SQL_SELECT_REGEXP = /select .*? FROM \W*(\w+)/i
|
10
|
+
SQL_UPDATE_REGEXP = /update \W*(\w+)/i
|
11
|
+
|
12
|
+
def call(_name, started, finished, _unique_id, payload)
|
13
|
+
if payload[:name] == "SQL" || payload[:name] =~ /.* Load$/ || payload[:name].nil?
|
14
|
+
table, action = query_info(payload[:sql])
|
15
|
+
end
|
16
|
+
|
17
|
+
if table
|
18
|
+
query_time = (finished - started) * 1_000
|
19
|
+
client.timing("#{namespace}.sql.#{table.downcase}.#{action.downcase}.time", query_time.round)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def query_info(query)
|
26
|
+
case query
|
27
|
+
when SQL_INSERT_DELETE_PARSER_REGEXP
|
28
|
+
[$3, $1]
|
29
|
+
when SQL_UPDATE_REGEXP
|
30
|
+
[$1, "update"]
|
31
|
+
when SQL_SELECT_REGEXP
|
32
|
+
[$1, "select"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "nightwing/base"
|
2
|
+
|
3
|
+
module Nightwing
|
4
|
+
module Instrumentation
|
5
|
+
class Base < Nightwing::Base
|
6
|
+
def initialize(options = {})
|
7
|
+
super default_options.merge(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_options
|
13
|
+
{ namespace: "instrumentation" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,29 +1,11 @@
|
|
1
1
|
require "sidekiq/api"
|
2
|
-
require "nightwing/
|
3
|
-
require "nightwing/debug_client"
|
4
|
-
require "nightwing/logger"
|
5
|
-
require "nightwing/client_logger"
|
2
|
+
require "nightwing/base"
|
6
3
|
|
7
4
|
module Nightwing
|
8
5
|
module Sidekiq
|
9
|
-
class Base
|
10
|
-
attr_reader :namespace, :logger
|
11
|
-
|
6
|
+
class Base < Nightwing::Base
|
12
7
|
def initialize(options = {})
|
13
|
-
|
14
|
-
@client = options.fetch(:client, Nightwing::DebugClient.new)
|
15
|
-
@logger = options.fetch(:logger, Nightwing::Logger.new)
|
16
|
-
@debug = options.fetch(:debug, false)
|
17
|
-
end
|
18
|
-
|
19
|
-
def client
|
20
|
-
@client_proxy ||= begin
|
21
|
-
if @debug
|
22
|
-
Nightwing::ClientLogger.new(client: @client, logger: @logger)
|
23
|
-
else
|
24
|
-
@client
|
25
|
-
end
|
26
|
-
end
|
8
|
+
super options.merge(namespace: "sidekiq")
|
27
9
|
end
|
28
10
|
|
29
11
|
private
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "nightwing/sidekiq/profiler"
|
2
1
|
require "oink"
|
3
2
|
|
4
3
|
module Nightwing
|
@@ -15,16 +14,17 @@ module Nightwing
|
|
15
14
|
|
16
15
|
yield
|
17
16
|
ensure
|
18
|
-
|
17
|
+
finish_snapshot = memory_snapshot
|
18
|
+
memory_delta_in_bytes = finish_snapshot - initial_snapshot
|
19
19
|
total_time = ((Time.now - started_at) * 1_000).round
|
20
20
|
total_gc_count = ::GC.count - initial_gc_count
|
21
21
|
|
22
22
|
client.timing "#{worker_namespace}.time", total_time
|
23
|
-
client.measure "#{worker_namespace}.
|
23
|
+
client.measure "#{worker_namespace}.memory.delta", memory_delta_in_bytes
|
24
24
|
client.measure "#{worker_namespace}.gc.count", total_gc_count
|
25
25
|
|
26
26
|
client.timing "#{queue_namespace}.time", total_time
|
27
|
-
client.measure "#{queue_namespace}.
|
27
|
+
client.measure "#{queue_namespace}.memory.delta", memory_delta_in_bytes
|
28
28
|
client.measure "#{queue_namespace}.gc.count", total_gc_count
|
29
29
|
end
|
30
30
|
end
|
data/lib/nightwing/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "active_support/all"
|
3
|
+
|
4
|
+
describe Nightwing::Instrumentation::ActiveRecord do
|
5
|
+
subject { described_class.new(namespace: "instr") }
|
6
|
+
|
7
|
+
describe "#call" do
|
8
|
+
context "when given select SQL query" do
|
9
|
+
it "measures time" do
|
10
|
+
expect(subject.client).to receive(:timing).with("instr.sql.users.select.time", 2_000)
|
11
|
+
payload = { name: "SQL", sql: "select * from users;" }
|
12
|
+
subject.call(nil, 5.seconds.ago, 3.seconds.ago, nil, payload)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when given insert SQL query" do
|
17
|
+
it "measures time" do
|
18
|
+
expect(subject.client).to receive(:timing).with("instr.sql.foo.insert.time", 1_000)
|
19
|
+
payload = { name: "SQL", sql: "insert into foo values(1, 2, 3);" }
|
20
|
+
subject.call(nil, 10.seconds.ago, 9.seconds.ago, nil, payload)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -24,9 +24,9 @@ describe Nightwing::Sidekiq::Profiler do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "records memory" do
|
27
|
-
expect(subject.client).to receive(:measure).with("sidekiq.default.my_worker.
|
27
|
+
expect(subject.client).to receive(:measure).with("sidekiq.default.my_worker.memory.delta", 0).and_call_original
|
28
28
|
expect(subject.client).to receive(:measure).with("sidekiq.default.my_worker.gc.count", 0).and_call_original
|
29
|
-
expect(subject.client).to receive(:measure).with("sidekiq.default.
|
29
|
+
expect(subject.client).to receive(:measure).with("sidekiq.default.memory.delta", 0).and_call_original
|
30
30
|
expect(subject.client).to receive(:measure).with("sidekiq.default.gc.count", 0).and_call_original
|
31
31
|
|
32
32
|
subject.call(MyWorker.new, nil, "default") do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nightwing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Ledet
|
@@ -123,8 +123,11 @@ files:
|
|
123
123
|
- README.md
|
124
124
|
- circle.yml
|
125
125
|
- lib/nightwing.rb
|
126
|
+
- lib/nightwing/base.rb
|
126
127
|
- lib/nightwing/client_logger.rb
|
127
128
|
- lib/nightwing/debug_client.rb
|
129
|
+
- lib/nightwing/instrumentation/active_record.rb
|
130
|
+
- lib/nightwing/instrumentation/base.rb
|
128
131
|
- lib/nightwing/logger.rb
|
129
132
|
- lib/nightwing/metric.rb
|
130
133
|
- lib/nightwing/sidekiq/base.rb
|
@@ -134,6 +137,7 @@ files:
|
|
134
137
|
- lib/nightwing/sidekiq/worker_stats.rb
|
135
138
|
- lib/nightwing/version.rb
|
136
139
|
- nightwing.gemspec
|
140
|
+
- spec/nightwing/instrumentation/active_record_spec.rb
|
137
141
|
- spec/nightwing/metric_spec.rb
|
138
142
|
- spec/nightwing/sidekiq/profiler_spec.rb
|
139
143
|
- spec/nightwing/sidekiq/queue_stats_spec.rb
|