nightwing 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d1a31b84aa7f3d919e2afa26971a8ed1936efa9c
4
- data.tar.gz: d4bd99cef7cb8449ed7e05d5f189053c21fdd695
3
+ metadata.gz: 1830dcc5ef65dd81a3991d08edb121cdd5e7dc35
4
+ data.tar.gz: 8fd3c1a4a52736adb30b92bec706960e068e8453
5
5
  SHA512:
6
- metadata.gz: 2babddd5a3b8c38132211c41fe33c5ceef7d850e4a8a83c32a7267fac271944d1badc830f62e4c676795685b748522b7f724c86c0e710adbf21ed130dfe1d046
7
- data.tar.gz: e42a3b39948aaee75c2a9b5450dc421ffda4c5ef74065ea3250a05ef1b85aca3b7c3fdbf73875942ff3abde2ed4806208af74f4290f1a75d6f0db47088dce024
6
+ metadata.gz: cafce097fd7a8470aa4b5316767d0dce065859c0f7de51a80b003696ce68db9773e11c9b30152092fd160dbcc8e81b4a8f90efc31071b88d40f6a1e28b1e2dc7
7
+ data.tar.gz: 0fe35c47611d301c4dfbffe431041ec9a6eea96c60af51d076ce6c3093f0ed1ff8f454f548e0b433795cfa8e61c41355c13257f37cd5969f174f346323948b4d
data/.rubocop.yml CHANGED
@@ -10,10 +10,14 @@ Metrics/LineLength:
10
10
  Max: 120
11
11
  StringLiterals:
12
12
  EnforcedStyle: double_quotes
13
+ Style/Alias:
14
+ Enabled: false
13
15
  Style/FrozenStringLiteralComment:
14
16
  Enabled: false
15
17
  Style/IfUnlessModifier:
16
18
  Enabled: false
19
+ Style/ModuleFunction:
20
+ Enabled: false
17
21
  Style/PerlBackrefs:
18
22
  Enabled: false
19
23
  Style/SignalException:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ ## Unreleased
2
+
3
+ ## 0.3.0
4
+
5
+ - New profiling extension for Redis
6
+ - New profiling extension for Memcache (via Dalli)
7
+ - Added new `Nightwing.client` to global statds client configuration
8
+ - Internal setup refactor
9
+ - Metric changes are listed below
10
+
11
+ **Renamed Metrics**
12
+
13
+ - `instrumentation.sql.<table>.<action>.time` to `sql.<table>.<action>.time`
14
+
15
+ **New Metrics**
16
+
17
+ - `memcache.command.time`
18
+ - `memcache.command.<command>.time`
19
+ - `memcache.command.processed`
20
+ - `memcache.command.<command>.processed`
21
+ - `redis.command.time`
22
+ - `redis.command.<command>.time`
23
+ - `redis.command.processed`
24
+ - `redis.command.<command>.processed`
25
+
1
26
  ## 0.2.0
2
27
 
3
28
  - Renamed memory_used metric so that we can utilize the memory namespace for additional metrics
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nightwing (0.2.0)
4
+ nightwing (0.3.0)
5
5
  activesupport (>= 4.1.0)
6
6
  oink (= 0.10.1)
7
7
  sidekiq (>= 2.6)
@@ -9,14 +9,14 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activemodel (4.2.5)
13
- activesupport (= 4.2.5)
12
+ activemodel (4.2.5.1)
13
+ activesupport (= 4.2.5.1)
14
14
  builder (~> 3.1)
15
- activerecord (4.2.5)
16
- activemodel (= 4.2.5)
17
- activesupport (= 4.2.5)
15
+ activerecord (4.2.5.1)
16
+ activemodel (= 4.2.5.1)
17
+ activesupport (= 4.2.5.1)
18
18
  arel (~> 6.0)
19
- activesupport (4.2.5)
19
+ activesupport (4.2.5.1)
20
20
  i18n (~> 0.7)
