gremlin 0.0.1 → 0.0.2

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: f7287de278b662763ddc2ca3cca5d38c41bdd190
4
- data.tar.gz: 823ee29d0d1dac97672d32d3649c502699271f0a
3
+ metadata.gz: 9f3277bdf017d08b45ad5deb0313a9aa4fe713dd
4
+ data.tar.gz: 359c2c16c2438cd7366911abf975c3b802776b87
5
5
  SHA512:
6
- metadata.gz: d40b078ddda9c56352cb260a493002bc9e13fa695cb781b5065fedd08c99a0c78205c8161c02953ce0004eaaf1f72473d3971744bc2d33faf5108623dee2b741
7
- data.tar.gz: 6ba936ae95928ad71d409f3213921ced78bca12e71f189b38c8da808fe158bbd9e33930a7b67d2c1a3857afbb9f845a9d83b95b4343498502e5088ab7238a6dd
6
+ metadata.gz: ecc158ed3ff1540d04d163e4ffc5dd2d5d1a02b5cb396133e221d3d41ef521e918612c55a7db11bce2095a72b2d001e6cf820ab03898ab6d5cd1539e9b31e3e4
7
+ data.tar.gz: a3477c8661b90c1a227f5870dcccddc0f75b4a171ea372fe766fa552abd1324536621f1d4dd4dcadacce6afe0839d32cf702e1f11fc9de764d7d9f77da14a5b7
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  *.sw*
2
2
  spec/examples.txt
3
+ *.gem
4
+ *.rdb
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gremlin (0.0.1)
4
+ gremlin (0.0.2)
5
5
  quantile
6
6
  rails
7
7
  redis (~> 3.2)
@@ -54,7 +54,7 @@ GEM
54
54
  erubis (2.7.0)
55
55
  globalid (0.3.7)
56
56
  activesupport (>= 4.1.0)
57
- i18n (0.7.0)
57
+ i18n (0.8.1)
58
58
  loofah (2.0.3)
59
59
  nokogiri (>= 1.5.9)
60
60
  mail (2.6.4)
@@ -97,7 +97,7 @@ GEM
97
97
  thor (>= 0.18.1, < 2.0)
98
98
  rake (10.5.0)
99
99
  rdoc (5.0.0)
100
- redis (3.3.2)
100
+ redis (3.3.3)
101
101
  redis-native_hash (0.2.1)
102
102
  redis (>= 2.0.0)
103
103
  rspec (3.5.0)
@@ -121,10 +121,10 @@ GEM
121
121
  activesupport (>= 4.0)
122
122
  sprockets (>= 3.0.0)
123
123
  thor (0.19.4)
124
- thread_safe (0.3.5)
124
+ thread_safe (0.3.6)
125
125
  tzinfo (1.2.2)
126
126
  thread_safe (~> 0.1)
127
- websocket-driver (0.6.4)
127
+ websocket-driver (0.6.5)
128
128
  websocket-extensions (>= 0.1.0)
129
129
  websocket-extensions (0.1.2)
130
130
 
@@ -139,4 +139,4 @@ DEPENDENCIES
139
139
  rspec (~> 3.3, >= 3.3.0)
140
140
 
141
141
  BUNDLED WITH
