slack_log_device 1.0.0

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 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