sidewatch 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b49f4160ae5ce3ac9bf51f9368f526659f841ba
4
+ data.tar.gz: 533bfa8a7b43ccb239ed218c1dcfeb26e5b1c3bb
5
+ SHA512:
6
+ metadata.gz: b76fa21af012ac9750c1397324ee005fb0389626657cacec615e740ee45b4b46679d0251555e29676b2cdc59f2f88eeb4ec7cc97478a45f64c962fb2849c5639
7
+ data.tar.gz: 058f477685ebe6800eda1394913a626b702a1d07ec85cf0b93be25afdf3f1f477b1aa0b86f5173cad60a5b6aeb1b015444ee6867958514cbca20c5ec0ee7da77
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.log
3
+ *.yml
4
+ *.rbc
5
+ .bundle
6
+ .env
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jan Hecking
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Sidewatch
2
+
3
+ Sidewatch uploads Sidekiq metrics to AWS CloudWatch in regular intervals.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sidewatch'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sidewatch
18
+
19
+ ## Usage
20
+
21
+ To start sidewatch as a daemon process in the background run
22
+
23
+ ruby sidewatch.rb start
24
+
25
+ To run sidewatch in the foreground, e.g. for testing, run
26
+
27
+ ruby sidewatch.rb run
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
data/bin/sidewatch ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+ require "dotenv"
6
+ require "sidewatch"
7
+
8
+ Bundler.require
9
+ Dotenv.load
10
+
11
+ pwd = Dir.pwd
12
+ Daemons.run_proc("sidewatch") do
13
+ Sidewatch::CLI.new(pwd).run
14
+ end
data/lib/sidewatch.rb ADDED
@@ -0,0 +1,19 @@
1
+ require "sidewatch/version"
2
+ require "sidewatch/cli"
3
+ require "sidewatch/daemon"
4
+ require "sidewatch/metric"
5
+ require "sidewatch/sidekiq"
6
+ require "sidewatch/cloudwatch"
7
+
8
+ module Sidewatch
9
+
10
+ class << self
11
+ attr_accessor :config
12
+ attr_accessor :logger
13
+ end
14
+
15
+ self.config = {}
16
+ self.logger = Logger.new(STDERR)
17
+ logger.level = Logger::WARN
18
+
19
+ end
@@ -0,0 +1,66 @@
1
+ require "erb"
2
+
3
+ module Sidewatch
4
+ class CLI
5
+
6
+ attr_accessor :options
7
+ attr_accessor :config_file
8
+
9
+ def initialize(pwd = Dir.pwd)
10
+ self.working_dir = pwd
11
+ parse_options
12
+ parse_config
13
+ setup_logger
14
+ end
15
+
16
+ def run
17
+ Sidewatch::Daemon.new(Sidewatch.config).run
18
+ end
19
+
20
+ private
21
+
22
+ attr_accessor :working_dir
23
+
24
+ def drop_daemons_args(args)
25
+ args = args.drop_while{|arg| arg != "--"}
26
+ args.drop(1)
27
+ end
28
+
29
+ def parse_options(args = ARGV)
30
+ args = drop_daemons_args(args)
31
+ options = {}
32
+ parser = OptionParser.new do |opts|
33
+ opts.banner = "Usage: #{__FILE__} [start|stop|run] (-- [options])"
34
+ opts.on("-c", "--config PATH", "path to YAML Config file") do |file|
35
+ options[:config] = file
36
+ end
37
+ opts.on("-l", "--logfile PATH", "path to writeable logfile") do |file|
38
+ options[:logfile] = file
39
+ end
40
+ end
41
+ parser.parse(args)
42
+ self.options = options
43
+ end
44
+
45
+ def parse_config
46
+ self.config_file = options.fetch(:config){ "/etc/sidewatch.yml" }
47
+ self.config_file = File.expand_path(config_file, working_dir)
48
+ if File.exists?(config_file)
49
+ config = YAML.load(ERB.new(IO.read(config_file)).result)
50
+ config.merge(options)
51
+ Sidewatch.config = config.symbolize_keys
52
+ end
53
+ end
54
+
55
+ def setup_logger
56
+ logfile =
57
+ if options[:logfile]
58
+ File.expand_path(options[:logfile], working_dir)
59
+ elsif Sidewatch.config[:logfile]
60
+ File.expand_path(Sidewatch.config[:logfile], File.dirname(config_file))
61
+ end
62
+ Sidewatch.logger = Logger.new(logfile) if logfile
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,49 @@
1
+ require "aws-sdk"
2
+
3
+ module Sidewatch
4
+ class Cloudwatch
5
+
6
+ attr_accessor :client
7
+
8
+ def initialize(config = {})
9
+ client = config.delete(:client){ Aws::CloudWatch::Client }
10
+ client = Object.const_get(client) if client.is_a?(String)
11
+ client = client.new(config) if client.is_a?(Class)
12
+ self.client = client
13
+ end
14
+
15
+ def send(metrics)
16
+ metrics.group_by(&:namespace).each do |ns, ns_metrics|
17
+ data = metric_data(ns, ns_metrics)
18
+ client.put_metric_data(data)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def metric_data(ns, metrics)
25
+ {
26
+ namespace: ns,
27
+ metric_data: metrics.map{|m|
28
+ {
29
+ metric_name: m.name,
30
+ dimensions: Array(m.dimensions).map{|name, value| {name: name, value: value}},
31
+ timestamp: m.timestamp,
32
+ value: m.value,
33
+ unit: m.unit
34
+ }
35
+ }
36
+ }
37
+ end
38
+
39
+ class MockClient
40
+ def initialize(config = {})
41
+ @out = config.fetch(:output){ $stdout }
42
+ end
43
+ def put_metric_data(data)
44
+ @out << data.to_s
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,46 @@
1
+ require "daemons"
2
+
3
+ module Sidewatch
4
+
5
+ class Daemon
6
+
7
+ attr_accessor :sidekiq
8
+ attr_accessor :cloudwatch
9
+ attr_accessor :interval
10
+
11
+ def initialize(config = {})
12
+ sidekiq_config = config.fetch(:sidekiq){ Hash.new }.symbolize_keys
13
+ self.sidekiq = Sidewatch::Sidekiq.new(sidekiq_config)
14
+ cloudwatch_config = config.fetch(:cloudwatch){ Hash.new }.symbolize_keys
15
+ self.cloudwatch = Sidewatch::Cloudwatch.new(cloudwatch_config)
16
+ self.interval = config.fetch(:interval){ 60 }
17
+ end
18
+
19
+ def run
20
+ logger.info("Starting #{self.class}...")
21
+ every(interval) do
22
+ metrics = sidekiq.metrics
23
+ logger.info(metrics)
24
+ cloudwatch.send(metrics)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def every(interval, &block)
31
+ loop do
32
+ ts = Time.now
33
+ block.call
34
+ remaining = (ts + interval) - Time.now
35
+ sleep remaining
36
+ end
37
+ rescue Interrupt
38
+ logger.info("Interrupted; exiting.")
39
+ end
40
+
41
+ def logger
42
+ Sidewatch.logger
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ class Metric
2
+
3
+ attr_accessor :namespace
4
+ attr_accessor :name
5
+ attr_accessor :value
6
+ attr_accessor :unit
7
+ attr_accessor :dimensions
8
+ attr_accessor :timestamp
9
+
10
+ def initialize(attributes = {})
11
+ attributes.each do |name, value|
12
+ public_send("#{name}=", value)
13
+ end
14
+ self.timestamp ||= Time.now.utc
15
+ end
16
+
17
+ def inspect
18
+ ts = timestamp.iso8601 if timestamp
19
+ {
20
+ namespace: namespace,
21
+ name: name,
22
+ value: value,
23
+ unit: unit,
24
+ dimensions: dimensions,
25
+ timestamp: ts
26
+ }.reject{|_,v| v.nil?}
27
+ end
28
+
29
+ end
@@ -0,0 +1,72 @@
1
+ require "sidekiq"
2
+
3
+ module Sidewatch
4
+ class Sidekiq
5
+
6
+ attr_accessor :namespace
7
+
8
+ def initialize(config = {})
9
+ self.namespace = config.fetch(:namespace){ "Sidekiq" }
10
+ ::Sidekiq.redis = config[:redis].symbolize_keys if config[:redis]
11
+ end
12
+
13
+ def metrics
14
+ metrics = []
15
+ metrics += global_metrics
16
+ metrics += per_queue_metrics
17
+ metrics
18
+ end
19
+
20
+ def global_metrics
21
+ stats = sidekiq_stats
22
+ metrics = []
23
+ [:failed, :enqueued, :processed, :retry_size, :scheduled_size].each do |stat|
24
+ name = camelcase(stat)
25
+ value = stats.send(stat)
26
+ metrics << Metric.new(namespace: namespace, name: name, value: value, unit: "Count", dimensions: default_dimensions)
27
+ end
28
+ metrics
29
+ end
30
+
31
+ def per_queue_metrics
32
+ metrics = []
33
+ sidekiq_queues.each do |queue|
34
+ dimensions = default_dimensions.merge("QueueName" => queue.name)
35
+ metrics << Metric.new(namespace: namespace, name: "Enqueued", value: queue.size, unit: "Count", dimensions: dimensions)
36
+ metrics << Metric.new(namespace: namespace, name: "Latency", value: queue.latency, unit: "Count", dimensions: dimensions)
37
+ end
38
+ metrics
39
+ end
40
+
41
+ private
42
+
43
+ def sidekiq_stats
44
+ ::Sidekiq::Stats.new
45
+ end
46
+
47
+ def sidekiq_queues
48
+ ::Sidekiq::Queue.all
49
+ end
50
+
51
+ def redis_uri
52
+ # is there a simpler way to get this?
53
+ uri = ::Sidekiq.redis {|redis|
54
+ redis = redis.redis if redis.is_a?(Redis::Namespace)
55
+ redis.client.id
56
+ }
57
+ uri = URI.parse(uri)
58
+ uri.password = "*****" if uri.password
59
+ uri.to_s
60
+ end
61
+
62
+ def default_dimensions
63
+ { "RedisURI" => redis_uri }
64
+ end
65
+
66
+ def camelcase(term)
67
+ string = term.to_s
68
+ string.gsub(/(?:^|_)([a-z\d]*)/){ $1.capitalize }
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Sidewatch
2
+ VERSION = "0.0.1"
3
+ end
data/sidewatch.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sidewatch/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sidewatch"
8
+ spec.version = Sidewatch::VERSION
9
+ spec.authors = ["Jan Hecking"]
10
+ spec.email = ["jan@travelmob.com"]
11
+ spec.description = %q{Uploads Sidekiq metrics to AWS CloudWatch in regular intervals}
12
+ spec.summary = %q{Uploads Sidekiq metrics to AWS CloudWatch in regular intervals}
13
+ spec.homepage = "https://github.com/jhecking"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake", "~> 10.4"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+
25
+ spec.add_runtime_dependency "daemons", "~> 1.2"
26
+ spec.add_runtime_dependency "sidekiq", "~> 2.17"
27
+ spec.add_runtime_dependency "aws-sdk", "~> 2.0"
28
+ spec.add_runtime_dependency "dotenv", "~> 2.0"
29
+ end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+
3
+ module Sidewatch
4
+
5
+ describe Cloudwatch do
6
+
7
+ let(:client){ spy("cloudwatch-client") }
8
+ subject{ described_class.new(client: client) }
9
+
10
+ describe "#send" do
11
+
12
+ it "sends the metrics using the cloudwatch client" do
13
+ metrics = []
14
+ metrics << Metric.new(namespace: "Clocks", name: "Ticks", value: 1234, unit: "Count", dimensions: { "ClockName" => "cuckoo" }, timestamp: Time.at(1440494300))
15
+ expected = {
16
+ namespace: "Clocks",
17
+ metric_data: [
18
+ {
19
+ metric_name: "Ticks",
20
+ dimensions: [
21
+ {
22
+ name: "ClockName",
23
+ value: "cuckoo"
24
+ }
25
+ ],
26
+ timestamp: Time.at(1440494300),
27
+ value: 1234,
28
+ unit: "Count"
29
+ }
30
+ ]
31
+ }
32
+
33
+ subject.send(metrics)
34
+
35
+ expect(client).to have_received(:put_metric_data).with(expected)
36
+ end
37
+
38
+ it "groups the metrics by namespace" do
39
+ metrics = []
40
+ metrics << Metric.new(namespace: "Clocks", name: "Ticks", value: 1234, unit: "Count")
41
+ metrics << Metric.new(namespace: "Events", name: "Failed", value: 55, unit: "Count")
42
+ received = []
43
+ allow(client).to receive(:put_metric_data){ |data| received << data }
44
+
45
+ subject.send(metrics)
46
+
47
+ expect(received).to contain_exactly(hash_including(namespace: "Clocks"), hash_including(namespace: "Events"))
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ module Sidewatch
4
+
5
+ describe Metric do
6
+
7
+ let(:namespace){ "Clocks" }
8
+ let(:metric_name){ "Ticks" }
9
+ let(:metric_value){ 1234 }
10
+ let(:metric_unit){ "Count" }
11
+ let(:dimensions){ { "ClockName" => "cuckoo" } }
12
+ let(:timestamp){ Time.at(1440494300) }
13
+ subject {
14
+ described_class.new(
15
+ name: metric_name,
16
+ value: metric_value,
17
+ unit: metric_unit,
18
+ dimensions: dimensions,
19
+ timestamp: timestamp,
20
+ )
21
+ }
22
+
23
+ describe "#initialize" do
24
+
25
+ context "missing timestamp" do
26
+ let(:timestamp){ nil }
27
+ it "sets a default timestamp" do
28
+ expect(subject.timestamp).to_not be_nil
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+
3
+ module Sidewatch
4
+
5
+ describe Sidekiq do
6
+
7
+ before(:each) do
8
+ allow(::Sidekiq).to receive(:redis=)
9
+ allow(subject).to receive(:redis_uri){ "redis://localhost:6379/0" }
10
+ end
11
+
12
+ describe "#metrics" do
13
+
14
+ it "returns global and per-queue metrics" do
15
+ global = double("global-metric")
16
+ expect(subject).to receive(:global_metrics).and_return([global])
17
+ per_queue = double("queue-metric")
18
+ expect(subject).to receive(:per_queue_metrics).and_return([per_queue])
19
+
20
+ metrics = subject.metrics
21
+
22
+ expect(metrics).to contain_exactly(global, per_queue)
23
+ end
24
+ end
25
+
26
+ describe "#global_metrics" do
27
+
28
+ let(:stats){
29
+ double("stats",
30
+ failed: 111,
31
+ enqueued: 222,
32
+ processed: 333,
33
+ retry_size: 444,
34
+ scheduled_size: 555,
35
+ )
36
+ }
37
+ before(:each) do
38
+ allow(subject).to receive(:sidekiq_stats){ stats }
39
+ end
40
+
41
+ it "produces a metric for failed jobs" do
42
+ failed = subject.global_metrics.find{|m| m.name == "Failed"}
43
+ expect(failed.value).to eq 111
44
+ end
45
+
46
+ it "produces a metric for enqueued jobs" do
47
+ failed = subject.global_metrics.find{|m| m.name == "Enqueued"}
48
+ expect(failed.value).to eq 222
49
+ end
50
+
51
+ it "produces a metric for processed jobs" do
52
+ failed = subject.global_metrics.find{|m| m.name == "Processed"}
53
+ expect(failed.value).to eq 333
54
+ end
55
+
56
+ it "produces a metric for retry queue size" do
57
+ failed = subject.global_metrics.find{|m| m.name == "RetrySize"}
58
+ expect(failed.value).to eq 444
59
+ end
60
+
61
+ it "produces a metric for scheduled queue size" do
62
+ failed = subject.global_metrics.find{|m| m.name == "ScheduledSize"}
63
+ expect(failed.value).to eq 555
64
+ end
65
+
66
+ end
67
+
68
+ describe "#per_queue_metrics" do
69
+
70
+ let(:queues){
71
+ [
72
+ double("queue1", name: "high-priority", size: 50, latency: 5),
73
+ double("queue2", name: "low-priority", size: 100, latency: 10),
74
+ ]
75
+ }
76
+ before(:each) do
77
+ allow(subject).to receive(:sidekiq_queues){ queues }
78
+ end
79
+
80
+ it "produces queue length and latency metrics for each queue" do
81
+ metrics = subject.per_queue_metrics.map(&:name).uniq
82
+
83
+ expect(metrics).to contain_exactly("Enqueued", "Latency")
84
+ end
85
+
86
+ it "produces at least one metric for every queue" do
87
+ metrics = subject.per_queue_metrics
88
+ queues = metrics.map{|metric| metric.dimensions["QueueName"]}.uniq
89
+
90
+ expect(queues).to contain_exactly("high-priority", "low-priority")
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1 @@
1
+ require "sidewatch"
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidewatch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jan Hecking
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: daemons
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sidekiq
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.17'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.17'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '2.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: dotenv
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ description: Uploads Sidekiq metrics to AWS CloudWatch in regular intervals
112
+ email:
113
+ - jan@travelmob.com
114
+ executables:
115
+ - sidewatch
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - bin/sidewatch
125
+ - lib/sidewatch.rb
126
+ - lib/sidewatch/cli.rb
127
+ - lib/sidewatch/cloudwatch.rb
128
+ - lib/sidewatch/daemon.rb
129
+ - lib/sidewatch/metric.rb
130
+ - lib/sidewatch/sidekiq.rb
131
+ - lib/sidewatch/version.rb
132
+ - sidewatch.gemspec
133
+ - spec/cloudwatch_spec.rb
134
+ - spec/metric_spec.rb
135
+ - spec/sidekiq_spec.rb
136
+ - spec/spec_helper.rb
137
+ homepage: https://github.com/jhecking
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.4.3
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Uploads Sidekiq metrics to AWS CloudWatch in regular intervals
161
+ test_files:
162
+ - spec/cloudwatch_spec.rb
163
+ - spec/metric_spec.rb
164
+ - spec/sidekiq_spec.rb
165
+ - spec/spec_helper.rb