142
- 1.11.2
142
+ 1.12.4
@@ -0,0 +1,143 @@
1
+ require 'benchmark'
2
+ require 'gremlin'
3
+
4
+
5
+ include Benchmark
6
+
7
+ print "Starting benchmarks..."
8
+
9
+ orig_std_out = STDOUT.clone
10
+ STDOUT.reopen(File::open('/dev/null', 'w'))
11
+
12
+ counter_init_benchmarks = (1..100).map do |n|
13
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
14
+ counter_name = "test_#{SecureRandom.hex(5)}_counter".to_sym
15
+ x.report("Counter initialize") { Gremlin::Instruments::Counter.new counter_name, "placeholder", {} }
16
+ end
17
+ end
18
+
19
+ counter_init_and_fetch_benchmarks = (1..100).map do |n|
20
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
21
+ counter_name = "test_#{SecureRandom.hex(5)}_counter".to_sym
22
+ x.report("Counter initialize then fetch") do
23
+ Gremlin::Instruments::Counter.new counter_name, "placeholder", {}
24
+ Gremlin.registry.get counter_name
25
+ end
26
+ end
27
+ end
28
+
29
+ counter_init_and_incr_benchmarks = (1..100).map do |n|
30
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
31
+ counter_name = "test_#{SecureRandom.hex(5)}_counter".to_sym
32
+ x.report("Counter increment") do
33
+ counter = Gremlin::Instruments::Counter.new counter_name, "placeholder", {}
34
+ counter.increment
35
+ end
36
+ end
37
+ end
38
+
39
+ gauge_init_benchmarks = (1..100).map do |n|
40
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
41
+ gauge_name = "test_#{SecureRandom.hex(5)}_gauge".to_sym
42
+ gauge_set_val = rand(1..25000000)
43
+ x.report("Gauge initialize") { Gremlin::Instruments::Gauge.new gauge_name, "placeholder", {} }
44
+ end
45
+ end
46
+
47
+ gauge_init_and_fetch_benchmarks = (1..100).map do |n|
48
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
49
+ gauge_name = "test_#{SecureRandom.hex(5)}_gauge".to_sym
50
+ gauge_set_val = rand(1..25000000)
51
+ x.report("Gauge fetch") do
52
+ Gremlin::Instruments::Gauge.new gauge_name, "placeholder", {}
53
+ Gremlin.registry.get gauge_name
54
+ end
55
+ end
56
+ end
57
+
58
+ gauge_init_and_set_benchmarks = (1..100).map do |n|
59
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
60
+ gauge_name = "test_#{SecureRandom.hex(5)}_gauge".to_sym
61
+ gauge_set_val = rand(1..25000000)
62
+ x.report("Gauge set") do
63
+ gauge = Gremlin::Instruments::Gauge.new gauge_name, "placeholder", {}
64
+ gauge.set({ :foo => "baz" }, gauge_set_val)
65
+ end
66
+ end
67
+ end
68
+
69
+ summary_init_benchmarks = (1..100).map do |n|
70
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
71
+ summary_name = "test_#{SecureRandom.hex(5)}_summary".to_sym
72
+ summary_observe_val = rand(1..25000000)
73
+ x.report("Summary initialize") { Gremlin::Instruments::Summary.new summary_name.to_sym, "placeholder", {} }
74
+ end
75
+ end
76
+
77
+ summary_init_and_fetch_benchmarks = (1..100).map do |n|
78
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
79
+ summary_name = "test_#{SecureRandom.hex(5)}_summary".to_sym
80
+ summary_observe_val = rand(1..25000000)
81
+ x.report("Summary fetch") do
82
+ Gremlin::Instruments::Summary.new summary_name.to_sym, "placeholder", {}
83
+ Gremlin.registry.get summary_name
84
+ end
85
+ end
86
+ end
87
+
88
+ summary_init_and_observe_benchmarks = (1..100).map do |n|
89
+ Benchmark.benchmark(CAPTION, 35, FORMAT) do |x|
90
+ summary_name = "test_#{SecureRandom.hex(5)}_summary".to_sym
91
+ summary_observe_val = rand(1..25000000)
92
+ x.report("Summary observe") do
93
+ summary = Gremlin::Instruments::Summary.new summary_name.to_sym, "placeholder", {}
94
+ summary.observe({ :bar => "foo" }, summary_observe_val)
95
+ end
96
+ end
97
+ end
98
+
99
+ STDOUT.reopen(orig_std_out)
100
+ print "Done!\n"
101
+
102
+ counter_init_agg = counter_init_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
103
+ counter_init_and_incr_agg = counter_init_and_incr_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
104
+ counter_init_and_fetch_agg = counter_init_and_fetch_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
105
+
106
+ puts "--------------------------------------------------------"
107
+ puts ""
108
+ puts "Counter Initialize Total: #{counter_init_agg*1000} ms"
109
+ puts "Counter Initialize Avg: #{counter_init_agg/100*1000} ms over 100 iterations"
110
+ puts "Counter Initialize and Fetch Total: #{counter_init_and_fetch_agg*1000} ms"
111
+ puts "Counter Initialize and Fetch Avg: #{counter_init_and_fetch_agg/100*1000} ms over 100 iterations"
112
+ puts "Counter Initialize and Fetch Total: #{counter_init_and_incr_agg*1000} ms"
113
+ puts "Counter Initialize and Fetch Avg: #{counter_init_and_incr_agg/100*1000} ms over 100 iterations"
114
+ puts ""
115
+
116
+ gauge_init_agg = gauge_init_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
117
+ gauge_init_and_fetch_agg = gauge_init_and_fetch_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
118
+ gauge_init_and_set_agg = gauge_init_and_set_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
119
+
120
+ puts "--------------------------------------------------------"
121
+ puts ""
122
+ puts "Gauge Initialize Total: #{gauge_init_agg*1000} ms"
123
+ puts "Gauge Initialize Avg: #{gauge_init_agg/100*1000} ms over 100 iterations"
124
+ puts "Gauge Initialize and Fetch Total: #{gauge_init_and_fetch_agg*1000} ms"
125
+ puts "Gauge Initialize and Fetch Avg: #{gauge_init_and_fetch_agg/100*1000} ms over 100 iterations"
126
+ puts "Gauge Initialize and Set Total: #{gauge_init_and_set_agg*1000} ms"
127
+ puts "Gauge Initialize and Set Avg: #{gauge_init_and_set_agg/100*1000} ms over 100 iterations"
128
+ puts ""
129
+ puts "--------------------------------------------------------"
130
+
131
+ summary_init_agg = summary_init_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
132
+ summary_init_and_fetch_agg = summary_init_and_fetch_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
133
+ summary_init_and_observe_agg = summary_init_and_observe_benchmarks.flatten.inject(0) { |sum, x| sum + x.real }
134
+
135
+ puts ""
136
+ puts "Summary Initialize Total: #{summary_init_agg*1000} ms"
137
+ puts "Summary Initialize Avg: #{summary_init_agg/100*1000} ms over 100 iterations"
138
+ puts "Summary Initialize and Fetch Total: #{summary_init_and_fetch_agg*1000} ms"
139
+ puts "Summary Initialize and Fetch Avg: #{summary_init_and_fetch_agg/100*1000} ms over 100 iterations"
140
+ puts "Summary Initialize and Observe Total: #{summary_init_and_observe_agg*1000} ms"
141
+ puts "Summary Initialize and Observe Avg: #{summary_init_and_observe_agg/100*1000} ms over 100 iterations"
142
+ puts ""
143
+ puts "--------------------------------------------------------"
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = %q{Gem to sanely emit metrics from Omadahealth rails applications}
13
13
  spec.description = %q{A modular metrics harness for Omadahealth rails applications}
