appsignal_report 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d4d4507b1ca8ebdd01e7cb9f06ce189d3c93c7e8
4
+ data.tar.gz: bce40d5abece6bcb5be025ac195e12120112ee79
5
+ SHA512:
6
+ metadata.gz: dca3d06438a1bd3678f0ff2aedad71abf4b6fed262231c772cb1c431f29260e84133ec4433aa0f86d8a05141143b54f440d585380e6a43505a5351907f0f733c
7
+ data.tar.gz: 5109060c35dd4d591a4ed1bb575305687b35f71bda09d1da40f03ab1284235f6f4a853460fedb6a8de5489e9ad3f44342d2bfa0a2551c6d30f3f02ade3b5bc2e
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ### 0.1.0
4
+ _August 14th, 2017_
5
+
6
+ - ruby gem
7
+ - properly implemented weekly report
8
+ - optional app name parameter
9
+ - post to slack feature (replaces format)
10
+ - code structure improvement
11
+ - CI via Travis
12
+ - changelog, readme, minitest, gemfile
13
+
14
+ ### 0.1.0-beta.1
15
+ _August 7th, 2017_
16
+
17
+ - minimal working release (deploy report)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Daniel Sager
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # appsignal_report
2
+
3
+ `appsignal_report` is a gem that generates reports based on data obtained from
4
+ [Appsignal](https://www.appsignal.com), a tool for monitoring of Ruby and
5
+ Elixir applications.
6
+
7
+ ## Status
8
+
9
+ [![Build Status](https://travis-ci.org/dsager/appsignal_report.svg?branch=master)](https://travis-ci.org/dsager/appsignal_report)
10
+
11
+ ## Reports
12
+
13
+ Currently the gem supports two kinds of reports, a deploy report and a weekly
14
+ report.
15
+
16
+ ## Deploy Report
17
+
18
+ The deploy report pulls metrics for the time around the last deploy recorded on
19
+ AppSignal (1 hour before to 1 hour after). Based on these metrics it calculates
20
+ changes in response time, error rate and throughput, possibly caused by the
21
+ deploy. The 20 minutes around the deploy are ignored to account for timeouts or
22
+ slow requests caused by service restarts or cold caches.
23
+
24
+ This only works if you are using AppSignal's
25
+ [deploy markers](https://docs.appsignal.com/push-api/deploy-marker.html) to
26
+ record your deployments.
27
+
28
+ ### Usage
29
+
30
+ ```
31
+ $ gem install appsignal_report
32
+ $ APPSIGNAL_API_TOKEN=ABC123 appsignal_report_deploy -i XYZ456
33
+ {
34
+ "title": "AppSignal Deploy Report",
35
+ "last_deploy_time": "2017-08-10 09:47:52 UTC",
36
+ "before": {
37
+ "data_points": 62,
38
+ "error_rate": 0.4675038958657989,
39
+ "response_time": 94.9387856438841,
40
+ "hourly_throughput": 32727
41
+ },
42
+ "after": {
43
+ "data_points": 62,
44
+ "error_rate": 0.0733371596199222,
45
+ "response_time": 56.71109484008057,
46
+ "hourly_throughput": 31362
47
+ },
48
+ "data_samples_from": "2017-08-10 08:47:00 UTC",
49
+ "data_samples_to": "2017-08-10 10:48:00 UTC",
50
+ "diff": {
51
+ "error_rate": -0.39416673624587667,
52
+ "error_rate_pct": -0.8431303775894644,
53
+ "response_time": -38.22769080380353,
54
+ "response_time_pct": -0.40265620151489834,
55
+ "hourly_throughput": -1365,
56
+ "hourly_throughput_pct": -0.041708680905674214
57
+ },
58
+ "messages": {
59
+ "info": "The deploy finished at 2017-08-10 09:47:52 UTC",
60
+ "error_rate": "The error rate decreased by 0.39% (from 0.47% to 0.07%, that is a change of -84.31%).",
61
+ "response_time": "The response time decreased by 38.23ms (from 94.94ms to 56.71ms, that is a change of -40.27%).",
62
+ "hourly_throughput": "The hourly throughput decreased by 1365.0 req/h (from 32727.0 req/h to 31362.0 req/h, that is a change of -4.17%)."
63
+ }
64
+ }
65
+ ```
66
+
67
+ ## Weekly Report
68
+
69
+ The weekly report pulls metrics for the last two weeks. Based on these metrics
70
+ it calculates changes in response time, error rate and throughput, comparing one
71
+ week to the other.
72
+
73
+ ### Usage
74
+
75
+ ```
76
+ $ gem install appsignal_report
77
+ $ APPSIGNAL_API_TOKEN=ABC123 appsignal_report_weekly -i XYZ456
78
+ {
79
+ "title": "AppSignal Weekly Report",
80
+ "now": "2017-08-14 13:19:15 UTC",
81
+ "one_week_ago": "2017-08-07 13:19:15 UTC",
82
+ "two_weeks_ago": "2017-07-31 13:19:15 UTC",
83
+ "before": {
84
+ "data_points": 168,
85
+ "error_rate": 0.19637939102939866,
86
+ "response_time": 74.6427894180237,
87
+ "hourly_throughput": 34611.166666666664
88
+ },
89
+ "after": {
90
+ "data_points": 168,
91
+ "error_rate": 0.06227341986188213,
92
+ "response_time": 61.364840452820985,
93
+ "hourly_throughput": 30819.684523809523
94
+ },
95
+ "data_samples_from": "2017-07-31 14:00:00 UTC",
96
+ "data_samples_to": "2017-08-14 13:00:00 UTC",
97
+ "diff": {
98
+ "error_rate": -0.13410597116751655,
99
+ "error_rate_pct": -0.6828922855119783,
100
+ "response_time": -13.277948965202711,
101
+ "response_time_pct": -0.17788655901967856,
102
+ "hourly_throughput": -3791.4821428571413,
103
+ "hourly_throughput_pct": -0.1095450546169726
104
+ },
105
+ "messages": {
106
+ "info": "Comparing the weeks 2017-07-31-2017-08-07 and 2017-08-07-2017-08-14.",
107
+ "error_rate": "The error rate decreased by 0.13% (from 0.2% to 0.06%, that is a change of -68.29%).",
108
+ "response_time": "The response time decreased by 13.28ms (from 74.64ms to 61.36ms, that is a change of -17.79%).",
109
+ "hourly_throughput": "The hourly throughput decreased by 3791.48 req/h (from 34611.17 req/h to 30819.68 req/h, that is a change of -10.95%)."
110
+ }
111
+ }
112
+ ```
113
+
114
+ ## FAQ
115
+
116
+ ### Where do I get an AppSignal API Token?
117
+
118
+ Every AppSignal user automatically has an API token, which is displayed at the
119
+ bottom of [your personal settings page](https://appsignal.com/users/edit).
120
+
121
+ ### Where do I find the AppSignal application ID?
122
+
123
+ The application ID is part of any appsignal.com URL, as soon as you open an
124
+ application. If you look at the example URL
125
+ `appsignal.com/devex/sites/XYZ456/web/exceptions`, the application ID is
126
+ `XYZ456`.
127
+
128
+ ## Maintainer
129
+
130
+ [Daniel Sager](https://github.com/dsager)
131
+
132
+ ## Contributing
133
+
134
+ - Fork this repository
135
+ - Implement your feature or fix including Tests
136
+ - Update the [change log](CHANGELOG.md)
137
+ - Commit your changes with a meaningful commit message
138
+ - Create a pull request
139
+
140
+ Thank you!
141
+
142
+ See the
143
+ [list of contributors](https://github.com/dsager/appsignal-report/contributors).
144
+
145
+ ### Tests
146
+
147
+ For the whole test suite, run `rake test`.
148
+ For individual tests, run
149
+ `ruby -Ilib:spec spec/appsignal_report/version_spec.rb`.
150
+
151
+ ## License
152
+
153
+ MIT License, see the [license file](LICENSE).
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ #
5
+ # Script to generate a report based on the last Appsignal deploy marker.
6
+ #
7
+ # The script will obtain the time of the last deploy from AppSignal and then
8
+ # pull metrics for the time around that deploy (1 hour before to 1 hour after).
9
+ # Based on these metrics it will calculate changes in response time, error rate
10
+ # and throughput, possibly caused by the deploy.
11
+ # The 20 minutes around the deploy are ignored to account for errors or slow
12
+ # requests caused by service restarts or cold caches.
13
+ #
14
+ # Pull up the help message to learn about the usage of this script:
15
+ #
16
+ # ./bin/appsignal_report_deploy --help
17
+ #
18
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
19
+
20
+ require 'appsignal_report'
21
+ require 'optparse'
22
+
23
+ options = { slack_webhook: nil, app_id: nil, app_name: nil }
24
+ parser = OptionParser.new do |parser|
25
+ parser.banner =
26
+ 'Usage: APPSIGNAL_API_TOKEN=XXX ./bin/appsignal_report_deploy [options]'
27
+ parser.separator ''
28
+ parser.separator 'Specific options:'
29
+ parser.on('-i ID',
30
+ '--app-id ID',
31
+ String,
32
+ 'Specify Appsignal App Id') do |id|
33
+ options[:app_id] = id
34
+ end
35
+ parser.on('-n NAME',
36
+ '--app-name NAME',
37
+ String,
38
+ 'Specify a name for the Appsignal App') do |name|
39
+ options[:app_name] = name
40
+ end
41
+ parser.on('-s WEBHOOK_URL',
42
+ '--slack WEBHOOK_URL',
43
+ String,
44
+ 'Post the report to a Slack Webhook') do |url|
45
+ options[:slack_webhook] = url
46
+ end
47
+ parser.separator ''
48
+ parser.separator 'Common options:'
49
+ parser.on_tail('-h', '--help', 'Show this message') do
50
+ puts parser
51
+ exit
52
+ end
53
+ end
54
+ parser.parse!
55
+
56
+ report = AppsignalReport::DeployReport.new(
57
+ api_token: ENV['APPSIGNAL_API_TOKEN'],
58
+ app_id: options[:app_id],
59
+ app_name: options[:app_name]
60
+ )
61
+
62
+ report.generate
63
+
64
+ unless options[:slack_webhook].nil?
65
+ message = AppsignalReport::SlackMessage.new(
66
+ report: report,
67
+ webhook_url: options[:slack_webhook]
68
+ )
69
+ puts message.post
70
+ else
71
+ puts report.report.to_json
72
+ end
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ #
5
+ # Script to generate a report based on Appsignal data over the last two weeks.
6
+ #
7
+ # The script will pull metrics for the last two weeks.
8
+ # Based on these metrics it will calculate changes in response time, error rate
9
+ # and throughput, comparing one week to the other.
10
+ #
11
+ # Pull up the help message to learn about the usage of this script:
12
+ #
13
+ # ./bin/appsignal_report_weekly --help
14
+ #
15
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
16
+
17
+ require 'appsignal_report'
18
+ require 'optparse'
19
+
20
+ options = { slack_webhook: nil, app_id: nil, app_name: nil }
21
+ parser = OptionParser.new do |parser|
22
+ parser.banner =
23
+ 'Usage: APPSIGNAL_API_TOKEN=XXX ./bin/appsignal_report_weekly [options]'
24
+ parser.separator ''
25
+ parser.separator 'Specific options:'
26
+ parser.on('-i ID',
27
+ '--app-id ID',
28
+ String,
29
+ 'Specify Appsignal App Id') do |id|
30
+ options[:app_id] = id
31
+ end
32
+ parser.on('-n NAME',
33
+ '--app-name NAME',
34
+ String,
35
+ 'Specify a name for the Appsignal App') do |name|
36
+ options[:app_name] = name
37
+ end
38
+ parser.on('-s WEBHOOK_URL',
39
+ '--slack WEBHOOK_URL',
40
+ String,
41
+ 'Post the report to a Slack Webhook') do |url|
42
+ options[:slack_webhook] = url
43
+ end
44
+ parser.separator ''
45
+ parser.separator 'Common options:'
46
+ parser.on_tail('-h', '--help', 'Show this message') do
47
+ puts parser
48
+ exit
49
+ end
50
+ end
51
+ parser.parse!
52
+
53
+ report = AppsignalReport::WeeklyReport.new(
54
+ api_token: ENV['APPSIGNAL_API_TOKEN'],
55
+ app_id: options[:app_id],
56
+ app_name: options[:app_name]
57
+ )
58
+
59
+ report.generate
60
+
61
+ unless options[:slack_webhook].nil?
62
+ message = AppsignalReport::SlackMessage.new(
63
+ report: report,
64
+ webhook_url: options[:slack_webhook]
65
+ )
66
+ puts message.post
67
+ else
68
+ puts report.report.to_json
69
+ end
@@ -0,0 +1,160 @@
1
+ module AppsignalReport
2
+ #
3
+ # Report base class, defines the general flow and helper methods used by the
4
+ # specific report classes.
5
+ #
6
+ class BaseReport
7
+ attr_reader :api_token, :app_id, :app_name, :report
8
+
9
+ # @param [String] api_token API token, find it here:
10
+ # <https://appsignal.com/users/edit>
11
+ # @param [String] app_id Application ID, visible in the URL when your
12
+ # application is opened on Appsignal.com
13
+ # @param [String] app_name Application Name, used for the report title
14
+ def initialize(api_token:, app_id:, app_name: nil)
15
+ @api_token = api_token
16
+ @app_id = app_id
17
+ @app_name = app_name
18
+ @report = {}
19
+ end
20
+
21
+ # To be defined by subclass, should set the instance var @report.
22
+ # @return [Hash]
23
+ def generate
24
+ raise NotImplementedError
25
+ end
26
+
27
+ # @return [String]
28
+ def title
29
+ [
30
+ 'AppSignal',
31
+ self.class.name.split('::').last.split(/(?=[A-Z])/).join(' '),
32
+ !app_name.nil? ? "(#{app_name})" : nil
33
+ ].compact.join(' ')
34
+ end
35
+
36
+ private
37
+
38
+ def process_metrics
39
+ api_response = perform_api_request(metrics_uri)
40
+ data = balance_samples(gather_samples(api_response[:data]))
41
+ %i(before after).each do |key|
42
+ @report[key] = {
43
+ data_points: data[key].size,
44
+ error_rate: get_average(data[key], :ex_rate),
45
+ response_time: get_average(data[key], :mean),
46
+ hourly_throughput: get_average(data[key], :count),
47
+ }
48
+ end
49
+ @report.merge!(
50
+ data_samples_from: Time.at(data[:before].first[:timestamp]).utc,
51
+ data_samples_to: Time.at(data[:after].last[:timestamp]).utc,
52
+ diff: generate_diff,
53
+ )
54
+ @report[:messages] = generate_messages
55
+ report
56
+ end
57
+
58
+ def generate_messages
59
+ {
60
+ info: info_message,
61
+ error_rate: metric_message(:error_rate, '%'),
62
+ response_time: metric_message(:response_time, 'ms'),
63
+ hourly_throughput: metric_message(:hourly_throughput, ' req/h'),
64
+ }
65
+ end
66
+
67
+ def info_message; end
68
+
69
+ def metric_message(field, unit = '')
70
+ <<-txt.split.join(' ')
71
+ The #{field.to_s.sub('_', ' ')}
72
+ #{report[:diff][field].positive? ? 'increased' : 'decreased'}
73
+ by #{report[:diff][field].abs.round(2)}#{unit}
74
+ (from #{report[:before][field].round(2)}#{unit}
75
+ to #{report[:after][field].round(2)}#{unit}, that is a change of
76
+ #{(report[:diff][:"#{field}_pct"] * 100).round(2)}%).
77
+ txt
78
+ end
79
+
80
+ # @param [Array[Hash]] data
81
+ # @param [Symbol] field
82
+ # @return [Float]
83
+ def get_average(data, field)
84
+ values = data.map { |row| row[field] }
85
+ values.inject(0, :+).fdiv(values.size)
86
+ end
87
+
88
+ def generate_diff
89
+ {
90
+ error_rate: abs_diff(:error_rate),
91
+ error_rate_pct: pct_diff(:error_rate),
92
+ response_time: abs_diff(:response_time),
93
+ response_time_pct: pct_diff(:response_time),
94
+ hourly_throughput: abs_diff(:hourly_throughput),
95
+ hourly_throughput_pct: pct_diff(:hourly_throughput),
96
+ }
97
+ end
98
+
99
+ def abs_diff(key)
100
+ report[:after][key] - report[:before][key]
101
+ end
102
+
103
+ def pct_diff(key)
104
+ abs_diff(key).fdiv(report[:before][key])
105
+ end
106
+
107
+ def gather_samples(samples)
108
+ split_timestamp = report_split_time.to_time.to_i
109
+ samples.each_with_object(before: [], after: []) do |row, hash|
110
+ next if timestamp_in_grace_period?(row[:timestamp])
111
+ if row[:timestamp] < split_timestamp
112
+ hash[:before] << row
113
+ else
114
+ hash[:after] << row
115
+ end
116
+ end
117
+ end
118
+
119
+ def balance_samples(samples)
120
+ sample_size = [samples[:before].size, samples[:after].size].min
121
+ samples[:before] = samples[:before].last(sample_size)
122
+ samples[:after] = samples[:after].first(sample_size)
123
+ samples
124
+ end
125
+
126
+ def report_split_time
127
+ raise NotImplementedError
128
+ end
129
+
130
+ def timestamp_in_grace_period?(_)
131
+ false
132
+ end
133
+
134
+ # @return [String]
135
+ def base_uri
136
+ "https://appsignal.com/api/#{app_id}"
137
+ end
138
+
139
+ # @return [URI]
140
+ def metrics_uri
141
+ raise NotImplementedError
142
+ end
143
+
144
+ # @return [Hash]
145
+ def perform_api_request(uri)
146
+ http = Net::HTTP.new(uri.host, uri.port)
147
+ http.use_ssl = true
148
+
149
+ response = http.request(
150
+ Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json')
151
+ )
152
+ if response.is_a? Net::HTTPSuccess
153
+ JSON.parse(response.body, symbolize_names: true)
154
+ else
155
+ raise StandardError,
156
+ "[API ERROR] #{response.code} - #{response.message}"
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,64 @@
1
+ module AppsignalReport
2
+ #
3
+ # Deploy Report
4
+ #
5
+ # Compare metrics of one hour before and after the last deploy:
6
+ # - Error Rate
7
+ # - Response Time
8
+ # - Throughput
9
+ #
10
+ class DeployReport < BaseReport
11
+ def generate
12
+ @report = {
13
+ title: title,
14
+ last_deploy_time: Time.parse(last_deploy[:created_at]).utc,
15
+ }
16
+ process_metrics
17
+ end
18
+
19
+ private
20
+
21
+ # @return [String]
22
+ def info_message
23
+ "The deploy finished at #{report[:last_deploy_time]}"
24
+ end
25
+
26
+ # @return [Time|nil]
27
+ def report_split_time
28
+ report[:last_deploy_time]
29
+ end
30
+
31
+ # @return [Boolean]
32
+ def timestamp_in_grace_period?(timestamp)
33
+ grace_period = 10 * 60
34
+ (timestamp - report[:last_deploy_time].to_time.to_i).abs < grace_period
35
+ end
36
+
37
+ # @return [URI]
38
+ def metrics_uri
39
+ one_hour = 3600 # seconds
40
+ query = URI.encode_www_form(
41
+ token: api_token,
42
+ from: (report[:last_deploy_time] - one_hour).iso8601,
43
+ to: (report[:last_deploy_time] + one_hour).iso8601,
44
+ 'fields[]': %i(mean count ex_rate)
45
+ )
46
+ URI("#{base_uri}/graphs.json?#{query}")
47
+ end
48
+
49
+ # @return [Hash]
50
+ def last_deploy
51
+ @last_deploy = perform_api_request(last_deploy_marker_uri)[:markers].first
52
+ end
53
+
54
+ # @return [URI]
55
+ def last_deploy_marker_uri
56
+ query = URI.encode_www_form(
57
+ token: api_token,
58
+ kind: :deploy,
59
+ limit: 1
60
+ )
61
+ URI("#{base_uri}/markers.json?#{query}")
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,61 @@
1
+ module AppsignalReport
2
+ class SlackMessage
3
+ attr_reader :report, :webhook_uri
4
+
5
+ def initialize(report:, webhook_url:)
6
+ @report = report
7
+ @webhook_uri = URI(webhook_url)
8
+ end
9
+
10
+ # @return [Hash]
11
+ def post
12
+ http = Net::HTTP.new(webhook_uri.host, webhook_uri.port)
13
+ http.use_ssl = true
14
+
15
+ post =
16
+ Net::HTTP::Post.new(webhook_uri, 'Content-Type' => 'application/json')
17
+ post.body = payload.to_json
18
+ response = http.request(post)
19
+
20
+ unless response.is_a? Net::HTTPSuccess
21
+ raise StandardError,
22
+ "[API ERROR] #{response.code} - #{response.message}"
23
+ end
24
+ end
25
+
26
+ # @return [Hash]
27
+ def payload
28
+ {
29
+ text: report.title,
30
+ attachments: attachment_messages.map { |message| { text: message } },
31
+ }
32
+ end
33
+
34
+ def attachment_messages
35
+ [
36
+ ":information_source: #{report.report[:messages][:info]}",
37
+ "#{error_rate_icon} #{report.report[:messages][:error_rate]}",
38
+ "#{response_time_icon} #{report.report[:messages][:response_time]}",
39
+ "#{throughput_icon} #{report.report[:messages][:hourly_throughput]}",
40
+ ]
41
+ end
42
+
43
+ def error_rate_icon
44
+ report.report[:diff][:error_rate].negative? ? ':+1:' : ':-1:'
45
+ end
46
+
47
+ def response_time_icon
48
+ report.report[:diff][:response_time].negative? ? ':+1:' : ':-1:'
49
+ end
50
+
51
+ def throughput_icon
52
+ up_down =
53
+ if report.report[:diff][:hourly_throughput].negative?
54
+ 'downwards'
55
+ else
56
+ 'upwards'
57
+ end
58
+ ":chart_with_#{up_down}_trend:"
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module AppsignalReport
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,44 @@
1
+ module AppsignalReport
2
+ #
3
+ # Weekly Report
4
+ #
5
+ # Compare metrics of the last week with the one before that:
6
+ # - Error Rate
7
+ # - Response Time
8
+ # - Throughput
9
+ #
10
+ class WeeklyReport < BaseReport
11
+ def generate
12
+ @report = {
13
+ title: title,
14
+ now: Time.now.utc,
15
+ one_week_ago: (Time.now - (3600 * 24 * 7)).utc,
16
+ two_weeks_ago: (Time.now - (3600 * 24 * 14)).utc,
17
+ }
18
+ process_metrics
19
+ end
20
+
21
+ private
22
+
23
+ # @return [String]
24
+ def info_message
25
+ week_1 = "#{report[:two_weeks_ago].to_date}-#{report[:one_week_ago].to_date}"
26
+ week_2 = "#{report[:one_week_ago].to_date}-#{report[:now].to_date}"
27
+ "Comparing the weeks #{week_1} and #{week_2}."
28
+ end
29
+
30
+ def report_split_time
31
+ report[:one_week_ago]
32
+ end
33
+
34
+ # @return [URI]
35
+ def metrics_uri
36
+ query = URI.encode_www_form(
37
+ token: api_token,
38
+ from: report[:two_weeks_ago].iso8601,
39
+ 'fields[]': %i(mean count ex_rate)
40
+ )
41
+ URI("#{base_uri}/graphs.json?#{query}")
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'time'
5
+
6
+ require_relative 'appsignal_report/version'
7
+ require_relative 'appsignal_report/base_report'
8
+ require_relative 'appsignal_report/weekly_report'
9
+ require_relative 'appsignal_report/deploy_report'
10
+ require_relative 'appsignal_report/slack_message'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appsignal_report
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Sager
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-14 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Toolkit to pull some Appsignal metrics and generate reports
42
+ email: software@sager1.de
43
+ executables:
44
+ - appsignal_report_deploy
45
+ - appsignal_report_weekly
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - CHANGELOG.md
50
+ - LICENSE
51
+ - README.md
52
+ - bin/appsignal_report_deploy
53
+ - bin/appsignal_report_weekly
54
+ - lib/appsignal_report.rb
55
+ - lib/appsignal_report/base_report.rb
56
+ - lib/appsignal_report/deploy_report.rb
57
+ - lib/appsignal_report/slack_message.rb
58
+ - lib/appsignal_report/version.rb
59
+ - lib/appsignal_report/weekly_report.rb
60
+ homepage: https://github.com/dsager/appsignal_report
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.5.2
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Useful reports around your AppSignal metrics
84
+ test_files: []