alacrity-rails 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d1deb83151619090305c93c971b07df5b0d2145
4
+ data.tar.gz: ba981ea6ea88638b648bfcc5a9707b32ae1b500c
5
+ SHA512:
6
+ metadata.gz: df2ef698abaf8b5ecabd244df82f438593134f95226bea65cf109fecb2b6013ac831d81b48ffdbdc45529bb6147fc951511be5644953089d4719cd1ad3d9eee4
7
+ data.tar.gz: 66861c9368055e355c1ff16239771226f05215b7af098c23c2c528efdca48e9805895df8109adce30d711ffd9603ddee639d7878c955f191e1112e9d6598990a
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Copyright 2016 Alacrity, LLC
@@ -0,0 +1,34 @@
1
+ # Overview
2
+
3
+ ## Alacrity Rails
4
+
5
+ The alacrity-rails gem collects runtime data from your Ruby on Rails app.
6
+
7
+ ## Compatibility
8
+
9
+ The alacrity-rails gem officially supports Ruby 2.0+.
10
+
11
+ It will work automatically with Rails 4 and up.
12
+
13
+ ## Installation
14
+
15
+ 1. Sign up for an account on https://www.alacrityapp.com
16
+ 2. Add the `alacrity-rails` gem to your `Gemfile`
17
+
18
+ ```
19
+ gem 'alacrity-rails', group: :production
20
+ ```
21
+
22
+ 3. Set the ALACRITY_API_TOKEN in your app's environment
23
+ 4. Deploy with the gem installed
24
+ 5. You'll begin seeing data on https://alacrityapp.com shortly after your site receives traffic.
25
+
26
+ ## Server Configuration Overrides
27
+
28
+ ### ALACRITY_API_TOKEN
29
+
30
+ You can find this on the settings page for your app on https://alacrityapp.com
31
+
32
+ ### ALACRITY_ENVIRONMENT
33
+
34
+ By default Alacrity will use `Rails.env` to determine the server environment. You can override this to any string value (like `staging`).
@@ -0,0 +1,12 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+
4
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
5
+ require "appraisal/task"
6
+ Appraisal::Task.new
7
+ task default: :appraisal
8
+ else
9
+ require "rspec/core/rake_task"
10
+ RSpec::Core::RakeTask.new
11
+ task default: :spec
12
+ end
@@ -0,0 +1,22 @@
1
+ if defined?(Rake)
2
+ require 'rake'
3
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each { |rake| load rake }
4
+ end
5
+
6
+ module AlacrityRails
7
+ autoload :Config, 'alacrity-rails/config'
8
+ autoload :ConnectionTester, 'alacrity-rails/connection_tester'
9
+ autoload :Client, 'alacrity-rails/client'
10
+ autoload :Middleware, 'alacrity-rails/middleware'
11
+ autoload :ServerConfig, 'alacrity-rails/server_config'
12
+ autoload :VERSION, 'alacrity-rails/version'
13
+
14
+ module Transaction
15
+ autoload :Base, 'alacrity-rails/transaction/base'
16
+ autoload :ConnectionTest, 'alacrity-rails/transaction/connection_test'
17
+ autoload :ServerStartup, 'alacrity-rails/transaction/server_startup'
18
+ autoload :WebTransaction, 'alacrity-rails/transaction/web_transaction'
19
+ end
20
+ end
21
+
22
+ require 'alacrity-rails/railtie'
@@ -0,0 +1,50 @@
1
+ module AlacrityRails
2
+ class Client
3
+
4
+ def self.open_transaction(env)
5
+ new_transaction!(env)
6
+ end
7
+
8
+ def self.store_request_metrics(started_at, ended_at, data)
9
+ transaction.store_request_metrics(started_at, ended_at, data)
10
+ end
11
+
12
+ def self.store_database_metrics(started_at, ended_at, data)
13
+ transaction.store_database_metrics(started_at, ended_at, data)
14
+ end
15
+
16
+ def self.close_transaction!
17
+ this_transaction = transaction
18
+ Thread.new { transmit(this_transaction) }
19
+ ensure
20
+ cleanup
21
+ end
22
+
23
+ def self.log_server_startup
24
+ Thread.new {
25
+ transmit(AlacrityRails::Transaction::ServerStartup.new)
26
+ }
27
+ end
28
+
29
+ def self.transaction
30
+ Thread.current[:alacrity_transaction]
31
+ end
32
+
33
+ def self.cleanup
34
+ Thread.current[:alacrity_transaction] = nil
35
+ end
36
+
37
+ def self.transmit(transactable)
38
+ Net::HTTP.start(*transactable.net_http_start_arguments) do |http|
39
+ http.request(transactable.post_request)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def self.new_transaction!(env)
46
+ Thread.current[:alacrity_transaction] = Transaction::WebTransaction.new(env)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ module AlacrityRails::Config
2
+ extend self
3
+
4
+ def self.api_token
5
+ @api_token ||= ENV['ALACRITY_API_TOKEN']
6
+ end
7
+ attr_writer :api_token
8
+
9
+ def self.enabled?
10
+ api_token.present?
11
+ end
12
+
13
+ def self.collector_host
14
+ @collector_host ||= ENV['ALACRITY_COLLECTOR_HOST'] || 'https://collector-api.alacrityapp.com'
15
+ end
16
+ end
@@ -0,0 +1,55 @@
1
+ module AlacrityRails
2
+ class ConnectionTester
3
+ def self.run; new.run end
4
+
5
+ def run
6
+ if Config.api_token.blank?
7
+ puts missing_api_token_message
8
+ else
9
+ response = Client.transmit(Transaction::ConnectionTest.new)
10
+
11
+ if response.code == '200'
12
+ puts success_message
13
+ else
14
+ puts bad_response_message(JSON.parse(response.body)['message'])
15
+ end
16
+ end
17
+
18
+ puts assistance_message
19
+ end
20
+
21
+ private
22
+
23
+ def missing_api_token_message
24
+ %<
25
+ Your API token could not be found in the configuration. You can find it on https://alacrityapp.com.
26
+
27
+ Then add it to your server's environment as `ALACRITY_API_TOKEN`
28
+
29
+ OR
30
+
31
+ Set it manually with an initializer (config/alacrity.rb)
32
+ AlacrityRails::Config.api_token = 'your token'>
33
+ end
34
+
35
+ def bad_response_message(server_message)
36
+ %<
37
+ Oh no! Its seems like we have a problem!
38
+
39
+ #{server_message}>
40
+ end
41
+
42
+ def success_message
43
+ %<
44
+ Everything looks good!
45
+
46
+ You should see data on https://alacrityapp.com shortly after your app receives traffic.>
47
+ end
48
+
49
+ def assistance_message
50
+ %<
51
+ If you need assistance or have any questions, send an email to support@alacrityapp.com or tweet @alacrityapp and we'll help you out!
52
+ >
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,10 @@
1
+ module AlacrityRails
2
+ class Middleware < Struct.new(:app)
3
+ def call(env)
4
+ Client.open_transaction(env)
5
+ response = app.call(env)
6
+ Client.close_transaction!
7
+ response
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module AlacrityRails
2
+ class Railtie < ::Rails::Railtie
3
+ initializer 'alacrity' do |config|
4
+ if Config.enabled?
5
+ Client.log_server_startup
6
+
7
+ config.middleware.insert_before 0, AlacrityRails::Middleware
8
+ end
9
+
10
+ ActiveSupport::Notifications.subscribe 'sql.active_record' do |name, started, finished, unique_id, data|
11
+ AlacrityRails::Client.store_database_metrics(started, finished, data)
12
+ end
13
+
14
+ ActiveSupport::Notifications.subscribe 'process_action.action_controller' do |name, started, finished, unique_id, data|
15
+ AlacrityRails::Client.store_request_metrics(started, finished, data)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module AlacrityRails::ServerConfig
2
+ extend self
3
+
4
+ def rails_version
5
+ @rails_version ||= Rails.version
6
+ end
7
+
8
+ def environment
9
+ @environment ||= ENV['ALACRITY_ENVIRONMENT'] || Rails.env
10
+ end
11
+
12
+ def client_identifier
13
+ @client_identifier ||= "alacrity-rails-#{AlacrityRails::VERSION}"
14
+ end
15
+
16
+ def as_json
17
+ {
18
+ client_identifier: client_identifier,
19
+ command: File.split($0).last,
20
+ environment: environment,
21
+ rails_version: rails_version,
22
+ ruby_version: RUBY_VERSION
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module AlacrityRails::Transaction
2
+ class Base
3
+ def post_request
4
+ Net::HTTP::Post.new(endpoint, {
5
+ "Authorization" => authorization_header_value,
6
+ "Content-Type" => "application/json"
7
+ }).tap { |request| request.body = to_json }
8
+ end
9
+
10
+ def self.net_http_start_arguments
11
+ @net_http_start_arguments ||= [endpoint.host, endpoint.port, use_ssl: endpoint.scheme == 'https']
12
+ end
13
+ def net_http_start_arguments; self.class.net_http_start_arguments end
14
+
15
+ def self.endpoint
16
+ raise 'Must implement'
17
+ end
18
+ def endpoint; self.class.endpoint end
19
+
20
+ def self.authorization_header_value
21
+ @authorization_header_value ||= ActionController::HttpAuthentication::Token.encode_credentials(AlacrityRails::Config.api_token)
22
+ end
23
+ def authorization_header_value; self.class.authorization_header_value end
24
+
25
+ def to_json
26
+ @to_json ||= super.to_json
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ module AlacrityRails::Transaction
2
+ class ConnectionTest < Base
3
+ def self.endpoint
4
+ @endpoint ||= URI("#{AlacrityRails::Config.collector_host}/v1/connection-test")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module AlacrityRails::Transaction
2
+ class ServerStartup < Base
3
+ def as_json(*args)
4
+ AlacrityRails::ServerConfig.as_json
5
+ end
6
+
7
+ def self.endpoint
8
+ @endpoint ||= URI("#{AlacrityRails::Config.collector_host}/v1/server-startups")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ module AlacrityRails::Transaction
2
+ class WebTransaction < Base
3
+ attr_accessor :url, :middleware_started_at, :controller, :action, :format,
4
+ :method, :status, :view_runtime, :db_runtime, :framework_elapsed
5
+
6
+ def initialize(env={})
7
+ self.middleware_started_at = Time.now
8
+ self.url = ["#{env['rack.url_scheme']}://", env['HTTP_HOST'], env['REQUEST_PATH']].compact.join
9
+ end
10
+
11
+ def store_database_metrics(started_at, finished_at, data)
12
+ sql_queries << {
13
+ statement_elapsed: ((finished_at - started_at) * 1000).to_i,
14
+ name: data[:name],
15
+ sql: data[:sql]
16
+ }
17
+ end
18
+
19
+ def store_request_metrics(started_at, finished_at, data)
20
+ self.framework_elapsed = ((finished_at - started_at) * 1000).to_i
21
+ self.controller = data[:controller]
22
+ self.action = data[:action]
23
+ self.format = data[:format]
24
+ self.method = data[:method]
25
+ self.status = data[:status]
26
+ self.view_runtime = data[:view_runtime].try(:to_i)
27
+ self.db_runtime = data[:db_runtime].try(:to_i)
28
+ end
29
+
30
+ def as_json(*args)
31
+ {
32
+ environment: AlacrityRails::ServerConfig.environment,
33
+ url: url,
34
+ controller: controller,
35
+ action: action,
36
+ middleware_elapsed: ((Time.now - middleware_started_at) * 1000).to_i,
37
+ framework_elapsed: framework_elapsed,
38
+ format: format,
39
+ method: method,
40
+ status: status,
41
+ view_runtime: view_runtime,
42
+ db_runtime: db_runtime,
43
+ sql_queries: sql_queries
44
+ }
45
+ end
46
+
47
+ def self.endpoint
48
+ @endpoint ||= URI("#{AlacrityRails::Config.collector_host}/v1/web-transactions")
49
+ end
50
+
51
+ def sql_queries
52
+ @sql_queries ||= []
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module AlacrityRails
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,8 @@
1
+ namespace :alacrity do
2
+
3
+ desc "Verifies your app's ability to communicate with Alacrity"
4
+ task :test_connection => :environment do
5
+ AlacrityRails::ConnectionTester.run
6
+ end
7
+
8
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alacrity-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alacrity, LLC
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ description: Rails Agent for the Alacrity Application Health Platform
28
+ email:
29
+ - support@alacrityapp.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.markdown
36
+ - Rakefile
37
+ - lib/alacrity-rails.rb
38
+ - lib/alacrity-rails/client.rb
39
+ - lib/alacrity-rails/config.rb
40
+ - lib/alacrity-rails/connection_tester.rb
41
+ - lib/alacrity-rails/middleware.rb
42
+ - lib/alacrity-rails/railtie.rb
43
+ - lib/alacrity-rails/server_config.rb
44
+ - lib/alacrity-rails/transaction/base.rb
45
+ - lib/alacrity-rails/transaction/connection_test.rb
46
+ - lib/alacrity-rails/transaction/server_startup.rb
47
+ - lib/alacrity-rails/transaction/web_transaction.rb
48
+ - lib/alacrity-rails/version.rb
49
+ - lib/tasks/test_connection.rake
50
+ homepage: https://www.alacrityapp.com
51
+ licenses:
52
+ - GPL
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 2.5.1
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Rails Agent for the Alacrity Application Health Platform
74
+ test_files: []