14
- spec.homepage = "https://github.com/omadahealth/omada-metrics"
14
+ spec.homepage = "https://github.com/omadahealth/gremlin"
15
15
  spec.license = "MIT"
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
@@ -1,9 +1,11 @@
1
1
  # Supporting librarires
2
2
  require "active_support/cache"
3
3
  require "active_support/notifications" if defined?(::Rails)
4
- require "quantile"
4
+ require "erb"
5
5
  require "json"
6
+ require "quantile"
6
7
  require "redis_hash"
8
+ require "yaml"
7
9
 
8
10
  # Gem internals
9
11
  require "gremlin/version"
@@ -13,6 +15,7 @@ require "gremlin/instruments/counter"
13
15
  require "gremlin/instruments/gauge"
14
16
  require "gremlin/instruments/summary"
15
17
  require "gremlin/quantile"
18
+ require "gremlin/notification_observer"
16
19
 
17
20
  # Rails support
18
21
  require "gremlin/engine" if defined?(::Rails::Engine)
@@ -20,8 +23,37 @@ require "gremlin/railtie" if defined?(::Rails)
20
23
 
21
24
  module Gremlin
22
25
  class << self
26
+ attr_reader :configuration
27
+
23
28
  def registry
24
29
  @registry ||= Gremlin::Registry.new
25
30
  end