21
21
  json (~> 1.7, >= 1.7.7)
22
22
  minitest (~> 5.1)
File without changes
data/README.md CHANGED
@@ -28,14 +28,26 @@ Sidekiq.configure_server do |config|
28
28
  end
29
29
  ```
30
30
 
31
+ To gather database metrics:
32
+
31
33
  ```ruby
32
34
  # config/initializers/instrumentation.rb
33
- ActiveSupport::Notifications.subscribe(
34
- 'sql.active_record',
35
- Nightwing::Instrumentation::ActiveRecord.new(client: Librato),
36
- )
35
+ Nightwing.client = Librato
36
+
37
+ ActiveSupport::Notifications.subscribe('sql.active_record', Nightwing::Instrumentation::ActiveRecord.new)
37
38
  ```
38
39
 
40
+ To gather Redis and memcache metrics:
41
+
42
+ ```ruby
43
+ # config/initializers/instrumentation.rb
44
+ Nightwing.client = Librato
45
+
46
+ require 'nightwing/extensions/dalli' # dalli gem required
47
+ require 'nightwing/extensions/redis' # redis gem required
48
+ ```
49
+
50
+
39
51
  ### Available options
40
52
 
41
53
  | Name | Description | Required? | Default |
@@ -51,7 +63,20 @@ When debug mode is turned on, Nightwing will output the metrics into a parsable
51
63
 
52
64
  Below are the metrics reported to Librato from instrumentation classes
53
65
 
54
- - `instrumentation.sql.<table>.<action>.time`: how long the database query took to complete
66
+ - `sql.<table>.<action>.time`: how long the database query took to complete
67
+
68
+ ## Extensions Metrics
69
+
70
+ Below are the metrics reported to Librato from instrumentation classes
71
+
72
+ - `redis.command.processed`: number of times overall command was called
73
+ - `redis.command.time`: response time (in ms) for all commands
74
+ - `redis.command.<command>.processed`: number of times the command was called
75
+ - `redis.command.<command>.time`: response time (in ms) for command
76
+ - `memcache.command.processed`: number of times overall command was called
77
+ - `memcache.command.time`: response time (in ms) for all commands
78
+ - `memcache.command.<command>.processed`: number of times the command was called
79
+ - `memcache.command.<command>.time`: response time (in ms) for command
55
80
 
56
81
  ## Sidekiq Metrics
57
82
 
data/circle.yml CHANGED
@@ -1,5 +1,14 @@
1
+ dependencies:
2
+ override:
3
+ - 'rvm-exec 2.1.7 bundle install'
4
+ - 'rvm-exec 2.2.3 bundle install'
5
+ - 'rvm-exec 2.3.0 bundle install'
6
+
1
7
  test:
2
- pre:
3
- - bundle exec rubocop
4
8
  override:
5
- - bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml
9
+ - 'rvm-exec 2.1.7 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
10
+ - 'rvm-exec 2.1.7 bundle exec rubocop'
11
+ - 'rvm-exec 2.2.3 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
12
+ - 'rvm-exec 2.2.3 bundle exec rubocop'
13
+ - 'rvm-exec 2.3.0 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
14
+ - 'rvm-exec 2.3.0 bundle exec rubocop'
data/lib/nightwing.rb CHANGED
@@ -1,6 +1,26 @@
1
1
  require "nightwing/version"
2
+ require "nightwing/debug_client"
2
3
  require "nightwing/instrumentation/active_record"
4
+ require "nightwing/sidekiq/base"
3
5
  require "nightwing/sidekiq/stats"
4
6
  require "nightwing/sidekiq/queue_stats"
5
7
  require "nightwing/sidekiq/worker_stats"
6
8
  require "nightwing/sidekiq/profiler"
9
+
10
+ module Nightwing
11
+ extend self
12
+
13
+ def client
14
+ @client || internal_client
15
+ end
16
+
17
+ def client=(c)
18
+ @client = c
19
+ end
20
+
21
+ private
22
+
23
+ def internal_client
24
+ @internal_client ||= Nightwing::DebugClient.new
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ Dalli::Client.class_eval do
2
+ def perform_with_profiling(*args)
3
+ begin
4
+ start_time = Time.now
5
+ result = perform_without_profiling(*args)
6
+ ensure
7
+ time_ellasped = (Time.now - start_time) * 1_000
8
+ command = args.first.is_a?(Array) ? args[0][0] : args.first
9
+
10
+ Nightwing.client.timing "memcache.command.time", time_ellasped
11
+ Nightwing.client.timing "memcache.command.#{command}.time", time_ellasped
12
+
13
+ Nightwing.client.increment "memcache.command.processed"
14
+ Nightwing.client.increment "memcache.command.#{command}.processed"
15
+ end
16
+
17
+ result
18
+ end
19
+ alias perform_without_profiling perform
20
+ alias perform perform_with_profiling
21
+ end if defined?(Dalli::Client)
@@ -0,0 +1,21 @@
1
+ Redis::Client.class_eval do
2
+ def call_with_profiling(*args, &blk)
3
+ begin
4
+ start_time = Time.now
5
+ result = call_without_profiling(*args, &blk)
6
+ ensure
7
+ time_ellasped = (Time.now - start_time) * 1_000
8
+ command = args.first.is_a?(Array) ? args[0][0] : args.first
9
+
10
+ Nightwing.client.timing "redis.command.time", time_ellasped
11
+ Nightwing.client.timing "redis.command.#{command}.time", time_ellasped
12
+
13
+ Nightwing.client.increment "redis.command.processed"
14
+ Nightwing.client.increment "redis.command.#{command}.processed"
15
+ end
16
+
17
+ result
18
+ end
19
+ alias call_without_profiling call
20
+ alias call call_with_profiling
21
+ end if defined?(Redis::Client)
@@ -1,10 +1,8 @@
1
- require "nightwing/instrumentation/base"
2
-
3
1
  module Nightwing
4
2
  module Instrumentation
5
3
  # This code was influenced by Matt Aimonetti's awesome blog post: "Practical Guide to StatsD/Graphite Monitoring"
6
4
  # Check it out: https://matt.aimonetti.net/posts/2013/06/26/practical-guide-to-graphite-monitoring
7
- class ActiveRecord < Base
5
+ class ActiveRecord
8
6
  SQL_INSERT_DELETE_PARSER_REGEXP = /^(\w+)\s(\w+)\s\W*(\w+)/
9
7
  SQL_SELECT_REGEXP = /select .*? FROM \W*(\w+)/i
10
8
  SQL_UPDATE_REGEXP = /update \W*(\w+)/i
@@ -15,8 +13,15 @@ module Nightwing
15
13
  end
16
14
 
17
15
  if table
16
+ action.downcase!
17
+ table.downcase!
18
18
  query_time = (finished - started) * 1_000
19
- client.timing("#{namespace}.sql.#{table.downcase}.#{action.downcase}.time", query_time.round)
19
+
20
+ Nightwing.client.timing "sql.#{action}.time", query_time.round
21
+ Nightwing.client.timing "sql.#{action}.#{table}.time", query_time.round
22
+
23
+ Nightwing.client.increment "sql.#{action}.processed"
24
+ Nightwing.client.increment "sql.#{action}.#{table}.processed"
20
25
  end
21
26
  end
22
27
 
@@ -1,11 +1,28 @@
1
1
  require "sidekiq/api"
2
- require "nightwing/base"
2
+ require "nightwing/metric"
3
+ require "nightwing/logger"
4
+ require "nightwing/client_logger"
3
5
 
4
6
  module Nightwing
5
7
  module Sidekiq
6
- class Base < Nightwing::Base
8
+ class Base
9
+ attr_reader :namespace, :logger
10
+
7
11
  def initialize(options = {})
8
- super options.merge(namespace: "sidekiq")
12
+ @namespace = options.fetch(:namespace, "sidekiq")
13
+ @client = options.fetch(:client, Nightwing.client)
14
+ @logger = options.fetch(:logger, Nightwing::Logger.new)
15
+ @debug = options.fetch(:debug, false)
16
+ end
17
+
18
+ def client
19
+ @client_proxy ||= begin
20
+ if @debug
21
+ Nightwing::ClientLogger.new(client: @client, logger: @logger)
22
+ else
23
+ @client
24
+ end
25
+ end
9
26
  end
10
27
 
11
28
  private
@@ -1,3 +1,3 @@
1
1
  module Nightwing
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ class Dalli
4
+ class Client
5
+ def perform(*_)
6
+ @performed = true
7
+ end
8
+
9
+ def called?
10
+ @performed
11
+ end
12
+ end
13
+ end
14
+
15
+ describe "Dalli extensions" do
16
+ subject { Dalli::Client.new }
17
+
18
+ before do
19
+ require "nightwing/extensions/dalli"
20
+ end
21
+
22
+ describe "#peform" do
23
+ it "measures time" do
24
+ expect(Nightwing.client).to receive(:timing) do |*args|
25
+ expect(args.first).to eq("memcache.command.time")
26
+ expect(args.last > 0).to be(true)
27
+ end
28
+
29
+ expect(Nightwing.client).to receive(:timing) do |*args|
30
+ expect(args.first).to eq("memcache.command.foo.time")
31
+ expect(args.last > 0).to be(true)
32
+ end
33
+
34
+ expect(Nightwing.client).to receive(:increment).with("memcache.command.processed")
35
+ expect(Nightwing.client).to receive(:increment).with("memcache.command.foo.processed")
36
+
37
+ subject.perform :foo
38
+ end
39
+
40
+ it "actually calls perform" do
41
+ subject.perform :foo
42
+ expect(subject).to be_called
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ class Redis
4
+ class Client
5
+ def call(*_)
6
+ @performed = true
7
+ end
8
+
9
+ def called?
10
+ @performed
11
+ end
12
+ end
13
+ end
14
+
15
+ describe "Redis extensions" do
16
+ subject { Redis::Client.new }
17
+
18
+ before do
19
+ require "nightwing/extensions/redis"
20
+ end
21
+
22
+ describe "#peform" do
23
+ it "measures time" do
24
+ expect(Nightwing.client).to receive(:timing) do |*args|
25
+ expect(args.first).to eq("redis.command.time")
26
+ expect(args.last > 0).to be(true)
27
+ end
28
+
29
+ expect(Nightwing.client).to receive(:timing) do |*args|
30
+ expect(args.first).to eq("redis.command.foo.time")
31
+ expect(args.last > 0).to be(true)
32
+ end
33
+
34
+ expect(Nightwing.client).to receive(:increment).with("redis.command.processed")
35
+ expect(Nightwing.client).to receive(:increment).with("redis.command.foo.processed")
36
+
37
+ subject.call :foo
38
+ end
39
+
40
+ it "actually calls perform" do
41
+ subject.call :foo
42
+ expect(subject).to be_called
43
+ end
44
+ end
45
+ end
@@ -2,12 +2,16 @@ require "spec_helper"
2
2
  require "active_support/all"
3
3
 
4
4
  describe Nightwing::Instrumentation::ActiveRecord do
5
- subject { described_class.new(namespace: "instr") }
5
+ subject { described_class.new }
6
6
 
7
7
  describe "#call" do
8
8
  context "when given select SQL query" do
9
9
  it "measures time" do
10
- expect(subject.client).to receive(:timing).with("instr.sql.users.select.time", 2_000)
10
+ expect(Nightwing.client).to receive(:timing).with("sql.select.time", 2_000)
11
+ expect(Nightwing.client).to receive(:timing).with("sql.select.users.time", 2_000)
12
+ expect(Nightwing.client).to receive(:increment).with("sql.select.processed")
13
+ expect(Nightwing.client).to receive(:increment).with("sql.select.users.processed")
14
+
11
15
  payload = { name: "SQL", sql: "select * from users;" }
12
16
  subject.call(nil, 5.seconds.ago, 3.seconds.ago, nil, payload)
13
17
  end
@@ -15,7 +19,11 @@ describe Nightwing::Instrumentation::ActiveRecord do
15
19
 
16
20
  context "when given insert SQL query" do
17
21
  it "measures time" do
18
- expect(subject.client).to receive(:timing).with("instr.sql.foo.insert.time", 1_000)
22
+ expect(Nightwing.client).to receive(:timing).with("sql.insert.time", 1_000)
23
+ expect(Nightwing.client).to receive(:timing).with("sql.insert.foo.time", 1_000)
24
+ expect(Nightwing.client).to receive(:increment).with("sql.insert.processed")
25
+ expect(Nightwing.client).to receive(:increment).with("sql.insert.foo.processed")
26
+
19
27
  payload = { name: "SQL", sql: "insert into foo values(1, 2, 3);" }
20
28
  subject.call(nil, 10.seconds.ago, 9.seconds.ago, nil, payload)
21
29
  end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe Nightwing do
4
+ describe "#client" do
5
+ context "when client is not set" do
6
+ class MyClient; end
7
+
8
+ before do
9
+ Nightwing.client = MyClient.new
10
+ end
11
+
12
+ it "returns client" do
13
+ expect(Nightwing.client.class).to eq(MyClient)
14
+ end
15
+ end
16
+
17
+ context "when client is not set" do
18
+ before do
19
+ Nightwing.client = nil
20
+ end
21
+
22
+ it "returns default client" do
23
+ expect(Nightwing.client.class).to eq(Nightwing::DebugClient)
24
+ end
25
+ end
26
+ end
27
+ end
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Ledet
@@ -119,15 +119,15 @@ files:
119
119
  - CHANGELOG.md
120
120
  - Gemfile
121
121
  - Gemfile.lock
122
- - LICENSE.txt
122
+ - LICENSE
123
123
  - README.md
124
124
  - circle.yml
125
125
  - lib/nightwing.rb
126
- - lib/nightwing/base.rb
127
126
  - lib/nightwing/client_logger.rb
128
127
  - lib/nightwing/debug_client.rb
128
+ - lib/nightwing/extensions/dalli.rb
129
+ - lib/nightwing/extensions/redis.rb
129
130
  - lib/nightwing/instrumentation/active_record.rb
130
- - lib/nightwing/instrumentation/base.rb
131
131
  - lib/nightwing/logger.rb
132
132
  - lib/nightwing/metric.rb
133
133
  - lib/nightwing/sidekiq/base.rb
@@ -137,12 +137,15 @@ files:
137
137
  - lib/nightwing/sidekiq/worker_stats.rb
138
138
  - lib/nightwing/version.rb
139
139
  - nightwing.gemspec
140
+ - spec/nightwing/extensions/dalli_spec.rb
141
+ - spec/nightwing/extensions/redis_spec.rb
140
142
  - spec/nightwing/instrumentation/active_record_spec.rb
141
143
  - spec/nightwing/metric_spec.rb
142
144
  - spec/nightwing/sidekiq/profiler_spec.rb
143
145
  - spec/nightwing/sidekiq/queue_stats_spec.rb
144
146
  - spec/nightwing/sidekiq/stats_spec.rb
145
147
  - spec/nightwing/sidekiq/worker_stats_spec.rb
148
+ - spec/nightwing_spec.rb
146
149
  - spec/spec_helper.rb
147
150
  homepage: https://github.com/teespring/nightwing
148
151
  licenses:
@@ -1,27 +0,0 @@
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
@@ -1,17 +0,0 @@
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