loggly-rb 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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +133 -0
- data/Rakefile +1 -0
- data/bin/loggly +24 -0
- data/lib/loggly.rb +51 -0
- data/lib/loggly/connection.rb +77 -0
- data/lib/loggly/exceptions.rb +8 -0
- data/lib/loggly/logging.rb +27 -0
- data/lib/loggly/middleware/loggly_response_middleware.rb +23 -0
- data/lib/loggly/model.rb +41 -0
- data/lib/loggly/models/event.rb +36 -0
- data/lib/loggly/models/search.rb +33 -0
- data/lib/loggly/remote_model.rb +80 -0
- data/lib/loggly/request.rb +28 -0
- data/lib/loggly/response.rb +127 -0
- data/lib/loggly/version.rb +3 -0
- data/loggly.gemspec +37 -0
- metadata +290 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 253ff688f04d5118626f5d26cd13324f4fe7ee9b
|
4
|
+
data.tar.gz: 7eb4cf65f3b31914ea4a7e335ac454fe0421faa7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b49f24af5c206911e101c4e62452cf3ba44e0a5cea7ac86c1a1b9b2e985bd1e43de708207d487014a18bcaa00234dcbb8c57c0d9264af37d7dfb9971c2595bd5
|
7
|
+
data.tar.gz: c3f01d63b025cbe0af036107cd7d2ee32b2b684fc0575fa657cc4562770c4849532e8478c2cc68b398e94d3a8a51adcbdc7148c3f9f88dd1bb24cbfd0f5a02ad
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Keith Larrimore
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Loggly
|
2
|
+
|
3
|
+
[Loggly](www.loggly.com) API client for the Ruby programming language.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'loggly'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install loggly
|
18
|
+
|
19
|
+
# Usage
|
20
|
+
|
21
|
+
## Connect
|
22
|
+
|
23
|
+
Simple connection method for Loggly authorization.
|
24
|
+
|
25
|
+
#### Required Connections Parameters:
|
26
|
+
|
27
|
+
params = { :uri => "http://<account>.loggly.com",
|
28
|
+
:username => <username>,
|
29
|
+
:password => <password> }
|
30
|
+
|
31
|
+
#### Connect:
|
32
|
+
|
33
|
+
Authorize the Loggly API with `Loggy.connect(params)`
|
34
|
+
|
35
|
+
## Search
|
36
|
+
|
37
|
+
The Loggly API provides a simple interface to perform searches.
|
38
|
+
|
39
|
+
#### Single Field
|
40
|
+
|
41
|
+
The query `:q => { :'loggly.tag' => "bar" }` outputs to `loggly.tag:bar`
|
42
|
+
|
43
|
+
#### Multiple Fields
|
44
|
+
|
45
|
+
There are multiple methods for performing more complex searches.
|
46
|
+
|
47
|
+
##### AND Method Only, for now
|
48
|
+
|
49
|
+
:q => {
|
50
|
+
:'loggly.tag' => "bar",
|
51
|
+
:'other.loggly.tag' => "baz"
|
52
|
+
}
|
53
|
+
|
54
|
+
outputs to `loggly.tags:bar AND other.loggly.tags:baz`
|
55
|
+
|
56
|
+
|
57
|
+
#### Interfacing with API:
|
58
|
+
|
59
|
+
`Loggly::Event.all(:q => { :'loggly.tags' => "bar" })` returns an array of events.
|
60
|
+
|
61
|
+
### Search Endpoint Parameters:
|
62
|
+
|
63
|
+
* `:q` - optional - query string. Defaults to `"*"`.
|
64
|
+
* `:from` - optional - Start time for the search. Defaults to `-24h`.
|
65
|
+
* `:until` - optional - End time for the search. Defaults to `now`.
|
66
|
+
* `:order` - optional - Direction of results returned, either `asc` or `desc`. Defaults to `desc`.
|
67
|
+
* `:per_page` - optional - Number of rows returned by search. Defaults to `25`.
|
68
|
+
|
69
|
+
Check the official [Loggy documentation](https://www.loggly.com/docs/api-retrieving-data/) for more assistance.
|
70
|
+
|
71
|
+
## Events
|
72
|
+
|
73
|
+
Each Event has a **Response** and **attributes** that match the Loggly fields.
|
74
|
+
|
75
|
+
### Response
|
76
|
+
|
77
|
+
{:total_events=>3292470,
|
78
|
+
:page=>0,
|
79
|
+
:events=>
|
80
|
+
[{:tags=>["chipper", "frontend"],
|
81
|
+
:timestamp => 1377431712208,
|
82
|
+
:logmsg => "{\timestamp\: \13-08-25 11:55:12,208191\, \baremsg\: \Alert is due to run\}"",
|
83
|
+
:event=>
|
84
|
+
{:syslog=>
|
85
|
+
{:priority=>142,
|
86
|
+
:timestamp=>"2013-08-25T11:55:12.208596+00:00",
|
87
|
+
:host=>"frontend01",
|
88
|
+
:severity=>"Informational",
|
89
|
+
:facility=>"local use 1"
|
90
|
+
},
|
91
|
+
:json=>
|
92
|
+
{:timestamp=>13-08-25 11:55:12,208191,
|
93
|
+
:baremsg=>"is due to run",
|
94
|
+
:level=>"INFO"
|
95
|
+
}
|
96
|
+
},
|
97
|
+
:logtypes=>["syslog", "json"],
|
98
|
+
:id=>"c693c674-0d7d-11e3-80e9-20ae90200ddd"
|
99
|
+
}]
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
* `total_events` - Total number of matching events for the entire time range
|
104
|
+
* `page` - Which page of the result set
|
105
|
+
* `tags` - An Array of any tags associated with the event
|
106
|
+
* `timestamp` - See [timestamps](https://www.loggly.com/docs/timestamps/) to understand how a reference timestamps is derived.
|
107
|
+
* `logmsg` - The message portion of the log event. (Any headers aren't included.)
|
108
|
+
* `event` - Any parsed fields are included.
|
109
|
+
* `logtypes` - An array of [log types](https://www.loggly.com/docs/log-types/) that were detected.
|
110
|
+
* `id` - Loggly's event ID.
|
111
|
+
|
112
|
+
Try the following to get an array of all the event attributes:
|
113
|
+
|
114
|
+
events = Loggly::Event.all
|
115
|
+
events.collect {|event| event.attributes}
|
116
|
+
|
117
|
+
## TODO
|
118
|
+
|
119
|
+
1. Sending Data
|
120
|
+
2. Retrieve Account Information
|
121
|
+
3. Field Search
|
122
|
+
4. `OR`, `NOT` and `TO` search functionality
|
123
|
+
5. Filter Search by field
|
124
|
+
6. Command Line Tools
|
125
|
+
|
126
|
+
|
127
|
+
## Contributing
|
128
|
+
|
129
|
+
1. Fork it ( http://github.com/<my-github-username>/loggly/fork )
|
130
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
131
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
132
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
133
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/loggly
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'pry'
|
5
|
+
require 'trollop'
|
6
|
+
|
7
|
+
require File.expand_path('../../lib/loggly', __FILE__)
|
8
|
+
|
9
|
+
opts = Trollop::options do
|
10
|
+
opt :uri, "Loggly URI", :type => :string
|
11
|
+
opt :username, "Loggly Client Username", :type => :string
|
12
|
+
opt :password, "Loggly Client Password", :type => :string
|
13
|
+
end
|
14
|
+
|
15
|
+
Loggly.connect(opts)
|
16
|
+
|
17
|
+
@events = begin
|
18
|
+
Loggly::Event.all
|
19
|
+
rescue Exception => e
|
20
|
+
Loggly.logger.debug e.message
|
21
|
+
Loggly.logger.debug e.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
|
24
|
+
pry.binding
|
data/lib/loggly.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'logger'
|
3
|
+
require 'faraday'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'faraday_middleware/multi_json'
|
7
|
+
require 'multi_xml'
|
8
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
9
|
+
require 'active_support/core_ext/object/blank'
|
10
|
+
require 'active_support/core_ext/module'
|
11
|
+
require 'active_support/inflector'
|
12
|
+
require 'active_support/notifications'
|
13
|
+
require 'loggly/version'
|
14
|
+
require 'loggly/exceptions'
|
15
|
+
require 'loggly/logging'
|
16
|
+
require 'loggly/connection'
|
17
|
+
require 'loggly/request'
|
18
|
+
require 'loggly/response'
|
19
|
+
require 'loggly/model'
|
20
|
+
require 'loggly/remote_model'
|
21
|
+
require 'loggly/middleware/loggly_response_middleware'
|
22
|
+
|
23
|
+
module Loggly
|
24
|
+
autoload :Event, 'loggly/models/event'
|
25
|
+
autoload :Search, 'loggly/models/search'
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
def connection
|
29
|
+
@connection ? @connection : (raise LogglyConnectionException)
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect(config = {})
|
33
|
+
@connection = Connection.new(:uri => config[:uri], :username => config[:username], :password => config[:password])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
extend ClassMethods
|
38
|
+
extend Logging
|
39
|
+
|
40
|
+
#MultiJson.use :yajl
|
41
|
+
#Faraday.default_adapter = :excon
|
42
|
+
|
43
|
+
Faraday::Response.register_middleware :loggly_response => lambda { LogglyResponseMiddleware }
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveSupport::Notifications.subscribe('request.faraday') do |name, start_time, end_time, _, env|
|
47
|
+
url = env[:url]
|
48
|
+
http_method = env[:method].to_s.upcase
|
49
|
+
duration = end_time - start_time
|
50
|
+
Loggly.logger.info '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration]
|
51
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Connection
|
3
|
+
|
4
|
+
USER_AGENT = "loggly-client v#{Loggly::VERSION}"
|
5
|
+
|
6
|
+
attr_accessor :options, :faraday
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
@faraday = self.create_faraday(@options[:uri], @options[:username], @options[:password]) if @options[:uri]
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_faraday(uri, username = nil, password = nil)
|
14
|
+
@faraday = Faraday.new uri do |c|
|
15
|
+
c.headers['User-Agent'] = USER_AGENT
|
16
|
+
|
17
|
+
c.request :basic_auth, username, password unless (username.blank? || password.blank?)
|
18
|
+
c.request :multipart
|
19
|
+
c.request :url_encoded
|
20
|
+
c.request :multi_json
|
21
|
+
|
22
|
+
c.response :xml, :content_type => /\bxml$/
|
23
|
+
c.response :multi_json, symbolize_keys: true, :content_type => /\bjson$/
|
24
|
+
c.response :loggly_response
|
25
|
+
c.response :logger, Loggly.logger
|
26
|
+
|
27
|
+
c.use :instrumentation
|
28
|
+
c.adapter Faraday.default_adapter
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def request(method, path, params, options, &callback)
|
33
|
+
sent_at = nil
|
34
|
+
|
35
|
+
response = @faraday.send(method) { |request|
|
36
|
+
sent_at = Time.now
|
37
|
+
request = config_request(request, method, path, params, options)
|
38
|
+
}.on_complete { |env|
|
39
|
+
env[:total_time] = Time.now.utc.to_f - sent_at.utc.to_f if sent_at
|
40
|
+
env[:request_params] = params
|
41
|
+
env[:request_options] = options
|
42
|
+
callback.call(env) if callback
|
43
|
+
}
|
44
|
+
|
45
|
+
response
|
46
|
+
end
|
47
|
+
|
48
|
+
def config_request(request, method, path, params, options)
|
49
|
+
case method.to_sym
|
50
|
+
when :delete, :get
|
51
|
+
request.url(path, params)
|
52
|
+
when :post, :put
|
53
|
+
request.path = path
|
54
|
+
request.body = params unless params.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
request
|
58
|
+
end
|
59
|
+
|
60
|
+
def get(path, params={}, options={}, &callback)
|
61
|
+
request(:get, path, params, options, &callback)
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete(path, params={}, options={}, &callback)
|
65
|
+
request(:delete, path, params, options, &callback)
|
66
|
+
end
|
67
|
+
|
68
|
+
def post(path, params={}, options={}, &callback)
|
69
|
+
request(:post, path, params, options, &callback)
|
70
|
+
end
|
71
|
+
|
72
|
+
def put(path, params={}, options={}, &callback)
|
73
|
+
request(:put, path, params, options, &callback)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Loggly
|
2
|
+
class LogglyException < StandardError; end
|
3
|
+
class UnexpectedHTTPException < LogglyException; end
|
4
|
+
class PermissionDeniedException < LogglyException; end
|
5
|
+
class NonExistentRecord < LogglyException; end
|
6
|
+
class LogglyConnectionException < LogglyException; end
|
7
|
+
class LogglyResponseException < LogglyException; end
|
8
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Loggly
|
2
|
+
module Logging
|
3
|
+
def logger=(logger)
|
4
|
+
@logger = logger
|
5
|
+
end
|
6
|
+
|
7
|
+
def logger
|
8
|
+
@logger ||= init_logger(STDOUT, :debug)
|
9
|
+
end
|
10
|
+
|
11
|
+
def init_logger(io, level)
|
12
|
+
logger = unless io
|
13
|
+
Logger.new(STDOUT)
|
14
|
+
else
|
15
|
+
Logger.new(io)
|
16
|
+
end
|
17
|
+
|
18
|
+
if level == :debug
|
19
|
+
logger.level = Logger::DEBUG
|
20
|
+
else
|
21
|
+
logger.level = Logger::INFO
|
22
|
+
end
|
23
|
+
|
24
|
+
logger
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Loggly
|
2
|
+
class LogglyResponseMiddleware < Faraday::Response::Middleware
|
3
|
+
include Loggly::Logging
|
4
|
+
|
5
|
+
ERROR_STATUSES = (400...600)
|
6
|
+
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status]
|
9
|
+
when 401
|
10
|
+
raise PermissionDeniedException
|
11
|
+
when 404
|
12
|
+
raise NonExistentRecord
|
13
|
+
when 0
|
14
|
+
raise UnexpectedHTTPException, "recieved an unexpected HTTP response code #{env[:status]}"
|
15
|
+
when ERROR_STATUSES
|
16
|
+
raise UnexpectedHTTPException, "recieved an unexpected HTTP response code #{env[:status]}"
|
17
|
+
end
|
18
|
+
|
19
|
+
env
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/loggly/model.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Model
|
3
|
+
include Logging
|
4
|
+
|
5
|
+
METADATA_KEYS = {}
|
6
|
+
|
7
|
+
attr_accessor :attributes, :response
|
8
|
+
|
9
|
+
def initialize(attributes = {})
|
10
|
+
@attributes = OpenStruct.new(attributes)
|
11
|
+
@response = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
@attributes.marshal_dump
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(pretty = false)
|
19
|
+
MultiJson.dump(self.to_hash, :pretty => pretty)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_log(options = {})
|
23
|
+
self.to_json(true)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
|
28
|
+
def from_hash(h)
|
29
|
+
new h
|
30
|
+
end
|
31
|
+
|
32
|
+
def from_json(s)
|
33
|
+
from_hash MultiJson.load(s, :symbolize_keys => true)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
extend ClassMethods
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Event < RemoteModel
|
3
|
+
|
4
|
+
METADATA_KEYS = {
|
5
|
+
:total_count => :total_events,
|
6
|
+
:current_page => :page,
|
7
|
+
}
|
8
|
+
|
9
|
+
set_resource_attributes({
|
10
|
+
:path_base => 'apiv2/',
|
11
|
+
:collection_name => 'events',
|
12
|
+
:index_method => 'events',
|
13
|
+
:path_ext => '',
|
14
|
+
:request_options => {
|
15
|
+
}
|
16
|
+
})
|
17
|
+
|
18
|
+
def initialize(attributes = {})
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.all(conditions = {}, options = {}, &callback)
|
23
|
+
conditions[:order] ||= "desc"
|
24
|
+
conditions[:from] ||= "-24h"
|
25
|
+
conditions[:until] ||= "now"
|
26
|
+
|
27
|
+
unless rsid = options[:rsid]
|
28
|
+
search = Search.create!(conditions, options)
|
29
|
+
rsid = search.attributes.id
|
30
|
+
end
|
31
|
+
|
32
|
+
super({:rsid => rsid}, options, &callback)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Search < RemoteModel
|
3
|
+
|
4
|
+
set_resource_attributes({
|
5
|
+
:path_base => 'apiv2/',
|
6
|
+
:collection_name => 'rsid',
|
7
|
+
:index_method => 'search',
|
8
|
+
:path_ext => '',
|
9
|
+
:request_options => {
|
10
|
+
}
|
11
|
+
})
|
12
|
+
|
13
|
+
def initialize(attributes = {})
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create!(conditions = {}, options = {}, &callback)
|
18
|
+
options.merge!(:klass => self)
|
19
|
+
params = prepare_params(conditions)
|
20
|
+
params[:size] = (options[:per_page] ||= @resource_attributes[:per_page])
|
21
|
+
params[:page] = (options[:page] ||= 0)
|
22
|
+
|
23
|
+
response = Request.new(@resource_attributes, :get, [path_base, index_method], path_ext, params, options).execute(Loggly.connection)
|
24
|
+
|
25
|
+
model = response.to_model
|
26
|
+
|
27
|
+
callback.call(model) if callback
|
28
|
+
|
29
|
+
model
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Loggly
|
2
|
+
class RemoteModel < Model
|
3
|
+
|
4
|
+
DEFAULT_RESOURCE_ATTRIBUTES = {
|
5
|
+
:path_base => nil,
|
6
|
+
:path_ext => nil,
|
7
|
+
:index_method => nil,
|
8
|
+
:collection_name => '',
|
9
|
+
:per_page => 25,
|
10
|
+
:request_options => {}
|
11
|
+
}
|
12
|
+
|
13
|
+
@resource_attributes = DEFAULT_RESOURCE_ATTRIBUTES
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
attr_reader :resource_attributes
|
17
|
+
|
18
|
+
def path_ext;@resource_attributes[:path_ext];end
|
19
|
+
def index_method;@resource_attributes[:index_method];end
|
20
|
+
def collection_name;@resource_attributes[:collection_name];end
|
21
|
+
|
22
|
+
def set_resource_attributes(ra)
|
23
|
+
@resource_attributes = DEFAULT_RESOURCE_ATTRIBUTES.merge(ra)
|
24
|
+
end
|
25
|
+
|
26
|
+
def path_base(params = {})
|
27
|
+
pb = @resource_attributes[:path_base] || File.join('/', @resource_attributes[:collection_name])
|
28
|
+
params.each { |k,v| pb.gsub!(":#{k}", v) } unless params.blank?
|
29
|
+
pb
|
30
|
+
end
|
31
|
+
|
32
|
+
def all(conditions = {}, options = {}, &callback)
|
33
|
+
options = options.merge(:klass => self)
|
34
|
+
params = conditions
|
35
|
+
params[:size] = (options[:per_page] ||= @resource_attributes[:per_page])
|
36
|
+
params[:page] = (options[:page] ||= 0)
|
37
|
+
|
38
|
+
response = Request.new(@resource_attributes, :get, [path_base, index_method], path_ext, params, options).execute(Loggly.connection)
|
39
|
+
models = response.to_models
|
40
|
+
|
41
|
+
callback.call(models) if callback
|
42
|
+
|
43
|
+
models
|
44
|
+
end
|
45
|
+
|
46
|
+
def prepare_params(conditions = {}, options = {})
|
47
|
+
params = {}
|
48
|
+
|
49
|
+
params[:q] = if conditions[:q].kind_of?(Hash)
|
50
|
+
conditions[:q].map { |condition| condition.join(':') }.join(' AND ')
|
51
|
+
else
|
52
|
+
'*'
|
53
|
+
end
|
54
|
+
|
55
|
+
params
|
56
|
+
end
|
57
|
+
|
58
|
+
def where(conditions = {}, options = {}, &callback)
|
59
|
+
self.all(conditions, options, &callback)
|
60
|
+
end
|
61
|
+
|
62
|
+
def find(id, options = {}, &callback)
|
63
|
+
options.merge(:klass => self)
|
64
|
+
|
65
|
+
response = Request.new(@resource_attributes, :get, [path_base, id.to_s], path_ext, {}, options).execute(Loggly.connection)
|
66
|
+
model = response.to_model
|
67
|
+
|
68
|
+
callback.call(models) if callback
|
69
|
+
|
70
|
+
model
|
71
|
+
end
|
72
|
+
|
73
|
+
def create!(attributes = {}, options = {}, &callback)
|
74
|
+
raise NotImplementedError
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
extend ClassMethods
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Request
|
3
|
+
|
4
|
+
attr_accessor :resource_attributes, :method, :path_parts, :path_ext, :params, :klass, :options
|
5
|
+
|
6
|
+
def initialize(resource_attributes, method, path_parts, path_ext, params = {}, options = {})
|
7
|
+
@resource_attributes, @method, @path_parts, @path_ext, @params, @options = resource_attributes, method, path_parts, path_ext, params, options
|
8
|
+
@klass = @options[:klass]
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(connection)
|
12
|
+
self.build_params!
|
13
|
+
response = Response.new(self, connection.send(@method, self.build_path(@path_parts, @path_ext), @params, @options))
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_params!
|
17
|
+
@params ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_path(parts = [], ext = '.json')
|
21
|
+
parts.compact!
|
22
|
+
parts.map!{ |p| p.to_s }
|
23
|
+
|
24
|
+
"#{File.join(parts)}#{ext}"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Loggly
|
2
|
+
class Response
|
3
|
+
|
4
|
+
METADATA_KEYS = {
|
5
|
+
:total_count => :total_count,
|
6
|
+
:current_page => :current_page,
|
7
|
+
:per_page => :per_page,
|
8
|
+
:offset => :offset,
|
9
|
+
:total_pages => :total_pages
|
10
|
+
}
|
11
|
+
|
12
|
+
attr_accessor :request, :faraday_response, :metadata_keys
|
13
|
+
|
14
|
+
def initialize(request, faraday_response)
|
15
|
+
@request = request
|
16
|
+
@faraday_response = faraday_response
|
17
|
+
@metadata_keys = METADATA_KEYS
|
18
|
+
add_metadata_keys(@request.klass::METADATA_KEYS) if defined? @request.klass::METADATA_KEYS
|
19
|
+
end
|
20
|
+
|
21
|
+
def env
|
22
|
+
@faraday_response.env
|
23
|
+
end
|
24
|
+
|
25
|
+
def status
|
26
|
+
self.env[:status]
|
27
|
+
end
|
28
|
+
|
29
|
+
def error_status?
|
30
|
+
(400...600).include? self.status
|
31
|
+
end
|
32
|
+
|
33
|
+
def body
|
34
|
+
self.env[:body]
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_metadata_keys(keys = {})
|
38
|
+
@metadata_keys.merge!(keys)
|
39
|
+
end
|
40
|
+
|
41
|
+
def metadata
|
42
|
+
return @metadata if defined?(@metadata)
|
43
|
+
|
44
|
+
if status == 200 && self.body.kind_of?(Hash)
|
45
|
+
@metadata = {}.with_indifferent_access
|
46
|
+
|
47
|
+
@metadata_keys.each do |k,v|
|
48
|
+
if self.body.has_key?(v)
|
49
|
+
@metadata[k] = self.body[v]
|
50
|
+
elsif self.request.options.has_key?(k)
|
51
|
+
@metadata[k] = self.request.options[v]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
@metadata
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def pages_left
|
60
|
+
if self.metadata && self.metadata[:current_page] && self.metadata[:total_pages]
|
61
|
+
self.metadata[:total_pages] - self.metadata[:current_page]
|
62
|
+
elsif self.metadata && self.metadata[:current_page] && self.metadata[:total_pages].nil?
|
63
|
+
self.total_pages - self.metadata[:current_page]
|
64
|
+
else
|
65
|
+
0
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def current_page
|
70
|
+
self.metadata[:current_page] if self.metadata
|
71
|
+
end
|
72
|
+
|
73
|
+
def total_pages
|
74
|
+
if self.metadata && !self.metadata[:total_pages].nil?
|
75
|
+
self.metadata[:total_pages]
|
76
|
+
else
|
77
|
+
self.metadata[:total_count] / self.metadata[:per_page]
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def pages_left?
|
83
|
+
self.current_page && self.total_pages ? (self.current_page < self.total_pages) : false
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_models(&blk)
|
87
|
+
self.build_models(@request.resource_attributes[:collection_name], @request.klass, &blk)
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_model
|
91
|
+
self.build_model(@request.resource_attributes[:collection_name], @request.klass)
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_models(collection_name, klass, &blk)
|
95
|
+
raise LogglyResponseException, 'could not create Models from Response' if self.error_status?
|
96
|
+
|
97
|
+
models = []
|
98
|
+
|
99
|
+
self.body[collection_name.to_sym].each do |h|
|
100
|
+
if r = h[collection_name.singularize.to_sym]
|
101
|
+
m = klass.send :from_hash, r
|
102
|
+
m.response = self
|
103
|
+
models << m
|
104
|
+
blk.call(m) if blk
|
105
|
+
else
|
106
|
+
next
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
models
|
111
|
+
end
|
112
|
+
|
113
|
+
def build_model(collection_name, klass)
|
114
|
+
raise LogglyResponseException, 'could not create Model from Response' if self.error_status?
|
115
|
+
|
116
|
+
model = nil
|
117
|
+
|
118
|
+
if r = self.body[collection_name.singularize.to_sym]
|
119
|
+
model = klass.send :from_hash, r
|
120
|
+
model.response = self
|
121
|
+
end
|
122
|
+
|
123
|
+
model
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
data/loggly.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'loggly/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "loggly-rb"
|
8
|
+
spec.version = Loggly::VERSION
|
9
|
+
spec.authors = ["Keith Larrimore", "Brendon Harris"]
|
10
|
+
spec.email = ["klarrimore@icehook.com", "bharris@icehook.com"]
|
11
|
+
spec.summary = %q{Loggly Ruby Client Library}
|
12
|
+
spec.description = %q{Loggly Ruby Client Library}
|
13
|
+
spec.homepage = "https://github.com/icehook/loggly"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
23
|
+
spec.add_development_dependency 'rspec', '>= 2.13.0'
|
24
|
+
spec.add_development_dependency 'ffaker', '~> 1.15.0'
|
25
|
+
spec.add_development_dependency 'machinist', '~> 2.0'
|
26
|
+
spec.add_development_dependency 'webmock', '~> 1.9.3'
|
27
|
+
spec.add_development_dependency 'guard-rspec', '~> 2.5.0'
|
28
|
+
spec.add_development_dependency 'rb-fsevent', '~> 0.9.3'
|
29
|
+
spec.add_development_dependency 'simplecov', '~> 0.7.1'
|
30
|
+
spec.add_runtime_dependency 'pry', '~> 0.9.12'
|
31
|
+
spec.add_runtime_dependency 'activesupport', '>= 3.2.15'
|
32
|
+
spec.add_runtime_dependency 'faraday', '~> 0.9.0'
|
33
|
+
spec.add_runtime_dependency 'faraday_middleware', '~> 0.9.1'
|
34
|
+
spec.add_runtime_dependency 'faraday_middleware-multi_json', '~> 0.0.6'
|
35
|
+
spec.add_runtime_dependency 'multi_xml', '~> 0.5.3'
|
36
|
+
spec.add_runtime_dependency 'trollop', '~> 2.0.0'
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,290 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loggly-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Keith Larrimore
|
8
|
+
- Brendon Harris
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-06-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.5'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.5'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 2.13.0
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.13.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: ffaker
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.15.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.15.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: machinist
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: webmock
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.9.3
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.9.3
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: guard-rspec
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 2.5.0
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 2.5.0
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rb-fsevent
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 0.9.3
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.9.3
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: simplecov
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 0.7.1
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 0.7.1
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: pry
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 0.9.12
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 0.9.12
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: activesupport
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 3.2.15
|
161
|
+
type: :runtime
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: 3.2.15
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: faraday
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 0.9.0
|
175
|
+
type: :runtime
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - "~>"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: 0.9.0
|
182
|
+
- !ruby/object:Gem::Dependency
|
183
|
+
name: faraday_middleware
|
184
|
+
requirement: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - "~>"
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: 0.9.1
|
189
|
+
type: :runtime
|
190
|
+
prerelease: false
|
191
|
+
version_requirements: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - "~>"
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: 0.9.1
|
196
|
+
- !ruby/object:Gem::Dependency
|
197
|
+
name: faraday_middleware-multi_json
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - "~>"
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: 0.0.6
|
203
|
+
type: :runtime
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: 0.0.6
|
210
|
+
- !ruby/object:Gem::Dependency
|
211
|
+
name: multi_xml
|
212
|
+
requirement: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - "~>"
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: 0.5.3
|
217
|
+
type: :runtime
|
218
|
+
prerelease: false
|
219
|
+
version_requirements: !ruby/object:Gem::Requirement
|
220
|
+
requirements:
|
221
|
+
- - "~>"
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: 0.5.3
|
224
|
+
- !ruby/object:Gem::Dependency
|
225
|
+
name: trollop
|
226
|
+
requirement: !ruby/object:Gem::Requirement
|
227
|
+
requirements:
|
228
|
+
- - "~>"
|
229
|
+
- !ruby/object:Gem::Version
|
230
|
+
version: 2.0.0
|
231
|
+
type: :runtime
|
232
|
+
prerelease: false
|
233
|
+
version_requirements: !ruby/object:Gem::Requirement
|
234
|
+
requirements:
|
235
|
+
- - "~>"
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: 2.0.0
|
238
|
+
description: Loggly Ruby Client Library
|
239
|
+
email:
|
240
|
+
- klarrimore@icehook.com
|
241
|
+
- bharris@icehook.com
|
242
|
+
executables:
|
243
|
+
- loggly
|
244
|
+
extensions: []
|
245
|
+
extra_rdoc_files: []
|
246
|
+
files:
|
247
|
+
- ".gitignore"
|
248
|
+
- Gemfile
|
249
|
+
- LICENSE.txt
|
250
|
+
- README.md
|
251
|
+
- Rakefile
|
252
|
+
- bin/loggly
|
253
|
+
- lib/loggly.rb
|
254
|
+
- lib/loggly/connection.rb
|
255
|
+
- lib/loggly/exceptions.rb
|
256
|
+
- lib/loggly/logging.rb
|
257
|
+
- lib/loggly/middleware/loggly_response_middleware.rb
|
258
|
+
- lib/loggly/model.rb
|
259
|
+
- lib/loggly/models/event.rb
|
260
|
+
- lib/loggly/models/search.rb
|
261
|
+
- lib/loggly/remote_model.rb
|
262
|
+
- lib/loggly/request.rb
|
263
|
+
- lib/loggly/response.rb
|
264
|
+
- lib/loggly/version.rb
|
265
|
+
- loggly.gemspec
|
266
|
+
homepage: https://github.com/icehook/loggly
|
267
|
+
licenses:
|
268
|
+
- MIT
|
269
|
+
metadata: {}
|
270
|
+
post_install_message:
|
271
|
+
rdoc_options: []
|
272
|
+
require_paths:
|
273
|
+
- lib
|
274
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
279
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
|
+
requirements:
|
281
|
+
- - ">="
|
282
|
+
- !ruby/object:Gem::Version
|
283
|
+
version: '0'
|
284
|
+
requirements: []
|
285
|
+
rubyforge_project:
|
286
|
+
rubygems_version: 2.2.2
|
287
|
+
signing_key:
|
288
|
+
specification_version: 4
|
289
|
+
summary: Loggly Ruby Client Library
|
290
|
+
test_files: []
|