31
+
32
+ def configuration
33
+ unless @configuration
34
+ @configuration = configure do |c|
35
+ c.redis = { :host => "localhost", :port => 6379, :db => 15 }
36
+ c.enabled = true
37
+ end
38
+ end
39
+ @configuration
40
+ end
41
+
42
+ def configure
43
+ config = Config.new
44
+ yield config
45
+ @configuration = config
46
+ end
47
+
48
+ def enabled?
49
+ @configuration.enabled
50
+ end
51
+
52
+ def disabled?
53
+ not enabled?
54
+ end
55
+ end
56
+
57
+ class Config < Struct.new(:redis, :enabled)
26
58
  end
27
59
  end
@@ -9,7 +9,10 @@ module Gremlin
9
9
  @base_labels = base_labels
10
10
  @mutex = Mutex.new
11
11
 
12
+ Redis::Client.default = Redis.new(**Gremlin.configuration.redis)
13
+ @r = Redis.new(**Gremlin.configuration.redis)
12
14
  @values = Redis::NativeHash.find(retention_key) || Redis::NativeHash.new
15
+ @values.redis = Redis.new(**Gremlin.configuration.redis)
13
16
  @values.key = retention_key
14
17
  @values.save
15
18
  end
@@ -65,18 +68,6 @@ module Gremlin
65
68
  end
66
69
  end
67
70
  end
68
-
69
- def get(labels={})
70
- v = @values[labels.to_json]
71
- case type
72
- when :counter
73
- v.to_i
74
- when :gauge
75
- v.to_f
76
- else
77
- v
78
- end
79
- end
80
71
  end
81
72
  end
82
73
  end
@@ -5,10 +5,7 @@ module Gremlin
5
5
  class Counter < Base
6
6
  def increment(labels={}, by=1)
7
7
  @mutex.synchronize do
8
- prev_val = get(labels.to_json) || default
9
- @values[labels.to_json] = prev_val + by
10
- @values.save
11
- @values[labels.to_json]
8
+ @r.hincrby retention_key, labels.to_json, by
12
9
  end
13
10
  end
14
11
 
@@ -23,6 +20,12 @@ module Gremlin
23
20
  def retention_key
24
21
  "gremlin_prometheus_#{node}_metrics_counter_#{name}"
25
22
  end
23
+
24
+ def get(labels={})
25
+ @values.reload!
26
+ v = @values[labels.to_json]
27
+ v.to_i
28
+ end
26
29
  end
27
30
  end
28
31
  end
@@ -5,9 +5,8 @@ module Gremlin
5
5
  class Gauge < Base
6
6
  def set(labels={}, value)
7
7
  @mutex.synchronize do
8
- @values[labels.to_json] = value
9
- @values.save
10
- @values[labels.to_json]
8
+ @r.hset retention_key, labels.to_json, value
9
+ get(labels)
11
10
  end
12
11
  end
13
12
 
@@ -18,6 +17,12 @@ module Gremlin
18
17
  def retention_key
19
18
  "gremlin_prometheus_#{node}_metrics_gauge_#{name}"
20
19
  end
20
+
21
+ def get(labels={})
22
+ @values.reload!
23
+ v = @values[labels.to_json]
24
+ v.to_f
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -0,0 +1,38 @@
1
+ module Gremlin
2
+ module NotificationObserver
3
+ class CounterReceiver
4
+ def initialize(name, docstring, labels)
5
+ @instrument = Gremlin::Instruments::Counter.new(name, docstring, labels)
6
+ begin
7
+ Gremlin.registry.register @instrument
8
+ rescue Gremlin::Registry::AlreadyRegisteredError; end
9
+ end
10
+
11
+ def call(name, start, finish, id, payload)
12
+ instrument.increment({})
13
+ end
14
+
15
+ def instrument
16
+ Gremlin.registry.get(@instrument.name)
17
+ end
18
+ end
19
+
20
+ class SummaryReceiver
21
+ def initialize(name, docstring, labels, payload_field)
22
+ @instrument = Gremlin::Instruments::Summary.new(name, docstring, labels)
23
+ begin
24
+ Gremlin.registry.register @instrument
25
+ rescue Gremlin::Registry::AlreadyRegisteredError; end
26
+ @field_to_observe = payload_field
27
+ end
28
+
29
+ def call(name, start, finish, id, payload)
30
+ instrument.observe({}, payload[@field_to_observe.to_sym])
31
+ end
32
+
33
+ def instrument
34
+ Gremlin.registry.get(@instrument.name)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,130 +1,93 @@
1
1
  module Gremlin
