mashape-analytics 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e507b18ab91cf466429b73696d8870399718405
4
+ data.tar.gz: 84a0ff103e263238b9666266ee15711c98b8b9f6
5
+ SHA512:
6
+ metadata.gz: bf23a510a58e286407907dbc4c69562503afd900eba40b0a090779759732177e031f6794501756b8c72a003db2ba8721a6513d86ee054ddadc0f1d6c5330fbeb
7
+ data.tar.gz: 4c4c68ae3a0e35367ddc06d63d1b7f83cc34d1aaf0bad0920eecefd3e2d25e62b51d1ce9cb4f88a989d2bf19f412c9efb9a57b4b375af9e8b5b65810727c76e6
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
@@ -0,0 +1,13 @@
1
+ # http://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ indent_style = space
6
+ indent_size = 2
7
+ end_of_line = lf
8
+ charset = utf-8
9
+ trim_trailing_whitespace = true
10
+ insert_final_newline = true
11
+
12
+ [*.md]
13
+ trim_trailing_whitespace = false
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rbczmq', '~> 1.7', '>= 1.7.8'
4
+
5
+ group :development do
6
+ gem 'minitest', '~> 5.5'
7
+ gem 'shoulda', '>= 0'
8
+ gem 'bundler', '~> 1.0'
9
+ gem 'jeweler', '~> 2.0', '>= 2.0.1'
10
+ gem 'simplecov', '>= 0'
11
+
12
+ # gem 'byebug' # for debugging
13
+
14
+ gem 'rails', '~> 4.1'
15
+ gem 'sinatra', '~> 1.4'
16
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Mashape Inc. (https://www.mashape.com/)
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.
@@ -0,0 +1,61 @@
1
+ # Mashape Analytics Ruby Agent
2
+
3
+ > for more information on Mashape Analytics, please visit [apianalytics.com](https://www.apianalytics.com)
4
+
5
+ ## Installation
6
+
7
+
8
+ ```sh
9
+ gem 'mashape-analytics'
10
+ bundle install
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Ruby on Rails
16
+
17
+ Open your `config/environment.rb` file, and within the `Rails::Initializer.run` block, add the middleware as below:
18
+
19
+ ```ruby
20
+ require 'mashape-analytics'
21
+
22
+ Rails::Initializer.run do |config|
23
+ config.middleware.use MashapeAnalytics::Frameworks::Rails, service_token: 'SERVICE_TOKEN', environment: 'production'
24
+ end
25
+ ```
26
+
27
+ *In rails 4, put the `config.middleware.use` line in the `config/application.rb` file.*
28
+
29
+
30
+ ### Sinatra
31
+
32
+ Register the middleware. Then activate it.
33
+
34
+ ```ruby
35
+ # myapp.rb
36
+ require 'sinatra'
37
+ require 'mashape-analytics'
38
+
39
+ register MashapeAnalytics::Frameworks::Sinatra
40
+
41
+ mashapeAnalytics! 'SERVICE_TOKEN', environment: 'production'
42
+ ```
43
+
44
+
45
+ ### Rack
46
+
47
+ Add the middleware.
48
+
49
+ ```ruby
50
+ require 'rack'
51
+ require 'mashape-analytics'
52
+
53
+ use MashapeAnalytics::Frameworks::Rack, service_token: 'SERVICE_TOKEN', environment: 'production'
54
+ ```
55
+
56
+
57
+ ## Copyright and License
58
+
59
+ Copyright Mashape Inc, 2015.
60
+
61
+ Licensed under [the MIT License](https://github.com/mashape/analytics-agent-ruby/blob/master/LICENSE)
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "apianalytics"
18
+ gem.homepage = "http://github.com/Mashape/analytics-agent-ruby"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Ruby agent for Mashape API Analytics}
21
+ gem.description = %Q{The ruby agent reports API traffic to http://apianalytics.com}
22
+ gem.email = "kennethkl@gmail.com"
23
+ gem.authors = ["Kenneth Lee"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['test'].execute
39
+ end
40
+
41
+ task :default => :test
42
+
43
+ require 'rdoc/task'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "apianalytics #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,11 @@
1
+ module MashapeAnalytics
2
+ module Message
3
+ end
4
+
5
+ module Frameworks
6
+ end
7
+ end
8
+
9
+ require 'mashape-analytics/capture'
10
+ require 'mashape-analytics/message'
11
+ require 'mashape-analytics/frameworks'
@@ -0,0 +1,76 @@
1
+ require 'mashape-analytics/utils'
2
+
3
+ module MashapeAnalytics
4
+ class Capture
5
+ require 'rbczmq'
6
+
7
+ @@zmq_ctx = ZMQ::Context.new
8
+ @zmq_push = nil
9
+ @connected = false
10
+ @options = {
11
+ host: 'tcp://socket.analytics.mashape.com:5500'
12
+ }
13
+ @thread = nil
14
+
15
+ @@queue = Utils::QueueWithTimeout.new
16
+
17
+ def self.start
18
+ return unless @thread == nil
19
+
20
+ @thread = Thread.new do
21
+ # Connect
22
+ @zmq_push = @@zmq_ctx.socket(:PUSH)
23
+ @zmq_push.connect(@options[:host])
24
+ @connected = true
25
+
26
+ # Send messages
27
+ while @connected
28
+ begin
29
+ alf = @@queue.pop_with_timeout(1) # 1s timeout
30
+ @zmq_push.send 'alf_1.0.0 ' << alf.to_s
31
+ rescue => ex
32
+ # TODO log debug
33
+ end
34
+ end
35
+
36
+ # Disconnect
37
+ @zmq_push.close
38
+
39
+ # Clean up
40
+ @zmq_push = nil
41
+ @connected = false
42
+ @thread = nil
43
+ end
44
+ end
45
+
46
+ ##
47
+ # Send immediately
48
+ ##
49
+ def self.record!(alf)
50
+ if not @connected
51
+ Capture.start
52
+ end
53
+
54
+ @@queue << alf
55
+ end
56
+
57
+ ##
58
+ # Force disconnect
59
+ ##
60
+ def self.disconnect
61
+ return unless @connected
62
+
63
+ @connected = false
64
+ @thread.join
65
+ end
66
+
67
+ def self.context
68
+ @@zmq_ctx
69
+ end
70
+
71
+ def self.setOptions(options)
72
+ @options.merge! options
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+
2
+ # == Rack Hook =============================================================
3
+ if (defined?(Rack))
4
+ require 'mashape-analytics/frameworks/rack'
5
+ end
6
+
7
+ # == Sinatra Hook ==========================================================
8
+ if (defined?(Sinatra))
9
+ require 'mashape-analytics/frameworks/sinatra'
10
+ end
11
+
12
+ # == Rails Hook ============================================================
13
+
14
+ if (defined?(Rails))
15
+ require 'mashape-analytics/frameworks/rails'
16
+ end
17
+
18
+
19
+ module MashapeAnalytics::Frameworks
20
+ end
@@ -0,0 +1,201 @@
1
+ require 'mashape-analytics/capture'
2
+ require 'time'
3
+ require 'socket'
4
+ require 'rack/utils'
5
+
6
+ def status_code(status)
7
+ Rack::Utils::HTTP_STATUS_CODES[status] || ''
8
+ end
9
+
10
+ def header_hash(headers)
11
+ Rack::Utils::HeaderHash.new.merge(headers)
12
+ end
13
+
14
+ module MashapeAnalytics::Frameworks
15
+ class Rack
16
+
17
+ def initialize(app, options = {})
18
+ @app = app
19
+ @service_token = options[:service_token]
20
+ @environment = options[:environment] || ''
21
+ @send_body = options[:send_body] || false
22
+ host = options[:host] || 'socket.analytics.mashape.com:5500'
23
+
24
+ MashapeAnalytics::Capture.setOptions(host: 'tcp://' + host)
25
+ end
26
+
27
+ def call(env)
28
+ startedDateTime = Time.now
29
+ status, headers, body = @app.call(env)
30
+
31
+ if body.respond_to? :to_str
32
+ body = [body.to_str]
33
+ elsif body.respond_to?(:body)
34
+ body = [body.body]
35
+ elsif body.respond_to?(:each)
36
+ # do nothing
37
+ else
38
+ raise TypeError, "stringable or iterable required"
39
+ end
40
+
41
+ record_alf startedDateTime, env, {
42
+ :status => status,
43
+ :headers => header_hash(headers),
44
+ :body => body
45
+ }
46
+
47
+ [status, headers, body]
48
+ end
49
+
50
+ protected
51
+ def host(request)
52
+ if forwarded = request['HTTP_X_FORWARDED_HOST']
53
+ forwarded.split(/,\s?/).last
54
+ elsif (request['rack.url_scheme'] == 'http' and request['SERVER_PORT'] == '80') or (request['rack.url_scheme'] == 'https' and request['SERVER_PORT'] == '443')
55
+ request['HTTP_HOST'] || "#{request['SERVER_NAME'] || request['SERVER_ADDR']}"
56
+ else
57
+ request['HTTP_HOST'] || "#{request['SERVER_NAME'] || request['SERVER_ADDR']}:#{request['SERVER_PORT']}"
58
+ end
59
+ end
60
+
61
+ def url(request)
62
+ query_string = ''
63
+ if request['QUERY_STRING'] != '' and request['QUERY_STRING'] != nil
64
+ query_string = '?' + request['QUERY_STRING']
65
+ end
66
+
67
+ "#{request['PATH_INFO']}#{query_string}"
68
+ end
69
+
70
+ def absolute_url(request)
71
+ "#{request['rack.url_scheme']}://#{host(request)}#{url(request)}"
72
+ end
73
+
74
+ def request_headers(request)
75
+ request.select {|k,v| k.start_with? 'HTTP_'}
76
+ .map { |k,v| {name: k.sub(/^HTTP_/, '').sub(/_/, '-'), value: v} }
77
+ end
78
+
79
+ def request_header_size(request)
80
+ # {METHOD} {URL} HTTP/1.1\r\n = 12 extra characters for space between method and url, and ` HTTP/1.1\r\n`
81
+ first_line = request['REQUEST_METHOD'].length + url(request).length + 12
82
+
83
+ # {KEY}: {VALUE}\n\r = 4 extra characters for `: ` and `\n\r` minus `HTTP_` in the KEY is -1
84
+ header_fields = request.select { |k,v| k.start_with? 'HTTP_' }
85
+ .map { |k,v| k.length + v.bytesize - 1 }
86
+ .inject(0) { |sum,v| sum + v }
87
+
88
+ last_line = 2 # /r/n
89
+
90
+ first_line + header_fields + last_line
91
+ end
92
+
93
+ def request_query_string(request)
94
+ request['QUERY_STRING'].split('&')
95
+ .map do |q|
96
+ parts = q.split('=')
97
+ {name: parts.first, value: parts.length > 1 ? parts.last : nil }
98
+ end
99
+ end
100
+
101
+ def request_content_size(request)
102
+ if request['HTTP_CONTENT_LENGTH']
103
+ request['HTTP_CONTENT_LENGTH'].to_i
104
+ else
105
+ request['rack.input'].size
106
+ end
107
+ end
108
+
109
+ def response_headers(response)
110
+ response[:headers].map { |k,v| {name: k, value: v} }
111
+ end
112
+
113
+ def response_headers_size(response)
114
+ # HTTP/1.1 {STATUS} {STATUS_TEXT} = 10 extra characters
115
+ first_line = response[:status].to_s.length + status_code(response[:status]).length + 10
116
+
117
+ # {KEY}: {VALUE}\n\r
118
+ header_fields = response[:headers].map { |k,v| k.length + v.bytesize + 4 }
119
+ .inject(0) { |sum,v| sum + v }
120
+
121
+ return first_line + header_fields
122
+ end
123
+
124
+ def response_content_size(response)
125
+ if response[:headers]['Content-Length']
126
+ response[:headers]['Content-Length'].to_i
127
+ else
128
+ response[:body].inject(0) { |sum, b| sum + b.bytesize }
129
+ end
130
+ end
131
+
132
+ def record_alf(startedDateTime, request, response)
133
+ time = Time.now - startedDateTime
134
+ alf = MashapeAnalytics::Message::Alf.new @service_token, @environment
135
+
136
+ req_headers_size = request_header_size(request)
137
+ req_content_size = request_content_size(request)
138
+
139
+ res_headers_size = response_headers_size(response)
140
+ res_content_size = response_content_size(response)
141
+
142
+ entry = {
143
+ startedDateTime: startedDateTime.iso8601,
144
+ serverIpAddress: Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address,
145
+ time: (time * 1000).to_i,
146
+ request: {
147
+ method: request['REQUEST_METHOD'],
148
+ url: absolute_url(request),
149
+ httpVersion: 'HTTP/1.1', # not available, default http/1.1
150
+ cookies: [],
151
+ queryString: request_query_string(request),
152
+ headers: request_headers(request),
153
+ headersSize: req_headers_size,
154
+ content: {
155
+ size: req_content_size,
156
+ mimeType: request['HTTP_CONTENT_TYPE'] || 'application/octet-stream'
157
+ },
158
+ bodySize: req_headers_size + req_content_size
159
+ },
160
+ response: {
161
+ status: response[:status],
162
+ statusText: status_code(response[:status]),
163
+ httpVersion: 'HTTP/1.1', # not available, default http/1.1
164
+ cookies: [],
165
+ headers: response_headers(response),
166
+ headersSize: res_headers_size,
167
+ content: {
168
+ size: res_content_size,
169
+ mimeType: response[:headers]['Content-Type'] || 'application/octet-stream'
170
+ },
171
+ bodySize: res_headers_size + res_content_size,
172
+ redirectURL: response[:headers]['Location'] || ''
173
+ },
174
+ cache: {},
175
+ timings: {
176
+ blocked: -1,
177
+ dns: -1,
178
+ connect: -1,
179
+ send: 0,
180
+ wait: (time * 1000).to_i,
181
+ receive: 0,
182
+ ssl: -1
183
+ }
184
+ }
185
+
186
+ if @send_body
187
+ require 'base64'
188
+ entry[:request][:content][:encoding] = 'base64'
189
+ request['rack.input'].rewind
190
+ entry[:request][:content][:text] = Base64.strict_encode64(request['rack.input'].read)
191
+
192
+ entry[:response][:content][:encoding] = 'base64'
193
+ entry[:response][:content][:text] = Base64.strict_encode64(response[:body].join())
194
+ end
195
+
196
+ alf.add_entry entry
197
+ MashapeAnalytics::Capture.record! alf
198
+ end
199
+
200
+ end
201
+ end
@@ -0,0 +1,7 @@
1
+ require 'mashape-analytics/frameworks/rack'
2
+
3
+ module MashapeAnalytics::Frameworks
4
+ class Rails < Rack
5
+ # Alias of Rack
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ require 'sinatra/base'
2
+ require 'mashape-analytics/frameworks/rack'
3
+ require 'time'
4
+ require 'socket'
5
+ require 'json'
6
+
7
+ module MashapeAnalytics::Frameworks
8
+ module Sinatra
9
+
10
+ def mashapeAnalytics!(service_token, options = {})
11
+ options[:service_token] = service_token
12
+ use MashapeAnalytics::Frameworks::Rack, options
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ require 'mashape-analytics/message/alf'
2
+
3
+ module MashapeAnalytics::Message
4
+ end
@@ -0,0 +1,38 @@
1
+ require 'json'
2
+
3
+ module MashapeAnalytics::Message
4
+ class Alf
5
+ attr_accessor :test
6
+
7
+ def initialize(serviceToken, environment, clientIp = nil)
8
+ @entries = []
9
+ @alf = {
10
+ version: '1.0.0',
11
+ serviceToken: serviceToken,
12
+ environment: environment,
13
+ har: {
14
+ log: {
15
+ version: '1.2',
16
+ creator: {
17
+ name: 'mashape-analytics-agent-ruby',
18
+ version: '1.0.0'
19
+ },
20
+ entries: @entries
21
+ }
22
+ }
23
+ }
24
+
25
+ if clientIp
26
+ @alf.clientIpAddress = clientIp
27
+ end
28
+ end
29
+
30
+ def add_entry(entry)
31
+ @entries << entry
32
+ end
33
+
34
+ def to_s
35
+ @alf.to_json
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ module MashapeAnalytics::Utils
2
+
3
+ # Source: http://spin.atomicobject.com/2014/07/07/ruby-queue-pop-timeout/
4
+ class QueueWithTimeout
5
+ def initialize
6
+ @mutex = Mutex.new
7
+ @queue = []
8
+ @recieved = ConditionVariable.new
9
+ end
10
+
11
+ def <<(x)
12
+ @mutex.synchronize do
13
+ @queue << x
14
+ @recieved.signal
15
+ end
16
+ end
17
+
18
+ def pop(non_block = false)
19
+ pop_with_timeout(non_block ? 0 : nil)
20
+ end
21
+
22
+ def pop_with_timeout(timeout = nil)
23
+ @mutex.synchronize do
24
+ if @queue.empty?
25
+ @recieved.wait(@mutex, timeout) if timeout != 0
26
+ #if we're still empty after the timeout, raise exception
27
+ raise ThreadError, "queue empty" if @queue.empty?
28
+ end
29
+ @queue.shift
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,83 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: mashape-analytics 1.0.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "mashape-analytics"
9
+ s.version = "1.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Mashape"]
14
+ s.date = "2015-06-25"
15
+ s.description = "The ruby agent that reports your API traffic to http://apianalytics.com"
16
+ s.email = "opensource@mashape.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".editorconfig",
24
+ ".travis.yml",
25
+ "Gemfile",
26
+ "LICENSE",
27
+ "README.md",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "mashape-analytics.gemspec",
31
+ "lib/mashape-analytics.rb",
32
+ "lib/mashape-analytics/capture.rb",
33
+ "lib/mashape-analytics/frameworks.rb",
34
+ "lib/mashape-analytics/frameworks/rack.rb",
35
+ "lib/mashape-analytics/frameworks/rails.rb",
36
+ "lib/mashape-analytics/frameworks/sinatra.rb",
37
+ "lib/mashape-analytics/message.rb",
38
+ "lib/mashape-analytics/message/alf.rb",
39
+ "lib/mashape-analytics/utils.rb",
40
+ "test/helper.rb",
41
+ "test/test_capture.rb",
42
+ "test/test_rack.rb",
43
+ "test/test_sinatra.rb"
44
+ ]
45
+ s.homepage = "http://github.com/Mashape/analytics-agent-ruby"
46
+ s.licenses = ["MIT"]
47
+ s.rubygems_version = "2.4.6"
48
+ s.summary = "Ruby agent for Mashape Analytics"
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 4
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<rbczmq>, [">= 1.7.8", "~> 1.7"])
55
+ s.add_development_dependency(%q<minitest>, ["~> 5.5"])
56
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
57
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
58
+ s.add_development_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0"])
59
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
60
+ s.add_development_dependency(%q<rails>, ["~> 4.1"])
61
+ s.add_development_dependency(%q<sinatra>, ["~> 1.4"])
62
+ else
63
+ s.add_dependency(%q<rbczmq>, [">= 1.7.8", "~> 1.7"])
64
+ s.add_dependency(%q<minitest>, ["~> 5.5"])
65
+ s.add_dependency(%q<shoulda>, [">= 0"])
66
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
67
+ s.add_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0"])
68
+ s.add_dependency(%q<simplecov>, [">= 0"])
69
+ s.add_dependency(%q<rails>, ["~> 4.1"])
70
+ s.add_dependency(%q<sinatra>, ["~> 1.4"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<rbczmq>, [">= 1.7.8", "~> 1.7"])
74
+ s.add_dependency(%q<minitest>, ["~> 5.5"])
75
+ s.add_dependency(%q<shoulda>, [">= 0"])
76
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
77
+ s.add_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0"])
78
+ s.add_dependency(%q<simplecov>, [">= 0"])
79
+ s.add_dependency(%q<rails>, ["~> 4.1"])
80
+ s.add_dependency(%q<sinatra>, ["~> 1.4"])
81
+ end
82
+ end
83
+
@@ -0,0 +1,77 @@
1
+ require 'rbczmq'
2
+ require 'rack'
3
+ require 'sinatra'
4
+
5
+ require 'simplecov'
6
+
7
+ gem 'minitest'
8
+ require 'minitest/autorun'
9
+ require 'minitest/unit'
10
+
11
+ module SimpleCov::Configuration
12
+ def clean_filters
13
+ @filters = []
14
+ end
15
+ end
16
+
17
+ SimpleCov.configure do
18
+ clean_filters
19
+ load_adapter 'test_frameworks'
20
+ end
21
+
22
+ ENV["COVERAGE"] && SimpleCov.start do
23
+ add_filter "/.rvm/"
24
+ end
25
+ require 'rubygems'
26
+ require 'bundler'
27
+ begin
28
+ Bundler.setup(:default, :development)
29
+ rescue Bundler::BundlerError => e
30
+ $stderr.puts e.message
31
+ $stderr.puts "Run `bundle install` to install missing gems"
32
+ exit e.status_code
33
+ end
34
+ # require 'test/unit'
35
+ require 'shoulda'
36
+
37
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
38
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
39
+ require 'mashape-analytics'
40
+
41
+ class MiniTest::Test
42
+ @@host = 'tcp://127.0.0.1:2200'
43
+
44
+ MashapeAnalytics::Capture.setOptions(host: @@host) # Set default host
45
+
46
+ def zmq_pull_socket(host)
47
+ pull_socket = MashapeAnalytics::Capture.context.socket(:PULL)
48
+ pull_socket.bind(host)
49
+
50
+ return pull_socket
51
+ end
52
+
53
+ def assert_ruby_agent(alf_json)
54
+ assert_equal 'mashape-analytics-agent-ruby', alf_json['har']['log']['creator']['name']
55
+ end
56
+
57
+ def assert_entry_request(entry_json, method, url)
58
+ assert_equal method, entry_json['request']['method']
59
+ assert_equal url, entry_json['request']['url']
60
+ end
61
+
62
+ def assert_entry_request_content(entry_json, encoding, text)
63
+ assert_equal encoding, entry_json['request']['content']['encoding']
64
+ assert_equal text, entry_json['request']['content']['text']
65
+ end
66
+
67
+ def assert_entry_response(entry_json, status, bodySize)
68
+ assert_equal status, entry_json['response']['status']
69
+ assert_equal bodySize, entry_json['response']['bodySize']
70
+ end
71
+
72
+ def assert_entry_response_content(entry_json, encoding, text)
73
+ assert_equal encoding, entry_json['response']['content']['encoding']
74
+ assert_equal text, entry_json['response']['content']['text']
75
+ end
76
+
77
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+ require 'json'
3
+
4
+ class TestCapture < MiniTest::Test
5
+
6
+ def setup
7
+ # Create our socket server
8
+ @zmq_pull = zmq_pull_socket(@@host)
9
+ end
10
+
11
+ def teardown
12
+ MashapeAnalytics::Capture.disconnect
13
+ @zmq_pull.close
14
+ end
15
+
16
+ should 'send ALF' do
17
+ alf = MashapeAnalytics::Message::Alf.new 'SERVICE-TOKEN', 'ENVIRONMENT'
18
+ MashapeAnalytics::Capture.record! alf
19
+
20
+ version, message = @zmq_pull.recv().split(' ', 2)
21
+
22
+ alf = JSON.parse(message)
23
+
24
+ assert_ruby_agent alf
25
+ assert_equal 'alf_1.0.0', version
26
+ end
27
+
28
+ end
@@ -0,0 +1,71 @@
1
+ require 'rack'
2
+ require 'helper'
3
+
4
+ class TestRack < MiniTest::Test
5
+ @send_body = false
6
+
7
+ def app
8
+ app = proc do
9
+ sleep 0.05
10
+ [200, {'CONTENT-TYPE' => 'application/json'}, ['{"messages": "Test Response"}']]
11
+ end
12
+ stack = MashapeAnalytics::Frameworks::Rack.new app, service_token: 'SERVICE-TOKEN', host: '127.0.0.1:2200', send_body: @send_body
13
+ Rack::MockRequest.new(stack)
14
+ end
15
+
16
+ def setup
17
+ # Create our socket server
18
+ @zmq_pull = zmq_pull_socket(@@host)
19
+ end
20
+
21
+ def teardown
22
+ MashapeAnalytics::Capture.disconnect
23
+ @zmq_pull.close
24
+ @send_body = false
25
+ end
26
+
27
+ should 'send ALF on GET /get?foo=bar&empty request' do
28
+ response = app.get('/get?foo=bar&empty', {'HTTP_ACCEPT' => 'application/json'})
29
+
30
+ version, message = @zmq_pull.recv.split(' ', 2)
31
+ alf = JSON.parse(message)
32
+
33
+ assert_ruby_agent alf
34
+
35
+ entry = alf['har']['log']['entries'].first
36
+ assert_entry_request entry, 'GET', 'http://example.org/get?foo=bar&empty'
37
+ assert_entry_response entry, 200, 76
38
+ end
39
+
40
+ should 'send ALF on POST /post request' do
41
+ response = app.post('/post', {'HTTP_ACCEPT' => 'application/json', input: 'test POST body'})
42
+
43
+ version, message = @zmq_pull.recv.split(' ', 2)
44
+ alf = JSON.parse(message)
45
+
46
+ assert_ruby_agent alf
47
+
48
+ entry = alf['har']['log']['entries'].first
49
+ assert_entry_request entry, 'POST', 'http://example.org/post'
50
+ assert_entry_response entry, 200, 76
51
+ end
52
+
53
+ should 'send ALF with body on POST /post request' do
54
+ @send_body = true
55
+ response = app.post('/post', {'HTTP_ACCEPT' => 'application/json', input: 'test POST body'})
56
+
57
+ version, message = @zmq_pull.recv.split(' ', 2)
58
+ alf = JSON.parse(message)
59
+
60
+ assert_ruby_agent alf
61
+
62
+ entry = alf['har']['log']['entries'].first
63
+ assert_entry_request entry, 'POST', 'http://example.org/post'
64
+ assert_entry_request_content entry, 'base64', 'dGVzdCBQT1NUIGJvZHk='
65
+
66
+ assert_entry_response entry, 200, 76
67
+ assert_entry_response_content entry, 'base64', 'eyJtZXNzYWdlcyI6ICJUZXN0IFJlc3BvbnNlIn0='
68
+ end
69
+
70
+
71
+ end
@@ -0,0 +1,60 @@
1
+ require 'sinatra'
2
+ require 'sinatra/base'
3
+ require 'rack'
4
+ require 'helper'
5
+
6
+
7
+ class TestSinatra < MiniTest::Test
8
+ @zmq_pull = nil
9
+
10
+ def app
11
+ Sinatra.new do
12
+ register MashapeAnalytics::Frameworks::Sinatra
13
+
14
+ mashapeAnalytics! 'MY-API-KEY', host: '127.0.0.1:2200', send_body: true
15
+
16
+ get('/get') { 'GET Endpoint' }
17
+ post('/post') { 'POST Endpoint' }
18
+ end
19
+ end
20
+
21
+ def setup
22
+ # Create our socket server
23
+ @zmq_pull = zmq_pull_socket('tcp://127.0.0.1:2200')
24
+ end
25
+
26
+ def teardown
27
+ MashapeAnalytics::Capture.disconnect
28
+ @zmq_pull.close if @zmq_pull != nil
29
+ end
30
+
31
+ should 'send ALF on GET /get?query=test request' do
32
+ request = Rack::MockRequest.new(app)
33
+ response = request.get('/get?query=test')
34
+
35
+ version, message = @zmq_pull.recv.split(' ', 2)
36
+ alf = JSON.parse(message)
37
+
38
+ assert_ruby_agent alf
39
+
40
+ entry = alf['har']['log']['entries'].first
41
+ assert_entry_request entry, 'GET', 'http://example.org/get?query=test'
42
+ assert_entry_response entry, 200, 86
43
+ end
44
+
45
+ should 'send ALF on POST /post request' do
46
+ request = Rack::MockRequest.new(app)
47
+ response = request.post('/post')
48
+
49
+ version, message = @zmq_pull.recv.split(' ', 2)
50
+ alf = JSON.parse(message)
51
+
52
+ assert_ruby_agent alf
53
+
54
+ entry = alf['har']['log']['entries'].first
55
+ assert_entry_request entry, 'POST', 'http://example.org/post'
56
+ assert_entry_response entry, 200, 87
57
+ end
58
+
59
+
60
+ end
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mashape-analytics
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mashape
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rbczmq
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.7.8
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '1.7'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.7.8
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.7'
33
+ - !ruby/object:Gem::Dependency
34
+ name: minitest
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.5'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '5.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: shoulda
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: jeweler
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 2.0.1
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '2.0'
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 2.0.1
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: simplecov
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rails
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '4.1'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '4.1'
123
+ - !ruby/object:Gem::Dependency
124
+ name: sinatra
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '1.4'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '1.4'
137
+ description: The ruby agent that reports your API traffic to http://apianalytics.com
138
+ email: opensource@mashape.com
139
+ executables: []
140
+ extensions: []
141
+ extra_rdoc_files:
142
+ - LICENSE
143
+ - README.md
144
+ files:
145
+ - ".document"
146
+ - ".editorconfig"
147
+ - ".travis.yml"
148
+ - Gemfile
149
+ - LICENSE
150
+ - README.md
151
+ - Rakefile
152
+ - VERSION
153
+ - lib/mashape-analytics.rb
154
+ - lib/mashape-analytics/capture.rb
155
+ - lib/mashape-analytics/frameworks.rb
156
+ - lib/mashape-analytics/frameworks/rack.rb
157
+ - lib/mashape-analytics/frameworks/rails.rb
158
+ - lib/mashape-analytics/frameworks/sinatra.rb
159
+ - lib/mashape-analytics/message.rb
160
+ - lib/mashape-analytics/message/alf.rb
161
+ - lib/mashape-analytics/utils.rb
162
+ - mashape-analytics.gemspec
163
+ - test/helper.rb
164
+ - test/test_capture.rb
165
+ - test/test_rack.rb
166
+ - test/test_sinatra.rb
167
+ homepage: http://github.com/Mashape/analytics-agent-ruby
168
+ licenses:
169
+ - MIT
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 2.4.6
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: Ruby agent for Mashape Analytics
191
+ test_files: []