nightwing 0.1.0 → 0.2.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.
- 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
|