2
- class Railtie < ::Rails::Railtie
3
- config.before_initialize do
4
- # XXX is there anything to configure? redis?
5
- end
6
-
7
- initializer "gremlin.base_instrumentation" do |app|
8
- environment = ::Rails.env.to_s
9
- application_name = ::Rails.application.class.parent_name.downcase
10
- node = `hostname`.strip
11
-
12
- #
13
- # ActionController
14
- #
15
-
16
- ActiveSupport::Notifications.subscribe "start_processing.action_controller" do |name, start, finish, id, payload|
17
- # Payload contains:
18
- # :controller --- The controller name
19
- # :action --- The action
20
- # :params --- Hash of request parameters without any filtered parameter
21
- # :headers --- Request headers
22
- # :format --- html/js/json/xml etc
23
- # :method --- HTTP request verb
24
- # :path --- Request path
25
-
26
- # Counter to track event occurances
2
+ module ActionController
3
+ class StartProcessingCounterReceiver < Gremlin::NotificationObserver::CounterReceiver
4
+ def call(name, start, finish, id, payload)
27
5
  begin
28
- occurance_counter = Gremlin::Instruments::Counter.new("action_controller_start_processing_events".to_sym,
29
- "ActionController start processing occurance counter.",
30
- application: application_name, environment: environment, node: node)
31
- Gremlin.registry.register occurance_counter
32
- rescue Gremlin::Registry::AlreadyRegisteredError
33
- occurance_counter = Gremlin.registry.get "action_controller_start_processing_events".to_sym
34
- end
35
-
36
- occurance_counter.increment({ controller: payload[:controller].to_s, format: payload[:format].to_s, action: payload[:action] })
6
+ instrument.increment({ controller: payload[:controller].to_s,
7
+ format: payload[:format].to_s,
8
+ action: payload[:action] })
9
+ rescue; end
37
10
  end
11
+ end
38
12
 
39
- ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload|
40
- # Payload contains:
41
- # :controller --- The controller name
42
- # :action --- The action
43
- # :params --- Hash of request parameters *without any filtered parameter*
44
- # :headers --- Request headers
45
- # :format --- html/js/json/xml etc
46
- # :method --- HTTP request verb
47
- # :path --- Request path
48
- # :status --- HTTP status code
49
- # :view_runtime --- Amount spent in view in ms
50
- # :db_runtime --- Amount spent executing database queries in ms
51
-
52
- # Counter to track event occurances
53
- begin
54
- occurance_counter = Gremlin::Instruments::Counter.new("action_controller_process_action_events".to_sym,
55
- "ActionController process action occurance counter.",
56
- application: application_name, environment: environment, node: node)
57
- Gremlin.registry.register occurance_counter
58
- rescue Gremlin::Registry::AlreadyRegisteredError
59
- occurance_counter = Gremlin.registry.get "action_controller_process_action_events".to_sym
60
- end
61
-
62
- occurance_counter.increment({ controller: payload[:controller].to_s, format: payload[:format].to_s, action: payload[:action], status: payload[:status] })
63
-
13
+ class ProcessActionCounterReceiver < Gremlin::NotificationObserver::CounterReceiver
14
+ def call(name, start, finish, id, payload)
64
15
  begin
65
- db_summary = Gremlin::Instruments::Summary.new("action_controller_process_action_db_runtime_ms".to_sym,
66
- "ActionController process action DB runtime in milliseconds.",
67
- application: application_name, environment: environment, node: node)
68
- Gremlin.registry.register db_summary
69
- rescue Gremlin::Registry::AlreadyRegisteredError
70
- db_summary = Gremlin.registry.get "action_controller_process_action_db_runtime_ms".to_sym
71
- end
72
-
73
- db_summary.observe({ controller: payload[:controller], method: payload[:method], status: payload[:status], action: payload[:action] }, payload[:db_runtime])
16
+ instrument.increment({ controller: payload[:controller].to_s,
17
+ format: payload[:format].to_s,
18
+ action: payload[:action],
19
+ status: payload[:status] })
20
+ rescue; end
21
+ end
22
+ end
74
23
 
