slack_log_device 1.0.0

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: 138ff680ce85491730409fffa3ffd0f863d21fdd
4
+ data.tar.gz: 7a74013420ab719a33a9040ed538218a39fcfb7d
5
+ SHA512:
6
+ metadata.gz: 94e144e14e8ac799a3255ad22aa0397352f0deba1dfb370f9df43fed6fb459498a1baba896021cf44e4a64de8e02eb27d8e63c0e5c96e58adc694c37491f50d4
7
+ data.tar.gz: 7dbee60ae209b3555f022c86f7ce23b03f0f364919e75337e751f1d117323e4dd6d4437f4593b8391b093bf5e589cb839e5d3a1a101adb8810fa1e659e873813
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ /.bundle/
3
+ /.ruby-version
4
+ /Gemfile.lock
5
+ /pkg/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --order random
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 Alexis Toulotte
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.mdown ADDED
@@ -0,0 +1,30 @@
1
+ # SlackLogDevice
2
+
3
+ LogDevice implementation that post logs on a Slack channel.
4
+
5
+ ## Setup
6
+
7
+ Just add this into your `Gemfile`:
8
+
9
+ ```ruby
10
+ gem 'slack_log_device'
11
+ ```
12
+
13
+ Then, just run a `bundle install`.
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ require 'slack_log_device'
19
+
20
+ logger = Logger.new(SlackLogDevice.new(webhook_url: 'https://hooks.slack.com/services/...', username: 'MyApp'))
21
+ logger.level = Logger::INFO
22
+ logger.warn('BAM!')
23
+ ```
24
+
25
+ Then, the logged message will be writen to webhook's configured channel.
26
+
27
+ ## Executing test suite
28
+
29
+ This project is fully tested with [Rspec 3](http://github.com/rspec/rspec).
30
+ Just run `bundle exec rake` (after a `bundle install`).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc 'Default: runs specs.'
7
+ task default: :spec
8
+
9
+ desc 'Run all specs in spec directory.'
10
+ RSpec::Core::RakeTask.new(:spec)
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,45 @@
1
+ require 'active_support/core_ext/hash'
2
+ require 'active_support/core_ext/string'
3
+ require 'httparty'
4
+ require 'logger'
5
+
6
+ class SlackLogDevice
7
+
8
+ attr_reader :timeout, :username, :webhook_url
9
+
10
+ def initialize(options = {})
11
+ options.assert_valid_keys(:timeout, :username, :webhook_url)
12
+ self.timeout = options.key?(:timeout) ? options[:timeout] : 5
13
+ self.username = options[:username]
14
+ self.webhook_url = options[:webhook_url]
15
+ end
16
+
17
+ def close
18
+ # Does nothing, this method must exist to consider the LogDevice as an IO.
19
+ end
20
+
21
+ def timeout=(value)
22
+ timeout = Integer(value) rescue nil
23
+ raise ArgumentError.new("Invalid timeout: #{value.inspect}") if timeout.nil?
24
+ @timeout = timeout
25
+ end
26
+
27
+ def username=(value)
28
+ @username = value.to_s.squish.presence
29
+ end
30
+
31
+ def webhook_url=(value)
32
+ raise ArgumentError.new('Webhook URL must be specified') if value.blank?
33
+ uri = URI(value.to_s) rescue nil
34
+ raise ArgumentError.new("Invalid Webhook URL: #{value.inspect}") if uri.nil? || !uri.is_a?(URI::HTTP)
35
+ @webhook_url = uri.to_s
36
+ end
37
+
38
+ def write(message)
39
+ data = { 'text' => message.to_s }
40
+ data['username'] = username if username.present?
41
+ HTTParty.post(webhook_url, body: data.to_json, headers: { 'Content-Type': 'application/json' }, timeout: timeout)
42
+ nil
43
+ end
44
+
45
+ end
@@ -0,0 +1,25 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'slack_log_device'
3
+ s.version = File.read("#{File.dirname(__FILE__)}/VERSION").strip
4
+ s.platform = Gem::Platform::RUBY
5
+ s.author = 'Alexis Toulotte'
6
+ s.email = 'al@alweb.org'
7
+ s.homepage = 'https://github.com/alexistoulotte/slack_log_device'
8
+ s.summary = 'LogDevice for Slack'
9
+ s.description = 'LogDevice implementation that post logs on a Slack channel'
10
+ s.license = 'MIT'
11
+
12
+ s.rubyforge_project = 'slack_log_device'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_dependency 'activesupport', '>= 5.0.0', '< 6.0.0'
20
+ s.add_dependency 'httparty', '>= 0.14.0', '< 0.15.0'
21
+
22
+ s.add_development_dependency 'byebug', '>= 9.0.0', '< 10.0.0'
23
+ s.add_development_dependency 'rake', '>= 12.0.0', '< 13.0.0'
24
+ s.add_development_dependency 'rspec', '>= 3.5.0', '< 3.6.0'
25
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackLogDevice do
4
+
5
+ let(:device) { SlackLogDevice.new(options) }
6
+ let(:logger) { Logger.new(device).tap { |logger| logger.level = Logger::INFO } }
7
+ let(:options) { { username: 'MyApp', webhook_url: 'https://hooks.slack.com/services/test' } }
8
+
9
+ describe '#close' do
10
+
11
+ it 'does nothing' do
12
+ expect {
13
+ device.close
14
+ }.not_to raise_error
15
+ end
16
+
17
+ end
18
+
19
+ describe '#initialize' do
20
+
21
+ it 'raise an error if an invalid option is given' do
22
+ expect {
23
+ SlackLogDevice.new(foo: 'bar')
24
+ }.to raise_error(ArgumentError, "Unknown key: :foo. Valid keys are: :timeout, :username, :webhook_url")
25
+ end
26
+
27
+ it 'raise an error if webhook option is not given' do
28
+ expect {
29
+ SlackLogDevice.new(options.except(:webhook_url))
30
+ }.to raise_error(ArgumentError, 'Webhook URL must be specified')
31
+ end
32
+
33
+ end
34
+
35
+ describe '#timeout' do
36
+
37
+ it 'is 5 by default' do
38
+ expect(device.timeout).to eq(5)
39
+ end
40
+
41
+ it 'can be specified' do
42
+ options[:timeout] = 10
43
+ expect(device.timeout).to be(10)
44
+ end
45
+
46
+ it 'raise an error if invalid' do
47
+ options[:timeout] = 'foo'
48
+ expect {
49
+ device
50
+ }.to raise_error(ArgumentError, 'Invalid timeout: "foo"')
51
+ end
52
+
53
+ it 'is default value if blank' do
54
+ options[:timeout] = ' '
55
+ expect {
56
+ device
57
+ }.to raise_error(ArgumentError, 'Invalid timeout: " "')
58
+ end
59
+
60
+ it 'raise an error if set as nil' do
61
+ expect {
62
+ device.timeout = nil
63
+ }.to raise_error(ArgumentError, 'Invalid timeout: nil')
64
+ end
65
+
66
+ it 'can be specified as string' do
67
+ options[:timeout] = '42'
68
+ expect(device.timeout).to eq(42)
69
+ end
70
+
71
+ it 'can be set' do
72
+ expect {
73
+ device.timeout = 15
74
+ }.to change { device.timeout }.from(5).to(15)
75
+ end
76
+
77
+ end
78
+
79
+ describe '#username' do
80
+
81
+ it 'is username set at initialization' do
82
+ expect(device.username).to eq('MyApp')
83
+ end
84
+
85
+ it 'is nil if not specified' do
86
+ device = SlackLogDevice.new(options.except(:username))
87
+ expect(device.username).to be_nil
88
+ end
89
+
90
+ it 'is squished' do
91
+ options[:username] = "John Doe\n "
92
+ expect(device.username).to eq('John Doe')
93
+ end
94
+
95
+ it 'is nil if blank' do
96
+ options[:username] = " \n"
97
+ expect(device.username).to be_nil
98
+ end
99
+
100
+ it 'can be set' do
101
+ expect {
102
+ device.username = 'John Doe'
103
+ }.to change { device.username }.from(options[:username]).to('John Doe')
104
+ end
105
+
106
+ end
107
+
108
+ describe '#webhook_url' do
109
+
110
+ it 'is webhook_url set at initialization' do
111
+ expect(device.webhook_url).to eq('https://hooks.slack.com/services/test')
112
+ end
113
+
114
+ it 'raise an error if invalid' do
115
+ options[:webhook_url] = 'foo'
116
+ expect {
117
+ device
118
+ }.to raise_error(ArgumentError, 'Invalid Webhook URL: "foo"')
119
+ end
120
+
121
+ it 'can be an HTTP URL' do
122
+ options[:webhook_url] = 'http://google.com'
123
+ expect(device.webhook_url).to eq('http://google.com')
124
+ end
125
+
126
+ it 'can be an HTTPs URL' do
127
+ options[:webhook_url] = 'https://google.com'
128
+ expect(device.webhook_url).to eq('https://google.com')
129
+ end
130
+
131
+ it 'raise an error if not an HTTP(s) url' do
132
+ options[:webhook_url] = 'ftp://google.com'
133
+ expect {
134
+ device
135
+ }.to raise_error(ArgumentError, 'Invalid Webhook URL: "ftp://google.com"')
136
+ end
137
+
138
+ it 'can be set' do
139
+ expect {
140
+ device.webhook_url = 'http://google.com'
141
+ }.to change { device.webhook_url }.from(options[:webhook_url]).to('http://google.com')
142
+ end
143
+
144
+ end
145
+
146
+ describe '#write' do
147
+
148
+ it 'sends a post to webhook URL with given given message and specified username' do
149
+ expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!', 'username' => options[:username] }.to_json, headers: { 'Content-Type': 'application/json' }, timeout: 5)
150
+ device.write('BAM!')
151
+ end
152
+
153
+ it 'returns nil' do
154
+ allow(HTTParty).to receive(:post)
155
+ expect(device.write('BAM!')).to be_nil
156
+ end
157
+
158
+ it 'does not send username if nil' do
159
+ options.delete(:username)
160
+ expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!' }.to_json, headers: { 'Content-Type': 'application/json' }, timeout: 5)
161
+ device.write('BAM!')
162
+ end
163
+
164
+ it 'does nothing if log level is lower than specified one' do
165
+ expect(HTTParty).not_to receive(:post)
166
+ logger.debug('BIM!')
167
+ end
168
+
169
+ it 'send HTTP request if log level is equal to specified one' do
170
+ expect(HTTParty).to receive(:post)
171
+ logger.info('BIM!')
172
+ end
173
+
174
+ it 'send HTTP request if log level is higher to specified one' do
175
+ expect(HTTParty).to receive(:post)
176
+ logger.warn('BIM!')
177
+ end
178
+
179
+ it 'use specified timeout' do
180
+ options[:timeout] = 12
181
+ expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!', 'username' => options[:username] }.to_json, headers: { 'Content-Type': 'application/json' }, timeout: 12)
182
+ device.write('BAM!')
183
+ end
184
+
185
+ end
186
+
187
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path("#{__dir__}/../lib/slack_log_device")
2
+ require 'byebug'
3
+
4
+ RSpec.configure do |config|
5
+ config.raise_errors_for_deprecations!
6
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slack_log_device
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexis Toulotte
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 6.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 5.0.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: httparty
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.14.0
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: 0.15.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.14.0
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: 0.15.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: byebug
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 9.0.0
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: 10.0.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 9.0.0
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: 10.0.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: rake
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 12.0.0
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: 13.0.0
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 12.0.0
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: 13.0.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: rspec
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 3.5.0
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: 3.6.0
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 3.5.0
110
+ - - "<"
111
+ - !ruby/object:Gem::Version
112
+ version: 3.6.0
113
+ description: LogDevice implementation that post logs on a Slack channel
114
+ email: al@alweb.org
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - Gemfile
122
+ - MIT-LICENSE
123
+ - README.mdown
124
+ - Rakefile
125
+ - VERSION
126
+ - lib/slack_log_device.rb
127
+ - slack_log_device.gemspec
128
+ - spec/slack_log_device_spec.rb
129
+ - spec/spec_helper.rb
130
+ homepage: https://github.com/alexistoulotte/slack_log_device
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project: slack_log_device
150
+ rubygems_version: 2.5.2
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: LogDevice for Slack
154
+ test_files:
155
+ - spec/slack_log_device_spec.rb
156
+ - spec/spec_helper.rb