appsignal 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/.rvmrc +1 -0
- data/.travis.yml +30 -0
- data/Gemfile +3 -0
- data/LICENCE +20 -0
- data/README.md +48 -0
- data/Rakefile +52 -0
- data/appsignal.gemspec +33 -0
- data/bin/appsignal +13 -0
- data/config/appsignal.yml +8 -0
- data/gemfiles/3.0.gemfile +16 -0
- data/gemfiles/3.1.gemfile +16 -0
- data/gemfiles/3.2.gemfile +16 -0
- data/gemfiles/edge.gemfile +16 -0
- data/lib/appsignal.rb +45 -0
- data/lib/appsignal/agent.rb +104 -0
- data/lib/appsignal/auth_check.rb +19 -0
- data/lib/appsignal/capistrano.rb +41 -0
- data/lib/appsignal/cli.rb +118 -0
- data/lib/appsignal/config.rb +30 -0
- data/lib/appsignal/exception_notification.rb +25 -0
- data/lib/appsignal/marker.rb +35 -0
- data/lib/appsignal/middleware.rb +30 -0
- data/lib/appsignal/railtie.rb +19 -0
- data/lib/appsignal/transaction.rb +77 -0
- data/lib/appsignal/transaction/faulty_request_formatter.rb +30 -0
- data/lib/appsignal/transaction/params_sanitizer.rb +36 -0
- data/lib/appsignal/transaction/regular_request_formatter.rb +11 -0
- data/lib/appsignal/transaction/slow_request_formatter.rb +34 -0
- data/lib/appsignal/transaction/transaction_formatter.rb +93 -0
- data/lib/appsignal/transmitter.rb +53 -0
- data/lib/appsignal/version.rb +3 -0
- data/lib/generators/appsignal/USAGE +8 -0
- data/lib/generators/appsignal/appsignal_generator.rb +70 -0
- data/lib/generators/appsignal/templates/appsignal.yml +4 -0
- data/log/.gitkeep +0 -0
- data/resources/cacert.pem +3849 -0
- data/spec/appsignal/agent_spec.rb +259 -0
- data/spec/appsignal/auth_check_spec.rb +36 -0
- data/spec/appsignal/capistrano_spec.rb +81 -0
- data/spec/appsignal/cli_spec.rb +124 -0
- data/spec/appsignal/config_spec.rb +40 -0
- data/spec/appsignal/exception_notification_spec.rb +12 -0
- data/spec/appsignal/inactive_railtie_spec.rb +30 -0
- data/spec/appsignal/marker_spec.rb +83 -0
- data/spec/appsignal/middleware_spec.rb +73 -0
- data/spec/appsignal/railtie_spec.rb +54 -0
- data/spec/appsignal/transaction/faulty_request_formatter_spec.rb +49 -0
- data/spec/appsignal/transaction/params_sanitizer_spec.rb +68 -0
- data/spec/appsignal/transaction/regular_request_formatter_spec.rb +14 -0
- data/spec/appsignal/transaction/slow_request_formatter_spec.rb +76 -0
- data/spec/appsignal/transaction/transaction_formatter_spec.rb +178 -0
- data/spec/appsignal/transaction_spec.rb +191 -0
- data/spec/appsignal/transmitter_spec.rb +64 -0
- data/spec/appsignal_spec.rb +66 -0
- data/spec/generators/appsignal/appsignal_generator_spec.rb +222 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/support/delegate_matcher.rb +39 -0
- metadata +247 -0
data/.gitignore
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
*.rbc
|
2
|
+
*.sassc
|
3
|
+
.sass-cache
|
4
|
+
capybara-*.html
|
5
|
+
.rspec
|
6
|
+
/log/*.log
|
7
|
+
/.bundle
|
8
|
+
/vendor/bundle
|
9
|
+
/tmp/*
|
10
|
+
/db/*.sqlite3
|
11
|
+
/public/system/*
|
12
|
+
/coverage/
|
13
|
+
/spec/tmp/*
|
14
|
+
**.orig
|
15
|
+
rerun.txt
|
16
|
+
pickle-email-*.html
|
17
|
+
*.gem
|
18
|
+
Gemfile.lock
|
19
|
+
.DS_Store
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3
|
data/.travis.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
rvm:
|
4
|
+
# - 1.9.2
|
5
|
+
- 1.9.3
|
6
|
+
- 1.8.7
|
7
|
+
- ree
|
8
|
+
# - ruby-head
|
9
|
+
# - jruby-18mode
|
10
|
+
- jruby-19mode
|
11
|
+
# - jruby-head
|
12
|
+
|
13
|
+
gemfile:
|
14
|
+
- gemfiles/3.0.gemfile
|
15
|
+
- gemfiles/3.1.gemfile
|
16
|
+
- gemfiles/3.2.gemfile
|
17
|
+
- gemfiles/edge.gemfile
|
18
|
+
|
19
|
+
matrix:
|
20
|
+
exclude:
|
21
|
+
- rvm: 1.8.7
|
22
|
+
gemfile: gemfiles/edge.gemfile
|
23
|
+
allow_failures:
|
24
|
+
- gemfile: gemfiles/edge.gemfile
|
25
|
+
|
26
|
+
script: RAILS_ENV=test bundle exec rspec spec
|
27
|
+
|
28
|
+
notifications:
|
29
|
+
campfire: 80beans:d43f43244263cafb088182aa79e7d96419da0372@188927
|
30
|
+
email: false
|
data/Gemfile
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 80beans
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
appsignal
|
2
|
+
=================
|
3
|
+
|
4
|
+
|
5
|
+
## Pull requests / issues
|
6
|
+
|
7
|
+
New features should be made in an issue or pullrequest. Title format is as follows:
|
8
|
+
|
9
|
+
|
10
|
+
name [request_count]
|
11
|
+
|
12
|
+
example
|
13
|
+
|
14
|
+
tagging [2]
|
15
|
+
|
16
|
+
## Event payload sanitizer
|
17
|
+
Appsignal logs Rails
|
18
|
+
[ActiveSupport::Notification](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html)-events
|
19
|
+
to appsignal.com over SSL. These events contain basic metadata such as a name
|
20
|
+
and timestamps, and additional 'payload' log data. By default,
|
21
|
+
appsignal will transmit all payload data. If you want to restrict the amount of
|
22
|
+
payload data that gets sent to <https://appsignal.com>, you can define your own
|
23
|
+
event payload sanitizer in `config/environment/my_env.rb`. The
|
24
|
+
`event_payload_sanitizer` needs to be a callable object that returns a
|
25
|
+
JSON-serializable hash.
|
26
|
+
|
27
|
+
### Examples
|
28
|
+
|
29
|
+
#### Pass through the entire payload unmodified (default)
|
30
|
+
```ruby
|
31
|
+
Appsignal.event_payload_sanitizer = proc { |event| event.payload }
|
32
|
+
```
|
33
|
+
|
34
|
+
#### Delete the entire event payload
|
35
|
+
```ruby
|
36
|
+
Appsignal.event_payload_sanitizer = proc { {} }
|
37
|
+
```
|
38
|
+
|
39
|
+
#### Conditional modification of the payload
|
40
|
+
```ruby
|
41
|
+
Appsignal.event_payload_sanitizer = proc do |event|
|
42
|
+
if event.name == 'interesting'
|
43
|
+
event.payload
|
44
|
+
else
|
45
|
+
{}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
task :publish do
|
2
|
+
NAME = 'appsignal'
|
3
|
+
VERSION_FILE = 'lib/appsignal/version.rb'
|
4
|
+
|
5
|
+
raise '$EDITOR should be set' unless ENV['EDITOR']
|
6
|
+
|
7
|
+
def build_and_push_gem
|
8
|
+
puts '# Building gem'
|
9
|
+
puts `gem build #{NAME}.gemspec`
|
10
|
+
puts '# Publishing Gem'
|
11
|
+
puts `gem push #{NAME}-#{gem_version}.gem`
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_and_push_tag
|
15
|
+
begin
|
16
|
+
puts `git commit -am 'Bump to #{version} [ci skip]'`
|
17
|
+
puts "# Creating tag #{version}"
|
18
|
+
puts `git tag #{version}`
|
19
|
+
puts `git push origin #{version}`
|
20
|
+
puts `git push origin master`
|
21
|
+
rescue
|
22
|
+
raise "Tag: '#{version}' already exists"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def changes
|
27
|
+
git_status_to_array(`git status -s -u `)
|
28
|
+
end
|
29
|
+
|
30
|
+
def gem_version
|
31
|
+
Appsignal::VERSION
|
32
|
+
end
|
33
|
+
|
34
|
+
def version
|
35
|
+
@version ||= 'v' << gem_version
|
36
|
+
end
|
37
|
+
|
38
|
+
def git_status_to_array(changes)
|
39
|
+
changes.split("\n").each { |change| change.gsub!(/^.. /,'') }
|
40
|
+
end
|
41
|
+
|
42
|
+
raise "Branch should hold no uncommitted file change)" unless changes.empty?
|
43
|
+
|
44
|
+
system("$EDITOR #{VERSION_FILE}")
|
45
|
+
if changes.member?(VERSION_FILE)
|
46
|
+
load File.expand_path(VERSION_FILE)
|
47
|
+
build_and_push_gem
|
48
|
+
create_and_push_tag
|
49
|
+
else
|
50
|
+
raise "Actually change the version in: #{VERSION_FILE}"
|
51
|
+
end
|
52
|
+
end
|
data/appsignal.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/appsignal/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = [
|
6
|
+
'Robert Beekman',
|
7
|
+
'Steven Weller',
|
8
|
+
'Thijs Cadier',
|
9
|
+
'Ron Cadier',
|
10
|
+
'Jacob Vosmaer'
|
11
|
+
]
|
12
|
+
gem.email = ['contact@appsignal.com']
|
13
|
+
gem.description = 'The official appsignal.com gem'
|
14
|
+
gem.summary = 'Logs performance and exception data from your app to'\
|
15
|
+
'appsignal.com'
|
16
|
+
gem.homepage = 'http://github.com/80beans/appsignal'
|
17
|
+
|
18
|
+
gem.files = `git ls-files`.split($\)
|
19
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
21
|
+
gem.name = 'appsignal'
|
22
|
+
gem.require_paths = ['lib']
|
23
|
+
gem.version = Appsignal::VERSION
|
24
|
+
|
25
|
+
gem.add_dependency 'rails', '~>3'
|
26
|
+
gem.add_dependency 'rake'
|
27
|
+
gem.add_dependency 'json'
|
28
|
+
gem.add_dependency 'rack'
|
29
|
+
|
30
|
+
gem.add_development_dependency 'rspec'
|
31
|
+
gem.add_development_dependency 'capistrano'
|
32
|
+
gem.add_development_dependency 'generator_spec'
|
33
|
+
end
|
data/bin/appsignal
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..','lib'))
|
4
|
+
require 'appsignal/cli'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Appsignal::CLI.run
|
8
|
+
rescue => e
|
9
|
+
raise e if $DEBUG
|
10
|
+
STDERR.puts e.message
|
11
|
+
STDERR.puts e.backtrace.join("\n")
|
12
|
+
exit 1
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
source :rubygems
|
3
|
+
|
4
|
+
gem 'rails', :git => 'git://github.com/rails/rails.git'
|
5
|
+
gem 'rspec'
|
6
|
+
gem 'rake'
|
7
|
+
gem 'json'
|
8
|
+
|
9
|
+
group :development, :test do
|
10
|
+
gem 'capistrano'
|
11
|
+
gem 'generator_spec'
|
12
|
+
end
|
13
|
+
|
14
|
+
platforms :jruby do
|
15
|
+
gem 'jruby-openssl'
|
16
|
+
end
|
data/lib/appsignal.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
raise 'This appsignal gem only works with rails' unless defined?(Rails)
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class << self
|
5
|
+
attr_accessor :subscriber, :event_payload_sanitizer
|
6
|
+
|
7
|
+
def active?
|
8
|
+
config && config[:active] == true
|
9
|
+
end
|
10
|
+
|
11
|
+
def logger
|
12
|
+
@logger ||= Logger.new("#{Rails.root}/log/appsignal.log").tap do |l|
|
13
|
+
l.level = Logger::INFO
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def transactions
|
18
|
+
@transactions ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def agent
|
22
|
+
@agent ||= Appsignal::Agent.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def config
|
26
|
+
@config ||= Appsignal::Config.new(Rails.root, Rails.env).load
|
27
|
+
end
|
28
|
+
|
29
|
+
def event_payload_sanitizer
|
30
|
+
@event_payload_sanitizer ||= proc { |event| event.payload }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'appsignal/cli'
|
36
|
+
require 'appsignal/config'
|
37
|
+
require 'appsignal/transmitter'
|
38
|
+
require 'appsignal/agent'
|
39
|
+
require 'appsignal/marker'
|
40
|
+
require 'appsignal/middleware'
|
41
|
+
require 'appsignal/transaction'
|
42
|
+
require 'appsignal/exception_notification'
|
43
|
+
require 'appsignal/auth_check'
|
44
|
+
require 'appsignal/version'
|
45
|
+
require 'appsignal/railtie'
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class Agent
|
3
|
+
attr_reader :queue, :active, :sleep_time, :slowest_transactions, :transmitter
|
4
|
+
ACTION = 'log_entries'
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
return unless Appsignal.active?
|
8
|
+
@sleep_time = 60.0
|
9
|
+
@slowest_transactions = {}
|
10
|
+
@queue = []
|
11
|
+
@retry_request = true
|
12
|
+
@thread = Thread.new do
|
13
|
+
while true do
|
14
|
+
send_queue if @queue.any?
|
15
|
+
sleep @sleep_time
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@transmitter = Transmitter.new(
|
19
|
+
Appsignal.config[:endpoint],
|
20
|
+
ACTION,
|
21
|
+
Appsignal.config[:api_key]
|
22
|
+
)
|
23
|
+
Appsignal.logger.info 'Started the Appsignal agent'
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_to_queue(transaction)
|
27
|
+
if !transaction.exception? && transaction.action
|
28
|
+
current_slowest_transaction = @slowest_transactions[transaction.action]
|
29
|
+
if current_slowest_transaction
|
30
|
+
if current_slowest_transaction.process_action_event.duration <
|
31
|
+
transaction.process_action_event.duration
|
32
|
+
current_slowest_transaction.clear_payload_and_events!
|
33
|
+
@slowest_transactions[transaction.action] = transaction
|
34
|
+
else
|
35
|
+
transaction.clear_payload_and_events!
|
36
|
+
end
|
37
|
+
else
|
38
|
+
@slowest_transactions[transaction.action] = transaction
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@queue << transaction
|
42
|
+
end
|
43
|
+
|
44
|
+
def send_queue
|
45
|
+
Appsignal.logger.debug "Sending queue"
|
46
|
+
begin
|
47
|
+
handle_result transmitter.transmit(queue.map(&:to_hash))
|
48
|
+
rescue Exception => ex
|
49
|
+
Appsignal.logger.error "Exception while communicating with AppSignal: #{ex}"
|
50
|
+
handle_result nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_result(code)
|
55
|
+
Appsignal.logger.debug "Queue sent, response code: #{code}"
|
56
|
+
case code.to_i
|
57
|
+
when 200
|
58
|
+
good_response
|
59
|
+
when 420 # Enhance Your Calm
|
60
|
+
good_response
|
61
|
+
@sleep_time = @sleep_time * 1.5
|
62
|
+
when 413 # Request Entity Too Large
|
63
|
+
good_response
|
64
|
+
@sleep_time = @sleep_time / 1.5
|
65
|
+
when 429
|
66
|
+
Appsignal.logger.error "Too many requests sent, disengaging the agent"
|
67
|
+
stop_logging
|
68
|
+
when 406
|
69
|
+
Appsignal.logger.error "Your appsignal gem cannot communicate with the API anymore, please upgrade. Disengaging the agent"
|
70
|
+
stop_logging
|
71
|
+
when 402
|
72
|
+
Appsignal.logger.error "Payment required, disengaging the agent"
|
73
|
+
stop_logging
|
74
|
+
when 401
|
75
|
+
Appsignal.logger.error "API token cannot be authorized, disengaging the agent"
|
76
|
+
stop_logging
|
77
|
+
else
|
78
|
+
retry_once
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
protected
|
83
|
+
|
84
|
+
def good_response
|
85
|
+
@queue = []
|
86
|
+
@slowest_transactions = {}
|
87
|
+
@retry_request = true
|
88
|
+
end
|
89
|
+
|
90
|
+
def retry_once
|
91
|
+
if @retry_request
|
92
|
+
@retry_request = false
|
93
|
+
else
|
94
|
+
@retry_request = true
|
95
|
+
@queue = []
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def stop_logging
|
100
|
+
ActiveSupport::Notifications.unsubscribe(Appsignal.subscriber)
|
101
|
+
Thread.kill(@thread)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|