24
+ class ProcessActionSummaryReceiver < Gremlin::NotificationObserver::SummaryReceiver
25
+ def call(name, start, finish, id, payload)
75
26
  begin
76
- view_summary = Gremlin::Instruments::Summary.new("action_controller_process_action_view_runtime_ms".to_sym,
77
- "ActionController process action view runtime in milliseconds.",
78
- application: application_name, environment: environment, node: node)
79
- Gremlin.registry.register view_summary
80
- rescue Gremlin::Registry::AlreadyRegisteredError
81
- view_summary = Gremlin.registry.get "action_controller_process_action_view_runtime_ms".to_sym
82
- end
83
-
84
- view_summary.observe({ controller: payload[:controller], method: payload[:method], status: payload[:status], action: payload[:action] }, payload[:view_runtime])
27
+ instrument.observe({ controller: payload[:controller],
28
+ method: payload[:method],
29
+ status: payload[:status],
30
+ action: payload[:action] },
31
+ payload[@field_to_observe.to_sym])
32
+ rescue; end
33
+ end
34
+ end
35
+ end
36
+
37
+ class Railtie < ::Rails::Railtie
38
+ config.before_initialize do
39
+ Gremlin.configure do |c|
40
+ c.redis = { url: "localhost", port: 6379, db: 15 }
41
+ c.enabled = true
85
42
  end
86
43
 
87
- ActiveSupport::Notifications.subscribe "redirect_to.action_controller" do |name, start, finish, id, payload|
88
- # Payload contains:
89
- # :status --- HTTP response code
90
- # :location --- URL to redirect to
91
-
92
- # Counter to track event occurances
93
- begin
94
- occurance_counter = Gremlin::Instruments::Counter.new("action_controller_redirect_to_events".to_sym,
95
- "ActionController redirect to occurance counter.",
96
- application: application_name, environment: environment, node: node)
97
- Gremlin.registry.register occurance_counter
98
- rescue Gremlin::Registry::AlreadyRegisteredError
99
- occurance_counter = Gremlin.registry.get "action_controller_redirect_to_events".to_sym
44
+ conf_file = ::Rails.root.join("config", "gremlin.yml")
45
+ config = YAML.load(ERB.new(File.read(conf_file)).result) if File.exists?(conf_file)
46
+ if config
47
+ Gremlin.configure do |c|
48
+ c.redis = config[::Rails.env] ? config[::Rails.env]["redis"] : config["redis"]
49
+ c.enabled = config[::Rails.env] ? config[::Rails.env]["enabled"] : config["enabled"]
100
50
  end
101
-
102
- occurance_counter.increment({ status: payload[:status] })
103
51
  end
52
+ end
104
53
 
105
- ##
106
- ## ActiveRecord
107
- ##
54
+ initializer "gremlin.base_instrumentation" do |app|
55
+ environment = ::Rails.env.to_s
56
+ application_name = ::Rails.application.class.parent_name.downcase
57
+ node = `hostname`.strip
58
+ basic_labels = { node: node, app: application_name, env: environment }
108
59
 
109
- ActiveSupport::Notifications.subscribe "sql.active_record" do |name, start, finish, id, payload|
110
- # Payload contains:
111
- # :sql --- SQL statement
112
- # :name --- Name of the operation
113
- # :connection_id --- self.object_id
114
- # :binds --- Bind parameters
60
+ next if Gremlin.disabled?
115
61
 
116
- # Counter to track event occurances
117
- begin
118
- occurance_counter = Gremlin::Instruments::Counter.new("active_record_sql_events".to_sym,
119
- "ActiveRecord SQL occurance counter.",
120
- application: application_name, environment: environment, node: node)
121
- Gremlin.registry.register occurance_counter
122
- rescue Gremlin::Registry::AlreadyRegisteredError
123
- occurance_counter = Gremlin.registry.get "active_record_sql_events".to_sym
124
- end
62
+ #
63
+ # ActionController instrumentation
64
+ #
125
65
 
