metrics_satellite 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +65 -0
  5. data/Rakefile +1 -0
  6. data/bin/metrics_satellite +6 -0
  7. data/lib/metrics_satellite/collectors/brakeman_collector.rb +12 -0
  8. data/lib/metrics_satellite/collectors/collector.rb +26 -0
  9. data/lib/metrics_satellite/collectors/flay_collector.rb +7 -0
  10. data/lib/metrics_satellite/collectors/guideline_collector.rb +14 -0
  11. data/lib/metrics_satellite/collectors/hotspots_collector.rb +19 -0
  12. data/lib/metrics_satellite/collectors/rails_best_practices_collector.rb +13 -0
  13. data/lib/metrics_satellite/filer.rb +58 -0
  14. data/lib/metrics_satellite/option_parser.rb +99 -0
  15. data/lib/metrics_satellite/reporter.rb +29 -0
  16. data/lib/metrics_satellite/runner.rb +101 -0
  17. data/lib/metrics_satellite/summarizers/brakeman_summarizer.rb +36 -0
  18. data/lib/metrics_satellite/summarizers/flay_summarizer.rb +21 -0
  19. data/lib/metrics_satellite/summarizers/guideline_summarizer.rb +24 -0
  20. data/lib/metrics_satellite/summarizers/hotspots_summarizer.rb +9 -0
  21. data/lib/metrics_satellite/summarizers/rails_best_practices_summarizer.rb +32 -0
  22. data/lib/metrics_satellite/summarizers/summarizer.rb +46 -0
  23. data/lib/metrics_satellite/version.rb +3 -0
  24. data/lib/metrics_satellite.rb +17 -0
  25. data/metrics_satellite.gemspec +31 -0
  26. data/spec/metrics_satellite/reporter_spec.rb +27 -0
  27. data/spec/metrics_satellite/runner_spec.rb +32 -0
  28. data/spec/metrics_satellite/summarizers/brakeman_summarizer_spec.rb +54 -0
  29. data/spec/metrics_satellite/summarizers/flay_summarizer_spec.rb +35 -0
  30. data/spec/metrics_satellite/summarizers/guideline_summarizer_spec.rb +54 -0
  31. data/spec/metrics_satellite/summarizers/hotspots_summarizer_spec.rb +35 -0
  32. data/spec/metrics_satellite/summarizers/rails_best_practices_summarizer_spec.rb +69 -0
  33. data/spec/spec_helper.rb +11 -0
  34. metadata +263 -0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ reports/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in metrics_satellite.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ryo Nakamura
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,65 @@
1
+ # MetricsSatellite
2
+ MetricsSatellite collects your rails application metrics.
3
+ This gem invokes 5 static metrics tools:
4
+
5
+ * [Brakeman](https://github.com/presidentbeef/brakeman) - A static analysis security vulnerability scanner for Rails
6
+ * [Flay](https://github.com/seattlerb/flay) - Analyzes code for structural similarities
7
+ * [Guideline](https://github.com/r7kamura/guideline) - Checks that your code is protecting the rule of coding guideline
8
+ * [Hotspots](https://github.com/chiku/hotspots) - Identify frequently modified files in a git repository
9
+ * [RailsBestPractices](https://github.com/railsbp/rails_best_practices) - A code metric tool for rails projects
10
+
11
+ ## Requirements
12
+ * Ruby >= 1.9
13
+
14
+ ## Installation
15
+ ```
16
+ $ gem install metrics_satellite
17
+ ```
18
+
19
+ ## Usage
20
+ MetricsSatellite has 2 features:
21
+
22
+ 1. Collect today's metrics reports
23
+ 2. Post today's metrics summary to [GrowthForcast](http://kazeburo.github.com/GrowthForecast/)
24
+
25
+ ```
26
+ $ metrics_satellite
27
+ Usage: metrics_satellite [options]
28
+ --type= (default: -) 'collect' or 'post'
29
+ --host= (default: -) GrowthForecast host to send report
30
+ --service= (default: metrics) GrowthForecast service name
31
+ --section= (default: section) GrowthForecast section name
32
+ --git= (default: ./) git repository directory
33
+ --app= (default: ./) application directory
34
+ --reports= (default: reports) collected reports directory
35
+ --guideline-abc-complexity= (default: 15) threshold of ABC complexity
36
+ --guideline-long-line= (default: 80) threshold of long line
37
+ --guideline-long-method= (default: 10) threshold of long method
38
+ --hotspots-cutoff= (default: 10) threshold of change count
39
+ --hotspots-time= (default: 14) time span of git log target
40
+ --no-brakeman (default: false) disable Brakeman
41
+ --no-flay (default: false) disable Flay
42
+ --no-guideline (default: false) disable Guideline
43
+ --no-hotspots (default: false) disable Hotspots
44
+ --no-rails-best-practices (default: false) disable RailsBestPractices
45
+ ```
46
+
47
+ ### Collect
48
+ Collect today's metrics reports.
49
+ By default, reports are saved in `./reports/` directory.
50
+
51
+ ```
52
+ $ metrics_satellite --type collect
53
+ ```
54
+
55
+ ![](http://dl.dropbox.com/u/5978869/image/20130108_170925.png)
56
+
57
+ ### Post
58
+ Post today's metrics summary to your GrowthForecast server(`collect` should be executed before `post`).
59
+ By default, a summary is posted to `http://#{host}/api/metrics/section/#{metrics_type}`.
60
+
61
+ ```
62
+ $ metrics_satellite --type post --host growthforecast.example.com
63
+ ```
64
+
65
+ ![](http://dl.dropbox.com/u/5978869/image/20130108_170744.png)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib/", __FILE__)
4
+ require "metrics_satellite"
5
+
6
+ MetricsSatellite::Runner.run
@@ -0,0 +1,12 @@
1
+ module MetricsSatellite
2
+ class BrakemanCollector < Collector
3
+ EXT = "html"
4
+
5
+ def collect
6
+ system(
7
+ "brakeman",
8
+ "--output", filepath
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ require "fileutils"
2
+
3
+ module MetricsSatellite
4
+ class Collector
5
+ include Filer
6
+
7
+ attr_reader :options
8
+
9
+ def self.underscore
10
+ to_s.underscore.split("/").last
11
+ end
12
+
13
+ def initialize(options = {})
14
+ @options = options
15
+ end
16
+
17
+ def run
18
+ create_directory
19
+ collect
20
+ end
21
+
22
+ def collect
23
+ raise "Implement #{self.class}#collect"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ module MetricsSatellite
2
+ class FlayCollector < Collector
3
+ def collect
4
+ system("flay", :out => file)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ module MetricsSatellite
2
+ class GuidelineCollector < Collector
3
+ def collect
4
+ system(
5
+ "guideline",
6
+ "--no-unused-method",
7
+ "--abc-complexity", options[:guideline_abc_complexity] || "15",
8
+ "--long-method", options[:guideline_long_method] || "30",
9
+ "--long-line", options[:guideline_long_line] || "128",
10
+ :out => file
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module MetricsSatellite
2
+ class HotspotsCollector < Collector
3
+ def collect
4
+ system(
5
+ "hotspots",
6
+ "--repository", repository_path,
7
+ "--cutoff", options[:hotspots_cutoff] || "10",
8
+ "--time", options[:hotspots_time] || "14",
9
+ :out => file
10
+ )
11
+ end
12
+
13
+ private
14
+
15
+ def repository_path
16
+ options[:git] || "."
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module MetricsSatellite
2
+ class RailsBestPracticesCollector < Collector
3
+ EXT = "html"
4
+
5
+ def collect
6
+ system(
7
+ "rails_best_practices",
8
+ "--format", "html",
9
+ "--output-file", filepath
10
+ )
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ require "date"
2
+ require "active_support/core_ext/string/inflections"
3
+
4
+ module MetricsSatellite
5
+ module Filer
6
+ EXT = "txt"
7
+
8
+ private
9
+
10
+ def pathname
11
+ Pathname.new(filepath)
12
+ end
13
+
14
+ def filepath
15
+ "#{directory}/#{filename}"
16
+ end
17
+
18
+ def directory
19
+ options[:startup_path].join(reports, name)
20
+ end
21
+
22
+ def create_directory
23
+ FileUtils.mkdir_p(directory)
24
+ end
25
+
26
+ def filename
27
+ "#{date}.#{ext}"
28
+ end
29
+
30
+ def date
31
+ Date.today.strftime("%Y-%m-%d")
32
+ end
33
+
34
+ def file
35
+ File.open(filepath, "w")
36
+ end
37
+
38
+ def name
39
+ tool_name.underscore
40
+ end
41
+
42
+ def tool_name
43
+ single_class_name.gsub(/Summarizer$|Collector$/, "")
44
+ end
45
+
46
+ def single_class_name
47
+ self.class.to_s.split("::").last
48
+ end
49
+
50
+ def ext
51
+ self.class::EXT
52
+ end
53
+
54
+ def reports
55
+ options[:reports] || "reports"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,99 @@
1
+ require "optparse"
2
+
3
+ module MetricsSatellite
4
+ class OptionParser < ::OptionParser
5
+ OPTIONS = [
6
+ "--type=", "(default: -) 'collect' or 'post'",
7
+ "--host=", "(default: -) GrowthForecast host to send report",
8
+ "--service=", "(default: metrics) GrowthForecast service name",
9
+ "--section=", "(default: section) GrowthForecast section name",
10
+ "--git=", "(default: ./) git repository directory",
11
+ "--app=", "(default: ./) application directory",
12
+ "--reports=", "(default: reports) collected reports directory",
13
+ "--guideline-abc-complexity=", "(default: 15) threshold of ABC complexity",
14
+ "--guideline-long-line=", "(default: 80) threshold of long line",
15
+ "--guideline-long-method=", "(default: 10) threshold of long method",
16
+ "--hotspots-cutoff=", "(default: 10) threshold of change count",
17
+ "--hotspots-time=", "(default: 14) time span of git log target",
18
+ "--no-brakeman", "(default: false) disable Brakeman",
19
+ "--no-flay", "(default: false) disable Flay",
20
+ "--no-guideline", "(default: false) disable Guideline",
21
+ "--no-hotspots", "(default: false) disable Hotspots",
22
+ "--no-rails-best-practices", "(default: false) disable RailsBestPractices",
23
+ ]
24
+
25
+ def self.parse!(argv)
26
+ new.parse!(argv)
27
+ end
28
+
29
+ def self.help
30
+ new.help
31
+ end
32
+
33
+ def initialize(*)
34
+ super
35
+ configure_options
36
+ end
37
+
38
+ def parse!(*)
39
+ super
40
+ options
41
+ end
42
+
43
+ def options
44
+ @options ||= {}
45
+ end
46
+
47
+ private
48
+
49
+ def configure_options
50
+ arguments.each do |argument|
51
+ on(argument.key, argument.description) do |value|
52
+ options[argument.to_sym] = value
53
+ end
54
+ end
55
+ end
56
+
57
+ def arguments
58
+ OPTIONS.each_slice(2).map do |key, description|
59
+ Argument.new(key, description)
60
+ end
61
+ end
62
+
63
+ class Argument
64
+ attr_reader :key, :description
65
+
66
+ def initialize(key, description)
67
+ @key = key
68
+ @description = description
69
+ end
70
+
71
+ def to_sym
72
+ str = @key
73
+ str = without_head_hyphen(str)
74
+ str = without_head_no(str)
75
+ str = without_last_equal(str)
76
+ str = underscored(str)
77
+ str.to_sym
78
+ end
79
+
80
+ private
81
+
82
+ def underscored(str)
83
+ str.gsub("-", "_")
84
+ end
85
+
86
+ def without_head_hyphen(str)
87
+ str.gsub(/^--/, "")
88
+ end
89
+
90
+ def without_head_no(str)
91
+ str.gsub(/^no-/, "")
92
+ end
93
+
94
+ def without_last_equal(str)
95
+ str.gsub(/=$/, "")
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,29 @@
1
+ require "rest_client"
2
+
3
+ module MetricsSatellite
4
+ class Reporter
5
+ attr_reader :host, :service, :section
6
+
7
+ def initialize(host, service, section)
8
+ @host = host
9
+ @service = service
10
+ @section = section
11
+ end
12
+
13
+ def report(summaries)
14
+ summaries.each do |key, count|
15
+ post(key, count)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def post(key, count)
22
+ RestClient.post(compose_url(key), :number => count)
23
+ end
24
+
25
+ def compose_url(graph)
26
+ "http://#{host}/api/#{service}/#{section}/#{graph}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,101 @@
1
+ require "pathname"
2
+
3
+ module MetricsSatellite
4
+ class Runner
5
+ attr_reader :options
6
+
7
+ def self.run
8
+ new.run
9
+ end
10
+
11
+ def initialize(argv = ARGV)
12
+ @options = OptionParser.parse!(argv).merge(:startup_path => startup_path)
13
+ end
14
+
15
+ def run
16
+ case type
17
+ when "collect"
18
+ collect_reports
19
+ when "post"
20
+ post_reports
21
+ else
22
+ exit
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def collect_reports
29
+ in_app_direcotry do
30
+ collectors.each do |klass|
31
+ klass.new(options).run
32
+ end
33
+ end
34
+ end
35
+
36
+ def post_reports
37
+ reporter.report(summaries)
38
+ end
39
+
40
+ def collectors
41
+ array = []
42
+ array << BrakemanCollector if options[:brakeman] != false
43
+ array << FlayCollector if options[:flay] != false
44
+ array << GuidelineCollector if options[:guideline] != false
45
+ array << HotspotsCollector if options[:hotspots] != false
46
+ array << RailsBestPracticesCollector if options[:rails_best_practices] != false
47
+ array
48
+ end
49
+
50
+ def summarizers
51
+ [
52
+ BrakemanSummarizer,
53
+ FlaySummarizer,
54
+ GuidelineSummarizer,
55
+ HotspotsSummarizer,
56
+ RailsBestPracticesSummarizer,
57
+ ]
58
+ end
59
+
60
+ def in_app_direcotry
61
+ Dir.chdir(app_path) { yield }
62
+ end
63
+
64
+ def app_path
65
+ options[:app] || "."
66
+ end
67
+
68
+ def exit
69
+ puts OptionParser.help
70
+ super
71
+ end
72
+
73
+ def summaries
74
+ summarizers.map {|klass| klass.summarize(options) }.inject({}, &:merge)
75
+ end
76
+
77
+ def reporter
78
+ Reporter.new(host, service, section)
79
+ end
80
+
81
+ def type
82
+ options[:type] || exit
83
+ end
84
+
85
+ def host
86
+ options[:host] || exit
87
+ end
88
+
89
+ def service
90
+ options[:service] || "metrics"
91
+ end
92
+
93
+ def section
94
+ options[:section] || "section"
95
+ end
96
+
97
+ def startup_path
98
+ Pathname.new(Dir.pwd)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,36 @@
1
+ require "nokogiri"
2
+
3
+ module MetricsSatellite
4
+ class BrakemanSummarizer < Summarizer
5
+ EXT = "html"
6
+
7
+ private
8
+
9
+ def create
10
+ { :count => count }
11
+ end
12
+
13
+ def count
14
+ count_node.text.strip.to_i
15
+ end
16
+
17
+ def count_node
18
+ count_node_parent.css("td")[1]
19
+ end
20
+
21
+ def count_node_parent
22
+ tree.css("#summary + table tr").detect do |tr|
23
+ td = tr.css("td")
24
+ td && td.text =~ /Security Warnings/
25
+ end
26
+ end
27
+
28
+ def tree
29
+ Nokogiri.HTML(content)
30
+ end
31
+
32
+ def content
33
+ pathname.read
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ module MetricsSatellite
2
+ class FlaySummarizer < Summarizer
3
+ private
4
+
5
+ def create
6
+ { :count => count }
7
+ end
8
+
9
+ def first_line
10
+ lines[0]
11
+ end
12
+
13
+ def count
14
+ first_line[/\d+$/].to_i
15
+ end
16
+
17
+ def lines
18
+ pathname.readlines
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module MetricsSatellite
2
+ class GuidelineSummarizer < Summarizer
3
+ private
4
+
5
+ def create
6
+ summarized_lines.inject({}) do |hash, line|
7
+ matched, name, count = *line.match(/(.+)Checker: (\d+)/)
8
+ if matched
9
+ hash.merge(name.underscore.to_sym => count.to_i)
10
+ else
11
+ hash
12
+ end
13
+ end
14
+ end
15
+
16
+ def summarized_lines
17
+ lines.reverse.take_while {|line| !line[/^$/] }.reverse
18
+ end
19
+
20
+ def lines
21
+ pathname.readlines
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module MetricsSatellite
2
+ class HotspotsSummarizer < Summarizer
3
+ private
4
+
5
+ def create
6
+ { :count => pathname.readlines.count }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ module MetricsSatellite
2
+ class RailsBestPracticesSummarizer < Summarizer
3
+ EXT = "html"
4
+
5
+ private
6
+
7
+ def create
8
+ { :count => count }
9
+ end
10
+
11
+ def count
12
+ matched, count_text = *count_node.text.match(/(\d+)/)
13
+ if matched
14
+ count_text.to_i
15
+ else
16
+ 0
17
+ end
18
+ end
19
+
20
+ def count_node
21
+ tree.css("body > h1 + p + p")[0]
22
+ end
23
+
24
+ def tree
25
+ Nokogiri.HTML(content)
26
+ end
27
+
28
+ def content
29
+ pathname.read
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ module MetricsSatellite
2
+ class Summarizer
3
+ include Filer
4
+
5
+ attr_reader :options
6
+
7
+ def self.summarize(options = {})
8
+ new(options).summarize
9
+ end
10
+
11
+ def initialize(options = {})
12
+ @options = options
13
+ end
14
+
15
+ def summarize
16
+ validate_report_existence
17
+ create_merged_summaries
18
+ end
19
+
20
+ private
21
+
22
+ def type
23
+ self.class.to_s.split("::").last.sub(/Summarizer$/, "").underscore
24
+ end
25
+
26
+ def create
27
+ raise "Implement #{self.class}#create"
28
+ end
29
+
30
+ def report_exist?
31
+ pathname.exist?
32
+ end
33
+
34
+ def create_merged_summaries
35
+ create.inject({}) do |hash, (key, value)|
36
+ hash.merge([type, key].join("_").to_sym => value)
37
+ end
38
+ end
39
+
40
+ def validate_report_existence
41
+ raise ReportNotFoundError, "Report for #{tool_name} is not found" unless report_exist?
42
+ end
43
+
44
+ class ReportNotFoundError < StandardError; end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module MetricsSatellite
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,17 @@
1
+ require "metrics_satellite/version"
2
+ require "metrics_satellite/option_parser"
3
+ require "metrics_satellite/runner"
4
+ require "metrics_satellite/filer"
5
+ require "metrics_satellite/reporter"
6
+ require "metrics_satellite/collectors/collector"
7
+ require "metrics_satellite/collectors/brakeman_collector"
8
+ require "metrics_satellite/collectors/flay_collector"
9
+ require "metrics_satellite/collectors/guideline_collector"
10
+ require "metrics_satellite/collectors/hotspots_collector"
11
+ require "metrics_satellite/collectors/rails_best_practices_collector"
12
+ require "metrics_satellite/summarizers/summarizer"
13
+ require "metrics_satellite/summarizers/brakeman_summarizer"
14
+ require "metrics_satellite/summarizers/flay_summarizer"
15
+ require "metrics_satellite/summarizers/guideline_summarizer"
16
+ require "metrics_satellite/summarizers/hotspots_summarizer"
17
+ require "metrics_satellite/summarizers/rails_best_practices_summarizer"
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "metrics_satellite/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "metrics_satellite"
7
+ gem.version = MetricsSatellite::VERSION
8
+ gem.authors = ["Ryo Nakamura"]
9
+ gem.email = ["r7kamura@gmail.com"]
10
+ gem.description = "MetricsSatellite collects your rails application metrics"
11
+ gem.summary = "Collect your rails application metrics"
12
+ gem.homepage = "https://github.com/r7kamura/metrics_satellite"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency "rest-client"
20
+ gem.add_dependency "nokogiri"
21
+ gem.add_dependency "activesupport"
22
+ gem.add_dependency "brakeman"
23
+ gem.add_dependency "flay"
24
+ gem.add_dependency "hotspots"
25
+ gem.add_dependency "rails_best_practices"
26
+ gem.add_dependency "rake"
27
+ gem.add_dependency "guideline", "~> 0.2.0"
28
+
29
+ gem.add_development_dependency "rspec", "2.12.0"
30
+ gem.add_development_dependency "simplecov"
31
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe Reporter do
5
+ let(:reporter) do
6
+ described_class.new(
7
+ "growthforecast.example.com",
8
+ "service",
9
+ "section"
10
+ )
11
+ end
12
+
13
+ describe "#report" do
14
+ let(:summaries) do
15
+ { :a => 1, :b => 2 }
16
+ end
17
+
18
+ it "sends request to server" do
19
+ RestClient.should_receive(:post).
20
+ with("http://growthforecast.example.com/api/service/section/a", :number => 1)
21
+ RestClient.should_receive(:post).
22
+ with("http://growthforecast.example.com/api/service/section/b", :number => 2)
23
+ reporter.report(summaries)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe Runner do
5
+ let(:runner) do
6
+ described_class.new(argv)
7
+ end
8
+
9
+ describe ".run" do
10
+ subject do
11
+ runner.run
12
+ end
13
+
14
+ context "when type is collect" do
15
+ let(:argv) do
16
+ %w[--type collect --host example.com]
17
+ end
18
+
19
+ let(:collectors) do
20
+ runner.send(:collectors)
21
+ end
22
+
23
+ it "call #run for each collector class" do
24
+ collectors.each do |collector|
25
+ collector.any_instance.should_receive(:run)
26
+ end
27
+ subject
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe BrakemanSummarizer do
5
+ let(:summarizer) do
6
+ described_class.new
7
+ end
8
+
9
+ describe "#create" do
10
+ subject do
11
+ summarizer.send(:create)
12
+ end
13
+
14
+ before do
15
+ summarizer.stub(:pathname => pathname)
16
+ end
17
+
18
+ let(:pathname) do
19
+ mock(:exist? => true, :read => content)
20
+ end
21
+
22
+ let(:content) do
23
+ <<-EOF
24
+ <!DOCTYPE HTML>
25
+ <html>
26
+ <head>
27
+ </head>
28
+ <body>
29
+ <h2 id="summary"></h2>
30
+ <table>
31
+ <tr>
32
+ <td>Scanned/Reported</td>
33
+ <td>total</td>
34
+ </tr>
35
+ <tr>
36
+ <td>Security Warnings</td>
37
+ <td>#{count}</td>
38
+ </tr>
39
+ </table>
40
+ </body>
41
+ </html>
42
+ EOF
43
+ end
44
+
45
+ let(:count) do
46
+ 100
47
+ end
48
+
49
+ it "creates summary of Brakeman" do
50
+ subject[:count].should == count
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe FlaySummarizer do
5
+ let(:summarizer) do
6
+ described_class.new
7
+ end
8
+
9
+ describe "#create" do
10
+ subject do
11
+ summarizer.send(:create)
12
+ end
13
+
14
+ before do
15
+ summarizer.stub(:pathname => pathname)
16
+ end
17
+
18
+ let(:pathname) do
19
+ mock(:readlines => lines, :exist? => true)
20
+ end
21
+
22
+ let(:lines) do
23
+ ["Total score (lower is better) = #{total_score}\n"]
24
+ end
25
+
26
+ let(:total_score) do
27
+ 100
28
+ end
29
+
30
+ it "creates summary of Flay" do
31
+ subject[:count].should == total_score
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe GuidelineSummarizer do
5
+ before do
6
+ summarizer.stub(:pathname => pathname, :lines => lines)
7
+ end
8
+
9
+ let(:summarizer) do
10
+ described_class.new
11
+ end
12
+
13
+ let(:lines) do
14
+ <<-EOF.each_line.map(&:strip)
15
+ lib/metrics_satellite.rb
16
+ 1: Line length 84 should be less than 80 characters
17
+
18
+ AbcComplexityChecker: 1
19
+ LongLineChecker: 2
20
+ LongMethodChecker: 3
21
+ EOF
22
+ end
23
+
24
+ let(:pathname) do
25
+ mock(:exist? => true)
26
+ end
27
+
28
+ describe "#create" do
29
+ subject do
30
+ summarizer.send(:create)
31
+ end
32
+
33
+ it "creates summary of Guideline" do
34
+ subject[:abc_complexity].should == 1
35
+ subject[:long_line].should == 2
36
+ subject[:long_method].should == 3
37
+ end
38
+ end
39
+
40
+ describe "#summarized_lines" do
41
+ subject do
42
+ summarizer.send(:summarized_lines)
43
+ end
44
+
45
+ it "extracts summarized lines from report" do
46
+ should == <<-EOF.each_line.map(&:strip)
47
+ AbcComplexityChecker: 1
48
+ LongLineChecker: 2
49
+ LongMethodChecker: 3
50
+ EOF
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe HotspotsSummarizer do
5
+ let(:summarizer) do
6
+ described_class.new
7
+ end
8
+
9
+ describe "#create" do
10
+ subject do
11
+ summarizer.send(:create)
12
+ end
13
+
14
+ before do
15
+ summarizer.stub(:pathname => pathname)
16
+ end
17
+
18
+ let(:pathname) do
19
+ mock(:readlines => lines, :exist? => true)
20
+ end
21
+
22
+ let(:lines) do
23
+ count.times.to_a
24
+ end
25
+
26
+ let(:count) do
27
+ 10
28
+ end
29
+
30
+ it "creates summary of Hotspots" do
31
+ subject[:count].should == count
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+
3
+ module MetricsSatellite
4
+ describe RailsBestPracticesSummarizer do
5
+ let(:summarizer) do
6
+ described_class.new
7
+ end
8
+
9
+ describe "#create" do
10
+ subject do
11
+ summarizer.send(:create)
12
+ end
13
+
14
+ before do
15
+ summarizer.stub(:pathname => pathname)
16
+ end
17
+
18
+ let(:pathname) do
19
+ mock(:exist? => true, :read => content)
20
+ end
21
+
22
+ context "when any warning is found" do
23
+ let(:content) do
24
+ <<-EOF
25
+ <!DOCTYPE HTML>
26
+ <html>
27
+ <head>
28
+ </head>
29
+ <body>
30
+ <h1></h1>
31
+ <p></p>
32
+ <p>Found #{count} warnings.</p>
33
+ </body>
34
+ </html>
35
+ EOF
36
+ end
37
+
38
+ let(:count) do
39
+ 100
40
+ end
41
+
42
+ it "creates summary of Brakeman" do
43
+ subject[:count].should == count
44
+ end
45
+ end
46
+
47
+ context "when any warning is not found" do
48
+ let(:content) do
49
+ <<-EOF
50
+ <!DOCTYPE HTML>
51
+ <html>
52
+ <head>
53
+ </head>
54
+ <body>
55
+ <h1></h1>
56
+ <p></p>
57
+ <p>No error found. Cool!</p>
58
+ </body>
59
+ </html>
60
+ EOF
61
+ end
62
+
63
+ it "creates summary of Brakeman with count as 0" do
64
+ subject[:count].should == 0
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ require "simplecov"
2
+ SimpleCov.start
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
5
+ require "metrics_satellite"
6
+
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
metadata ADDED
@@ -0,0 +1,263 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metrics_satellite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryo Nakamura
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: activesupport
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: brakeman
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: flay
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: hotspots
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rails_best_practices
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: guideline
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: 0.2.0
150
+ type: :runtime
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: 0.2.0
158
+ - !ruby/object:Gem::Dependency
159
+ name: rspec
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - '='
164
+ - !ruby/object:Gem::Version
165
+ version: 2.12.0
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - '='
172
+ - !ruby/object:Gem::Version
173
+ version: 2.12.0
174
+ - !ruby/object:Gem::Dependency
175
+ name: simplecov
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ description: MetricsSatellite collects your rails application metrics
191
+ email:
192
+ - r7kamura@gmail.com
193
+ executables:
194
+ - metrics_satellite
195
+ extensions: []
196
+ extra_rdoc_files: []
197
+ files:
198
+ - .gitignore
199
+ - Gemfile
200
+ - LICENSE.txt
201
+ - README.md
202
+ - Rakefile
203
+ - bin/metrics_satellite
204
+ - lib/metrics_satellite.rb
205
+ - lib/metrics_satellite/collectors/brakeman_collector.rb
206
+ - lib/metrics_satellite/collectors/collector.rb
207
+ - lib/metrics_satellite/collectors/flay_collector.rb
208
+ - lib/metrics_satellite/collectors/guideline_collector.rb
209
+ - lib/metrics_satellite/collectors/hotspots_collector.rb
210
+ - lib/metrics_satellite/collectors/rails_best_practices_collector.rb
211
+ - lib/metrics_satellite/filer.rb
212
+ - lib/metrics_satellite/option_parser.rb
213
+ - lib/metrics_satellite/reporter.rb
214
+ - lib/metrics_satellite/runner.rb
215
+ - lib/metrics_satellite/summarizers/brakeman_summarizer.rb
216
+ - lib/metrics_satellite/summarizers/flay_summarizer.rb
217
+ - lib/metrics_satellite/summarizers/guideline_summarizer.rb
218
+ - lib/metrics_satellite/summarizers/hotspots_summarizer.rb
219
+ - lib/metrics_satellite/summarizers/rails_best_practices_summarizer.rb
220
+ - lib/metrics_satellite/summarizers/summarizer.rb
221
+ - lib/metrics_satellite/version.rb
222
+ - metrics_satellite.gemspec
223
+ - spec/metrics_satellite/reporter_spec.rb
224
+ - spec/metrics_satellite/runner_spec.rb
225
+ - spec/metrics_satellite/summarizers/brakeman_summarizer_spec.rb
226
+ - spec/metrics_satellite/summarizers/flay_summarizer_spec.rb
227
+ - spec/metrics_satellite/summarizers/guideline_summarizer_spec.rb
228
+ - spec/metrics_satellite/summarizers/hotspots_summarizer_spec.rb
229
+ - spec/metrics_satellite/summarizers/rails_best_practices_summarizer_spec.rb
230
+ - spec/spec_helper.rb
231
+ homepage: https://github.com/r7kamura/metrics_satellite
232
+ licenses: []
233
+ post_install_message:
234
+ rdoc_options: []
235
+ require_paths:
236
+ - lib
237
+ required_ruby_version: !ruby/object:Gem::Requirement
238
+ none: false
239
+ requirements:
240
+ - - ! '>='
241
+ - !ruby/object:Gem::Version
242
+ version: '0'
243
+ required_rubygems_version: !ruby/object:Gem::Requirement
244
+ none: false
245
+ requirements:
246
+ - - ! '>='
247
+ - !ruby/object:Gem::Version
248
+ version: '0'
249
+ requirements: []
250
+ rubyforge_project:
251
+ rubygems_version: 1.8.24
252
+ signing_key:
253
+ specification_version: 3
254
+ summary: Collect your rails application metrics
255
+ test_files:
256
+ - spec/metrics_satellite/reporter_spec.rb
257
+ - spec/metrics_satellite/runner_spec.rb
258
+ - spec/metrics_satellite/summarizers/brakeman_summarizer_spec.rb
259
+ - spec/metrics_satellite/summarizers/flay_summarizer_spec.rb
260
+ - spec/metrics_satellite/summarizers/guideline_summarizer_spec.rb
261
+ - spec/metrics_satellite/summarizers/hotspots_summarizer_spec.rb
262
+ - spec/metrics_satellite/summarizers/rails_best_practices_summarizer_spec.rb
263
+ - spec/spec_helper.rb