columbo 0.1.5 → 0.2.1

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: 7e4dc0fa4f95aac130e637f09794b94404bf22e5
4
+ data.tar.gz: 64c82608f49ff6b51a6a60a054392d25c8ae93e4
5
+ SHA512:
6
+ metadata.gz: 997eae7d6bf3e6e6595168508f3cc9d435b59b6f70bff1a47fc1c84f8aaec557ee3769bea9cda05486f94193a659c39204fb16962c2e759afc49fc40dc2633b9
7
+ data.tar.gz: b62b4e55bbae5cc25aaed09673e9ad5bec5ab5f7b38c35549d97cd6d5bde64825441349fb8abf61bac5b83e3ea2d4522a5fed62c26cf377e860edf2d71948b13
data/README.md CHANGED
@@ -5,6 +5,12 @@ that captures users browsing sessions for Rack applications.
5
5
 
6
6
  Tribute to [Inspector Columbo](http://www.imdb.com/title/tt1466074/)
7
7
 
8
+ ## Disclaimer
9
+
10
+ This is an alpha release, it is tested with Sinatra and Rails 3 only.
11
+ The UI to explore sessions is in progress (ETA: 2013'Q4) therefore
12
+ there is no point using this gem at the moment.
13
+
8
14
  ## Using with Rack application
9
15
 
10
16
  *Columbo* can be used with any Rack application,
@@ -16,8 +22,8 @@ simply require and use as follows:
16
22
  require 'columbo/capture'
17
23
  use Columbo::Capture, {
18
24
  capture: true,
19
- bench: false,
20
- mongo_uri: 'mongodb://user:password@mongodb_host:port/database',
25
+ bench: true,
26
+ api_key: 'your-private-api-key',
21
27
  logger: 'log/columbo.log'
22
28
  }
23
29
  run app
@@ -25,28 +31,35 @@ simply require and use as follows:
25
31
  ## Using with Rails 3
26
32
 
27
33
  In order to use, include the following in a Rails application
28
- *Gemfile* file:
34
+ **Gemfile** file:
29
35
 
30
36
  gem 'columbo'
31
37
 
32
- *config/application.rb* file:
38
+ **config/application.rb** file:
33
39
 
34
40
  require 'columbo/capture'
35
41
  config.middleware.insert 0, Columbo::Capture, {
36
42
  capture: Rails.env.production?,
37
- bench: false,
38
- mongo_uri: 'mongodb://user:password@mongodb_host:port/database',
39
- logger: 'log/columbo.log'
43
+ api_key: 'your-private-api-key',
44
+ logger: 'log/columbo.log',
45
+ filter_uri: ['admin']
40
46
  }
41
47
 
42
48
  Check the Rack configuration:
43
49
 
44
50
  rake middleware
45
51
 
46
- ## Disclaimer
52
+ ## Options
47
53
 
48
- This is an alpha release, it is tested with Sinatra and Rails 3 only.
49
- UI to explore sessions will be completed later (ETA: 2013'Q2).
54
+ - `api_key`: the api key for authentication (mandatory),
55
+ - `capture`: set to true to collect data, default `false`
56
+ - `bench`: set to true to benchmark middleware overhead, default `false`
57
+ - `logger`: file to write logs to, default `env['rack.errors']`
58
+ - `capture_crawlers`: set to true to capture hits from crawlers, default `false`
59
+ - `api_uri`: overwrite api endpoint uri
60
+ - `crawlers`: overwrite crawlers user agent regex
61
+ - `filter_params`: array of parameters to filter, for `Rails` default to `Rails.configuration.filter_parameters`
62
+ - `filter_uri`: array of uri for which **not** to capture data
50
63
 
51
64
  ## Author
52
65
 
@@ -54,5 +67,5 @@ Jerome Touffe-Blin, [@jtblin](https://twitter.com/jtlbin), [http://www.linkedin.
54
67
 
55
68
  ## License
56
69
 
57
- Columbo is copyright 2012 Jerome Touffe-Blin and contributors. It is licensed under the BSD license. See the include LICENSE file for details.
70
+ Columbo is copyright 2013 Jerome Touffe-Blin and contributors. It is licensed under the BSD license. See the include LICENSE file for details.
58
71
 
data/lib/columbo.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'columbo/version'
2
- require 'columbo/db_client'
2
+ require 'columbo/api_client'
3
+ require 'columbo/capture'
3
4
  require 'columbo/inspector'
4
5
  require 'columbo/log_writer'
6
+ require 'columbo/compressor'
5
7
 
6
8
  module Columbo
7
- MONGO_COLLECTION = "hits".freeze
8
-
9
9
  def self.logger
10
10
  @logger
11
11
  end
@@ -0,0 +1,49 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Columbo
5
+ class APIClient
6
+
7
+ API_URI = "http://localhost:15080".freeze
8
+
9
+ def initialize(api_key, api_uri)
10
+ @api_key = api_key
11
+ @api_uri = api_uri || API_URI
12
+ end
13
+
14
+ def handshake
15
+ Thread.new do
16
+ headers = { "Content-Type" => "application/json; charset=utf-8" }
17
+
18
+ uri = URI(@api_uri + '/' + @api_key + '/handshake')
19
+ Net::HTTP.new(uri.host, uri.port).start do |http|
20
+ response = http.get(uri.request_uri, headers)
21
+ json = JSON.parse(response.body)
22
+ json.each { |k, v| yield k, v }
23
+ end
24
+ end
25
+ end
26
+
27
+ def post_data(hash)
28
+ headers = {
29
+ "Accept-Encoding" => "gzip, deflate",
30
+ "Content-Encoding" => "deflate",
31
+ "Content-Type" => "application/json; charset=utf-8"
32
+ }
33
+
34
+ zlib = Columbo::Compressor
35
+ json = hash.merge({api_key: @api_key}).to_json
36
+ payload = zlib.deflate(json)
37
+ uri = URI(@api_uri + '/' + @api_key + '/capture')
38
+
39
+ start = Time.now
40
+ Net::HTTP.new(uri.host, uri.port).start do |http|
41
+ response = http.post(uri.request_uri, payload, headers)
42
+ stop = Time.now
43
+ duration = ((stop-start) * 1000).round(3)
44
+ zlib.unzip(response.body, response['Content-Encoding']) + ' - Time: ' + duration.to_s + 'ms'
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -1,27 +1,40 @@
1
1
  require 'columbo'
2
2
  require 'rack/utils'
3
3
  require 'rack/logger'
4
+ require 'securerandom'
4
5
 
5
6
  module Columbo
6
7
  class Capture
7
8
  include Rack::Utils
8
9
 
10
+ attr_reader :client, :filter_params, :filter_uri
11
+
9
12
  FORMAT = %{[Columbo #{Columbo::VERSION}] [%s] %s - %s "%s%s %s\n}
10
13
 
11
14
  def initialize(app, opts={})
12
15
  @app = app
13
16
  # Options
14
- @capture = opts[:capture]
17
+ @capture = !!opts[:capture]
15
18
  @bench = opts[:capture] && opts[:bench]
16
- @capture_crawlers = opts[:capture_crawlers]
17
- @crawlers = opts[:crawlers] || "(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg|bot|crawler|spider|robot|crawling|facebook|w3c|coccoc|Daumoa)"
18
- @mongo_uri = opts[:mongo_uri]
19
+ capture_crawlers = opts[:capture_crawlers]
20
+ crawlers = opts[:crawlers] || "(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg|bot|crawler|spider|robot|crawling|facebook|w3c|coccoc|Daumoa|panopta)"
21
+ api_key = opts[:api_key]
22
+ api_uri = opts[:api_uri]
23
+ @filter_params = opts[:filter_params] || []
24
+ @filter_uri = opts[:filter_uri] || []
25
+
26
+ @cookie_name = 'clickstream.io'
27
+ filter_params.concat(Rails.configuration.filter_parameters || []) if defined?(Rails)
19
28
 
20
29
  Columbo.logger = opts[:logger] if opts[:logger]
21
30
 
22
- raise ArgumentError, 'mongo URI missing.' if @mongo_uri.nil?
31
+ raise ArgumentError, 'API key missing.' if api_key.nil?
23
32
 
24
- @inspector = Columbo::Inspector.new @mongo_uri
33
+ @inspector = Columbo::Inspector.new api_key, api_uri, crawlers, capture_crawlers, filter_params
34
+ @cookie_regex = Regexp.new "#{@cookie_name}="
35
+
36
+ @client = {}
37
+ Columbo::APIClient.new(api_key, api_uri).handshake { |k, v| @client[k] = v}
25
38
  end
26
39
 
27
40
  def call(env)
@@ -35,30 +48,36 @@ module Columbo
35
48
 
36
49
  start = Time.now if @bench
37
50
 
38
- headers = HeaderHash.new(headers) # Is it required?
51
+ headers = HeaderHash.new(headers)
39
52
 
40
- if !STATUS_WITH_NO_ENTITY_BODY.include?(status) &&
41
- !headers['transfer-encoding'] &&
42
- headers['content-type'] &&
43
- headers['content-type'].include?("text/html")
53
+ if @capture && !STATUS_WITH_NO_ENTITY_BODY.include?(status) && !headers['transfer-encoding'] && headers['content-type'] && (
54
+ headers['content-type'].include?('text/html') || headers['content-type'].include?('application/json') ||
55
+ headers['content-type'].include?('application/xml') || headers['content-type'].include?('text/javascript') ||
56
+ headers['content-type'].include?('text/plain')
57
+ ) && !filtered_uri?(env['REQUEST_URI'])
44
58
 
45
- Thread.abort_on_exception = true
59
+ cookie = session_cookie(env, headers)
60
+ pid = SecureRandom.uuid
61
+ body = response.clone
46
62
 
63
+ Thread.abort_on_exception = false
47
64
  Thread.new do
48
65
  begin
49
- @inspector.investigate env, status, headers, response, start_processing, stop_processing, @crawlers, @capture_crawlers
66
+ result = @inspector.investigate env, status, headers, body, start_processing, stop_processing, cookie, pid
67
+ log env, result
50
68
  rescue Exception => e
51
69
  log_error env, e
52
70
  end
53
- end if @capture
71
+ end
54
72
 
73
+ response = insert_js(response, headers, cookie, pid) if headers['content-type'].include?('text/html') #&& headers['content-length'].to_i > 0
55
74
  end
56
75
 
57
76
  if @bench
58
77
  stop = Time.now
59
78
  duration = ((stop-start) * 1000).round(3)
60
- log(env, "Time: #{duration}ms")
61
79
  headers['Columbo'] = "version #{Columbo::VERSION}, time #{duration}ms"
80
+ Thread.new { log(env, "Time: #{duration}ms") }
62
81
  end
63
82
 
64
83
  [status, headers, response]
@@ -66,6 +85,42 @@ module Columbo
66
85
 
67
86
  private
68
87
 
88
+ def filtered_uri?(uri)
89
+ filter_uri.select {|filter| uri.match filter}.size > 0
90
+ end
91
+
92
+ def session_cookie(env, headers)
93
+ cookie = extract_cookie(env['HTTP_COOKIE'])
94
+ set_cookie(headers, cookie)
95
+ end
96
+
97
+ def extract_cookie(string)
98
+ return unless string
99
+ match = string.match(/columbo=([^;]*)/)
100
+ match[1] if match && match.length > 1
101
+ end
102
+
103
+ def set_cookie(headers, cookie)
104
+ expires = Time.now+60*60
105
+ cookie = cookie.nil? ? {value: SecureRandom.uuid} : {value: cookie}
106
+ cookie[:expires] = expires
107
+ Rack::Utils.set_cookie_header!(headers, @cookie_name, cookie)
108
+ cookie[:value]
109
+ end
110
+
111
+ def insert_js(body, headers, sid, pid)
112
+ html = ''
113
+ body.each { |part| html += part }
114
+ body.close if body.respond_to?(:close)
115
+ str_filter_params = filter_params.map { |filter| filter.to_s }
116
+ if html.size > 0
117
+ script = "<script>(function(){var uri='#{client['ws']}', cid='#{client['clientId']}', sid='#{sid}', pid='#{pid}', paramsFilter = #{str_filter_params}; #{client['js']}})();</script>"
118
+ html += "\n" + script
119
+ end
120
+ headers['content-length'] = html.size.to_s
121
+ [html]
122
+ end
123
+
69
124
  def log(env, message)
70
125
  now = Time.now
71
126
 
@@ -0,0 +1,51 @@
1
+ require 'stringio'
2
+ require 'zlib'
3
+
4
+ module Columbo
5
+ class Compressor
6
+
7
+ def self.encoding_handled?(content_encoding)
8
+ %w(gzip deflate).include? content_encoding
9
+ end
10
+
11
+ def self.unzip(source, content_encoding)
12
+ case content_encoding
13
+ when 'gzip' then decompress(source)
14
+ when 'deflate' then inflate(source)
15
+ else source
16
+ end
17
+ end
18
+
19
+ def self.zip(source, accept_encoding)
20
+ if accept_encoding.match 'deflate'
21
+ deflate(source)
22
+ elsif accept_encoding.match 'gzip'
23
+ compress(source)
24
+ else
25
+ source
26
+ end
27
+ end
28
+
29
+ # Compresses a string using gzip inspired by ActiveSupport::Gzip
30
+ def self.compress(source)
31
+ output = StringIO.new
32
+ gz = Zlib::GzipWriter.new(output)
33
+ gz.write(source)
34
+ gz.close
35
+ output.string
36
+ end
37
+
38
+ def self.deflate(source)
39
+ Zlib::Deflate.deflate(source)
40
+ end
41
+
42
+ def self.decompress(source)
43
+ Zlib::GzipReader.new(StringIO.new(source)).read
44
+ end
45
+
46
+ def self.inflate(source)
47
+ Zlib::Inflate.inflate(source.read)
48
+ end
49
+
50
+ end
51
+ end
@@ -1,88 +1,77 @@
1
1
  require 'rack/request'
2
2
  require 'rack/response'
3
- require 'nokogiri'
4
- require 'html_mini'
3
+ require 'socket'
5
4
 
6
5
  module Columbo
7
6
  class Inspector
8
7
 
9
- def initialize(mongo_uri)
10
- @mongo_uri = mongo_uri
8
+ def initialize(api_key, api_uri, crawlers, capture_crawlers, filter_params)
9
+ @client = Columbo::APIClient.new(api_key, api_uri)
10
+ @crawlers, @capture_crawlers, @filter_params = crawlers, capture_crawlers, filter_params
11
+ @hostname = Socket.gethostname
12
+ @rg = Regexp.new(crawlers, Regexp::IGNORECASE)
11
13
  end
12
14
 
13
- def investigate(env, status, headers, body, start, stop, crawlers, capture_crawlers)
14
- # Lazy connection to MongoDB
15
- client = Columbo::DbClient.new @mongo_uri
15
+ def investigate(env, status, headers, body, start, stop, cookie, pid)
16
16
  # Normalise request from env
17
17
  request = Rack::Request.new(env)
18
18
  # Don't capture bots traffic by default
19
- rg = Regexp.new(crawlers, Regexp::IGNORECASE)
20
- return if request.user_agent.match(rg) && !capture_crawlers
19
+ return unless @capture_crawlers || !request.user_agent.match(@rg)
21
20
  html = ''
22
- body.each { |part| html += part }
23
- # Retrieve plain text body for full text search
24
- text, title = to_plain_text(html)
25
- # Get request headers
21
+ # in case of gzipping has been done by the app
22
+ body.each { |part| html += Columbo::Compressor.unzip(part, headers['Content-Encoding']) }
26
23
  request_headers = {}
27
- request.env.each { |key, value| request_headers[key.sub(/^HTTP_/, '').downcase] = value if key.start_with? 'HTTP_'}
24
+ request.env.each { |key, value| request_headers[key.sub(/^HTTP_/, '').gsub(/_/, '-').downcase] = value if key.start_with? 'HTTP_'}
25
+ params = request.params.clone || {}
26
+ @filter_params.each {|param| params[param.to_s] = '[FILTERED]' if params[param.to_s]}
27
+ session_opts = request.session_options.clone || {}
28
+ session_opts.delete :secret
28
29
  data = {
30
+ sid: cookie,
31
+ pid: pid,
32
+ hostname: @hostname,
33
+ filter_params: @filter_params,
29
34
  request: {
30
- params: request.params,
31
- remote_ip: request.ip,
35
+ params: params,
36
+ ip: request.ip,
32
37
  user_agent: request.user_agent,
33
- method: request.env['REQUEST_METHOD'],
38
+ referer: request.referer,
39
+ method: request.request_method,
40
+ path: request.path, # script_name + path_info
41
+ fullpath: request.fullpath, # "#{path}?#{query_string}"
42
+ script_name: request.script_name,
43
+ path_info: request.path_info,
34
44
  uri: request.env['REQUEST_URI'],
35
- script: request.env['SCRIPT_NAME'],
36
- path: request.env['PATH_INFO'],
37
- query_string: request.env['QUERY_STRING'],
38
- protocol: request.env['rack.url_scheme'],
39
- server_name: request.env['SERVER_NAME'],
40
- server_port: request.env['SERVER_PORT'],
41
- http: request.env['SERVER_PROTOCOL'],
42
- session: request.env['rack.session'],
43
- cookie: request.env['rack.request.cookie_hash'],
45
+ querystring: request.query_string,
46
+ scheme: request.scheme,
47
+ host: request.host,
48
+ port: request.port,
49
+ url: request.url, # base_url + fullpath
50
+ base_url: request.base_url, # scheme + host [+ port]
51
+ content_type: request.content_type,
52
+ content_charset: request.content_charset,
53
+ media_type: request.media_type,
54
+ media_type_params: request.media_type_params,
55
+ protocol: request.env['HTTP_VERSION'],
56
+ session: request.session,
57
+ session_options: session_opts,
58
+ cookies: request.cookies,
44
59
  path_parameters: request.env['action_dispatch.request.path_parameters'],
45
- headers: request_headers
60
+ headers: request_headers,
61
+ xhr: request.xhr?
46
62
  },
47
- status: status,
48
- headers: headers,
49
- size: html.length,
50
- body: HtmlMini.minify(html),
51
- text: text,
52
- title: title,
53
- start: start,
54
- stop: stop,
55
- time: stop-start
63
+ response: {
64
+ status: status,
65
+ headers: headers,
66
+ size: html.length,
67
+ body: html,
68
+ start: start,
69
+ stop: stop,
70
+ time: stop-start
71
+ }
56
72
  }
57
- # Insert data in MongoDB
58
- client.insert sanitize(data)
59
- end
60
-
61
- def to_plain_text(html)
62
- html_doc = Nokogiri::HTML(html)
63
- html_doc.xpath('//script').each {|node| node.remove}
64
- html_doc.xpath('//style').each {|node| node.remove}
65
- text = ''
66
- html_doc.xpath('//body').each {|node| text += node.text.gsub(/\s{2,}/, ' ')}
67
- title_tag = html_doc.xpath('//title').first
68
- title = title_tag.nil? ? nil : title_tag.text
69
- [text, title]
70
- end
71
-
72
- private
73
-
74
- def sanitize(data)
75
- Hash[
76
- data.map do |key, value|
77
- value = sanitize(value) if value.is_a? Hash
78
- # replace $ and . in keys by Unicode full width equivalent
79
- # http://docs.mongodb.org/manual/faq/developers/#faq-dollar-sign-escaping
80
- key = key.gsub('.', 'U+FF0E').gsub('$', 'U+FF04') if key.is_a? String
81
- # transform symbol into string to avoid auto transformation into $symbol
82
- value = value.to_s if value.is_a? Symbol
83
- [key, value]
84
- end
85
- ]
73
+ # Send data to API
74
+ @client.post_data data
86
75
  end
87
76
 
88
77
  end
@@ -1,3 +1,3 @@
1
1
  module Columbo
2
- VERSION = '0.1.5'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,113 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: columbo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jerome Touffe-Blin
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-14 00:00:00.000000000 Z
11
+ date: 2013-12-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rack
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.4.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.4.0
30
27
  - !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: 1.5.9
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: 1.5.9
46
- - !ruby/object:Gem::Dependency
47
- name: html_mini
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: 0.0.2
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.0.2
62
- - !ruby/object:Gem::Dependency
63
- name: mongo
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: 1.6.1
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: 1.6.1
78
- - !ruby/object:Gem::Dependency
79
- name: bson_ext
28
+ name: sinatra
80
29
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
30
  requirements:
83
- - - ! '>='
31
+ - - '>='
84
32
  - !ruby/object:Gem::Version
85
- version: 1.6.1
86
- type: :runtime
33
+ version: 1.3.0
34
+ type: :development
87
35
  prerelease: false
88
36
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
37
  requirements:
91
- - - ! '>='
38
+ - - '>='
92
39
  - !ruby/object:Gem::Version
93
- version: 1.6.1
40
+ version: 1.3.0
94
41
  - !ruby/object:Gem::Dependency
95
- name: sinatra
42
+ name: lorem
96
43
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
44
  requirements:
99
- - - ! '>='
45
+ - - '>='
100
46
  - !ruby/object:Gem::Version
101
- version: 1.3.0
47
+ version: 0.1.2
102
48
  type: :development
103
49
  prerelease: false
104
50
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
51
  requirements:
107
- - - ! '>='
52
+ - - '>='
108
53
  - !ruby/object:Gem::Version
109
- version: 1.3.0
110
- description: ! 'A Ruby client library for Columbo: a Customer Experience Management
54
+ version: 0.1.2
55
+ description: 'A Ruby client library for Columbo: a Customer Experience Management
111
56
  tool'
112
57
  email: jtblin@gmail.com
113
58
  executables: []
@@ -116,7 +61,9 @@ extra_rdoc_files:
116
61
  - LICENSE
117
62
  - README.md
118
63
  files:
64
+ - lib/columbo/api_client.rb
119
65
  - lib/columbo/capture.rb
66
+ - lib/columbo/compressor.rb
120
67
  - lib/columbo/db_client.rb
121
68
  - lib/columbo/inspector.rb
122
69
  - lib/columbo/log_writer.rb
@@ -127,27 +74,26 @@ files:
127
74
  - README.md
128
75
  homepage: http://github.com/jtblin/columbo-rb
129
76
  licenses: []
77
+ metadata: {}
130
78
  post_install_message:
131
79
  rdoc_options:
132
80
  - --charset=UTF-8
133
81
  require_paths:
134
82
  - lib
135
83
  required_ruby_version: !ruby/object:Gem::Requirement
136
- none: false
137
84
  requirements:
138
- - - ! '>='
85
+ - - '>='
139
86
  - !ruby/object:Gem::Version
140
87
  version: '0'
141
88
  required_rubygems_version: !ruby/object:Gem::Requirement
142
- none: false
143
89
  requirements:
144
- - - ! '>='
90
+ - - '>='
145
91
  - !ruby/object:Gem::Version
146
92
  version: 1.3.6
147
93
  requirements: []
148
94
  rubyforge_project:
149
- rubygems_version: 1.8.25
95
+ rubygems_version: 2.1.10
150
96
  signing_key:
151
- specification_version: 3
97
+ specification_version: 4
152
98
  summary: A Ruby client library for Inspector Columbo
153
99
  test_files: []