logcamp-ruby 0.0.2

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: ec6d69519bd75c04b0e19592c8e28374a393092c
4
+ data.tar.gz: 354aa85d380ccd42560de497d0fad7ac5455a6e7
5
+ SHA512:
6
+ metadata.gz: d582170ca196cab67cc6d00a48b68c3d288f908184ab9f1f4a6334441748a4fd1a56c3be30786eb0857e4257ab680fe9e79317c6b0e33d866f8483ef6820ad85
7
+ data.tar.gz: 35ebeda939707bcf79b1bdcec0c61c63b663bb50ba8f23cc43695d5249df0267fc12b826d1965d16bafb75d5fffa62da515664b2debb37b7a6dac5e34d01bd9d
@@ -0,0 +1,53 @@
1
+ # Logcamp::Ruby
2
+
3
+ [![Build Status](https://semaphoreapp.com/api/v1/projects/c6901197-8348-4906-a36b-af15503eef80/320811/badge.png)](https://semaphoreapp.com/olimart/logcamp-ruby--2)
4
+
5
+ Simple gem for communicating with external API. Heavily inspired by stripe gem.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'logcamp-ruby'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install logcamp-ruby
20
+
21
+ ## Usage
22
+
23
+ In your app
24
+
25
+ 1. Set token
26
+
27
+ ```ruby
28
+ Logcamp.token = ENV['LOGCAMP_TOKEN']
29
+ ```
30
+
31
+ 2. Send event
32
+
33
+ ```ruby
34
+ Logcamp::Event.create(
35
+ status: 'event status',
36
+ message: 'notification message',
37
+ date: '01/01/2015 14:30',
38
+ alert: true,
39
+ metadata: {
40
+ key1: value1,
41
+ key2: value2
42
+ }
43
+ )
44
+ ```
45
+
46
+ **For Sinatra app** you may need to add `require 'bundler/setup'`
47
+
48
+
49
+ ## Tests
50
+
51
+ ```ruby
52
+ rake test
53
+ ```
@@ -0,0 +1,145 @@
1
+ # Logcamp Ruby bindings
2
+ require "cgi"
3
+ require "set"
4
+ require "openssl"
5
+ require "json"
6
+ require "net/http"
7
+ require "uri"
8
+
9
+ # Version
10
+ require "logcamp/version"
11
+
12
+ # API operations
13
+ require "logcamp/api_operations/create"
14
+
15
+ # Resources
16
+ require "logcamp/logcamp_object"
17
+ require "logcamp/api_resource"
18
+ require "logcamp/event"
19
+
20
+ # Errors
21
+ require "logcamp/errors/logcamp_error"
22
+ require "logcamp/errors/api_error"
23
+ require "logcamp/errors/api_connection_error"
24
+ require "logcamp/errors/invalid_request_error"
25
+ require "logcamp/errors/invalid_metadata_error"
26
+ require "logcamp/errors/authentication_error"
27
+
28
+ module Logcamp
29
+ @api_base = "https://logcamp.herokuapp.com/api"
30
+
31
+ class << self
32
+ attr_accessor :token, :api_base, :verify_ssl_certs, :api_version
33
+ end
34
+
35
+ def self.api_url(url="")
36
+ @api_base + url
37
+ end
38
+
39
+ def self.request(method, url, token, params={}, headers={})
40
+ unless token ||= @token
41
+ raise AuthenticationError.new("No token provided")
42
+ end
43
+
44
+ if !params[:metadata].nil? && params[:metadata].class != Hash
45
+ raise InvalidMetadataError.new("Invalid metadata. Only key value pair is supported", params)
46
+ else
47
+ params[:metadata] = params[:metadata].to_json
48
+ end
49
+
50
+ url = api_url(url)
51
+
52
+ begin
53
+ uri = URI(url)
54
+ request = Net::HTTP::Post.new(uri) if method == :post
55
+
56
+ request["User-Agent"] = "Logcamp-ruby gem"
57
+ request["Authorization"] = "Token token=\"#{token}\""
58
+ request["Content-Type"] = "application/json"
59
+ request.body = params.to_json
60
+
61
+ http = Net::HTTP.new(uri.hostname, uri.port)
62
+
63
+ # see http://www.rubyinside.com/how-to-cure-nethttps-risky-default-https-behavior-4010.html
64
+ # for info about ssl verification
65
+
66
+ http.use_ssl = true if uri.scheme == "https"
67
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if uri.scheme == "https"
68
+
69
+ response = http.start {|h|
70
+ h.request(request)
71
+ }
72
+
73
+ # since http.request doesn't throw such exceptions, check them by status codes
74
+ handle_api_error(response.code, response.body)
75
+
76
+ rescue SocketError => e
77
+ handle_connection_error(e)
78
+ rescue NoMethodError => e
79
+ handle_connection_error(e)
80
+ rescue OpenSSL::SSL::SSLError => e
81
+ handle_connection_error(e)
82
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
83
+ handle_connection_error(e)
84
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
85
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, InvalidMetadataError => e
86
+ handle_connection_error(e)
87
+ end
88
+
89
+ [response, token]
90
+ end
91
+
92
+ def self.handle_connection_error(e)
93
+ case e
94
+ when SocketError
95
+ message = "Unexpected error when trying to connect to Logcamp."
96
+
97
+ when NoMethodError
98
+ message = "Unexpected HTTP response code"
99
+ when InvalidMetadataError
100
+ message = "Invalid metadata. Only key value pair is supported"
101
+ else
102
+ message = "Unexpected error communicating with Logcamp."
103
+ end
104
+
105
+ raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
106
+ end
107
+
108
+ def self.handle_api_error(rcode, rbody)
109
+ begin
110
+ error_obj = JSON.parse(rbody)
111
+ rescue JSON::ParserError
112
+ raise general_api_error(rcode, rbody)
113
+ end
114
+
115
+ case rcode
116
+ when 400, 404, 422
117
+ raise invalid_request_error error, rcode, rbody, error_obj
118
+ when 401
119
+ raise authentication_error error, rcode, rbody, error_obj
120
+ when 500
121
+ raise api_error error, rcode, rbody, error_obj
122
+ else
123
+ # raise api_error error, rcode, rbody, error_obj
124
+ end
125
+
126
+ end
127
+
128
+ def self.invalid_request_error(error, rcode, rbody, error_obj)
129
+ InvalidRequestError.new(error[:message], error[:param], rcode,
130
+ rbody, error_obj)
131
+ end
132
+
133
+ def self.authentication_error(error, rcode, rbody, error_obj)
134
+ AuthenticationError.new(error[:message], rcode, rbody, error_obj)
135
+ end
136
+
137
+ def self.api_error(error, rcode, rbody, error_obj)
138
+ APIError.new(error[:message], rcode, rbody, error_obj)
139
+ end
140
+
141
+ def self.general_api_error(rcode, rbody)
142
+ APIError.new("Invalid response object from API: #{rbody.inspect} " +
143
+ "(HTTP response code was #{rcode})", rcode, rbody)
144
+ end
145
+ end
@@ -0,0 +1,16 @@
1
+ module Logcamp
2
+ module APIOperations
3
+ module Create
4
+ module ClassMethods
5
+ def create(params={}, token=nil)
6
+ response, token = Logcamp.request(:post, self.url, token, params)
7
+ response
8
+ end
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Logcamp
2
+ class APIResource < LogcampObject
3
+ def self.class_name
4
+ self.name.split('::')[-1]
5
+ end
6
+
7
+ def self.url()
8
+ if self == APIResource
9
+ raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses)')
10
+ end
11
+ "/#{CGI.escape(class_name.downcase)}s"
12
+ end
13
+
14
+ def url
15
+ unless id = self['id']
16
+ raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", 'id')
17
+ end
18
+ "#{self.class.url}/#{CGI.escape(id)}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module Logcamp
2
+ class APIConnectionError < LogcampError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Logcamp
2
+ class APIError < LogcampError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Logcamp
2
+ class AuthenticationError < LogcampError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Logcamp
2
+ class InvalidMetadataError < LogcampError
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module Logcamp
2
+ class InvalidRequestError < LogcampError
3
+ attr_accessor :param
4
+
5
+ def initialize(message, param, http_status=nil, http_body=nil, json_body=nil)
6
+ super(message, http_status, http_body, json_body)
7
+ @param = param
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module Logcamp
2
+ class LogcampError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_status
5
+ attr_reader :http_body
6
+ attr_reader :json_body
7
+
8
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
+ @message = message
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ @json_body = json_body
13
+ end
14
+
15
+ def to_s
16
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
17
+ "#{status_string}#{@message}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Logcamp
2
+ class Event < APIResource
3
+ include Logcamp::APIOperations::Create
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Logcamp
2
+ class LogcampObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Logcamp
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path("../../test_helper", __FILE__)
2
+
3
+ module Logcamp
4
+ class EventTest < Test::Unit::TestCase
5
+ should "create should return status 201" do
6
+ response = Logcamp::Event.create(status: 'success', message: 'Event occured', alert: true, metadata: { date: Time.now })
7
+ assert_equal "201", response.code
8
+ end
9
+
10
+ should "raise Logcamp::AuthenticationError if no token provided" do
11
+ Logcamp.token = nil
12
+ assert_raises(Logcamp::AuthenticationError) {Logcamp::Event.create}
13
+ end
14
+
15
+ should "raise Logcamp::InvalidRequestError if not enough parameters" do
16
+ begin
17
+ rescue JSON::ParserError
18
+ assert_raises(Logcamp::InvalidRequestError) {Logcamp::Event.create}
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require "logcamp"
2
+ require "test/unit"
3
+ require "shoulda"
4
+
5
+ class Test::Unit::TestCase
6
+
7
+ setup do
8
+ Logcamp.token = "111"
9
+ end
10
+
11
+ teardown do
12
+ Logcamp.token = nil
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logcamp-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Olivier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.8.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: shoulda
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.4.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.4.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: ''
98
+ email:
99
+ - olivier@yafoy.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - README.md
105
+ - lib/logcamp.rb
106
+ - lib/logcamp/api_operations/create.rb
107
+ - lib/logcamp/api_resource.rb
108
+ - lib/logcamp/errors/api_connection_error.rb
109
+ - lib/logcamp/errors/api_error.rb
110
+ - lib/logcamp/errors/authentication_error.rb
111
+ - lib/logcamp/errors/invalid_metadata_error.rb
112
+ - lib/logcamp/errors/invalid_request_error.rb
113
+ - lib/logcamp/errors/logcamp_error.rb
114
+ - lib/logcamp/event.rb
115
+ - lib/logcamp/logcamp_object.rb
116
+ - lib/logcamp/version.rb
117
+ - test/logcamp/event_test.rb
118
+ - test/test_helper.rb
119
+ homepage: ''
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.4.3
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Gem to send events notification to logcamp central app.
143
+ test_files:
144
+ - test/logcamp/event_test.rb
145
+ - test/test_helper.rb