126
- occurance_counter.increment
127
- end
66
+ # Generic instrumentation for /(start_processing|process_action|redirect_to)\.action_controller/
67
+ occurance_counter = Gremlin::NotificationObserver::CounterReceiver.new("notification_count",
68
+ "Count of notifications handled by Gremlin.",
69
+ basic_labels)
70
+ ActiveSupport::Notifications.subscribe /(start_processing|process_action|redirect_to)\.action_controller/, occurance_counter
71
+
72
+ # Instrumentation for start_processing.action_controller
73
+ start_processing_occurance_counter = Gremlin::ActionController::StartProcessingCounterReceiver.new("action_controller_start_processing_count",
74
+ "Count of start_processing.action_controller notifications handled by Gremlin.",
75
+ basic_labels)
76
+ ActiveSupport::Notifications.subscribe "start_processing.action_controller", start_processing_occurance_counter
77
+
78
+ # Instrumentation for process_action.action_controller
79
+ view_summary = Gremlin::ActionController::ProcessActionSummaryReceiver.new("action_controller_process_action_view_runtime_ms",
80
+ "ActionController process action view runtime in milliseconds.",
81
+ basic_labels, "view_runtime")
82
+ db_summary = Gremlin::ActionController::ProcessActionSummaryReceiver.new("action_controller_process_action_db_runtime_ms",
83
+ "ActionController process action db runtime in milliseconds.",
84
+ basic_labels, "db_runtime")
85
+ process_action_occurance_counter = Gremlin::ActionController::ProcessActionCounterReceiver.new("action_controller_process_action_count",
86
+ "Count of process_action.action_controller notifications handled by Gremlin.",
87
+ basic_labels)
88
+ ActiveSupport::Notifications.subscribe "process_action.action_controller", process_action_occurance_counter
89
+ ActiveSupport::Notifications.subscribe "process_action.action_controller", view_summary
90
+ ActiveSupport::Notifications.subscribe "process_action.action_controller", db_summary
128
91
  end
129
92
  end
130
93
  end
@@ -5,7 +5,9 @@ module Gremlin
5
5
  NotAMetricError = Class.new StandardError
6
6
 
7
7
  def initialize
8
+ Redis::Client.default = Redis.new(**Gremlin.configuration.redis)
8
9
  @metrics = Redis::NativeHash.find(retention_key) || Redis::NativeHash.new()
10
+ @metrics.redis = Redis.new(**Gremlin.configuration.redis)
9
11
  @metrics.key = retention_key
10
12
  @metrics.save
11
13
 
@@ -26,6 +28,10 @@ module Gremlin
26
28
  end
27
29
  end
28
30
 
31
+ def dump_metrics
32
+ @metrics
33
+ end
34
+
29
35
  def get(name)
30
36
  m = @metrics[name.to_sym]
31
37
  deserialize(m) unless m.nil?
@@ -1,3 +1,3 @@
1
1
  module Gremlin
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gremlin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin G. Phillips
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-17 00:00:00.000000000 Z
11
+ date: 2017-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -139,6 +139,7 @@ files:
139
139
  - Gemfile
140
140
  - Gemfile.lock
141
141
  - app/controllers/gremlin/metrics_controller.rb
142
+ - benchmark.rb
142
143
  - config/routes.rb
143
144
  - gremlin.gemspec
144
145
  - lib/gremlin.rb
@@ -147,13 +148,14 @@ files:
147
148
  - lib/gremlin/instruments/counter.rb
148
149
  - lib/gremlin/instruments/gauge.rb
149
150
  - lib/gremlin/instruments/summary.rb
151
+ - lib/gremlin/notification_observer.rb
150
152
  - lib/gremlin/quantile.rb
151
153
  - lib/gremlin/quantile/estimator.rb
152
154
  - lib/gremlin/quantile/quantile.rb
153
155
  - lib/gremlin/railtie.rb
154
156
  - lib/gremlin/registry.rb
155
157
  - lib/gremlin/version.rb
156
- homepage: https://github.com/omadahealth/omada-metrics
158
+ homepage: https://github.com/omadahealth/gremlin
157
159
  licenses:
158
160
  - MIT
159
161
  metadata: