slack_log_device 4.0.1 → 4.0.2
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 +4 -4
- data/VERSION +1 -1
- data/lib/slack_log_device.rb +1 -1
- data/lib/slack_log_device/formatter.rb +2 -2
- data/slack_log_device.gemspec +1 -2
- metadata +3 -13
- data/.gitignore +0 -6
- data/.rspec +0 -2
- data/Gemfile +0 -3
- data/Rakefile +0 -10
- data/spec/slack_log_device/formatter_spec.rb +0 -285
- data/spec/slack_log_device_spec.rb +0 -553
- data/spec/spec_helper.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa496f8eaaa923412893876e4dc044c26d2d0064
|
4
|
+
data.tar.gz: b8fe6470d8864cd83fb17e462bdc59e0e75b4596
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c675155309e06685fb1ea2e83f81d8f3ec563b503f2b132ddf6070c7bc8c05a5dc96732afadf3cdb3569c1da50204a8fd9256c6554e4c4812a6227071986f9b
|
7
|
+
data.tar.gz: d4b68b6993c883600e93ea8d67c7751af7dd854f549badfd9949d2048efd9911db9ea417e52045887449c35ed55c06a6645912d06e74edf7f368a20595ab5bb5
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.0.
|
1
|
+
4.0.2
|
data/lib/slack_log_device.rb
CHANGED
@@ -30,7 +30,7 @@ class SlackLogDevice
|
|
30
30
|
self.timeout = options.key?(:timeout) ? options[:timeout] : 5
|
31
31
|
self.username = options[:username]
|
32
32
|
self.webhook_url = options[:webhook_url]
|
33
|
-
at_exit { flush }
|
33
|
+
at_exit { flush } unless Thread.current.key?(:__rspec)
|
34
34
|
end
|
35
35
|
|
36
36
|
def auto_flush?
|
@@ -9,7 +9,7 @@ class SlackLogDevice
|
|
9
9
|
def initialize(options = {}, &block)
|
10
10
|
options.assert_valid_keys(:extra_metadata)
|
11
11
|
@extra_metadata = options.key?(:extra_metadata) ? options[:extra_metadata] : {}
|
12
|
-
@
|
12
|
+
@message_converter = block_given? ? Proc.new(&block) : -> (message) { message }
|
13
13
|
end
|
14
14
|
|
15
15
|
def call(severity, datetime, progname, message)
|
@@ -44,7 +44,7 @@ class SlackLogDevice
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def convert_message(message)
|
47
|
-
@
|
47
|
+
@message_converter.call(message.to_s.strip).to_s.strip
|
48
48
|
end
|
49
49
|
|
50
50
|
def default_metadata(request)
|
data/slack_log_device.gemspec
CHANGED
@@ -9,8 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.description = 'LogDevice implementation that post logs on a Slack channel'
|
10
10
|
s.license = 'MIT'
|
11
11
|
|
12
|
-
s.files = `git ls-files`.split("\n")
|
13
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
|
+
s.files = `git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)'`.split("\n")
|
14
13
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
14
|
s.require_paths = ['lib']
|
16
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slack_log_device
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Toulotte
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -116,21 +116,14 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
-
- .gitignore
|
120
|
-
- .rspec
|
121
|
-
- Gemfile
|
122
119
|
- MIT-LICENSE
|
123
120
|
- README.mdown
|
124
|
-
- Rakefile
|
125
121
|
- VERSION
|
126
122
|
- lib/slack_log_device.rb
|
127
123
|
- lib/slack_log_device/debug_exceptions.rb
|
128
124
|
- lib/slack_log_device/formatter.rb
|
129
125
|
- lib/slack_log_device/set_request_in_thread.rb
|
130
126
|
- slack_log_device.gemspec
|
131
|
-
- spec/slack_log_device/formatter_spec.rb
|
132
|
-
- spec/slack_log_device_spec.rb
|
133
|
-
- spec/spec_helper.rb
|
134
127
|
homepage: https://github.com/alexistoulotte/slack_log_device
|
135
128
|
licenses:
|
136
129
|
- MIT
|
@@ -155,7 +148,4 @@ rubygems_version: 2.0.14.1
|
|
155
148
|
signing_key:
|
156
149
|
specification_version: 4
|
157
150
|
summary: LogDevice for Slack
|
158
|
-
test_files:
|
159
|
-
- spec/slack_log_device/formatter_spec.rb
|
160
|
-
- spec/slack_log_device_spec.rb
|
161
|
-
- spec/spec_helper.rb
|
151
|
+
test_files: []
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,285 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SlackLogDevice::Formatter do
|
4
|
-
|
5
|
-
let(:max_message_length) { SlackLogDevice::Formatter::MAX_MESSAGE_LENGTH }
|
6
|
-
|
7
|
-
describe '::MAX_MESSAGE_LENGTH' do
|
8
|
-
|
9
|
-
it 'is 4000' do
|
10
|
-
expect(SlackLogDevice::Formatter::MAX_MESSAGE_LENGTH).to be(4000)
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#call' do
|
16
|
-
|
17
|
-
context "with no block or metadata" do
|
18
|
-
|
19
|
-
let(:formatter) { SlackLogDevice::Formatter.new }
|
20
|
-
|
21
|
-
it 'returns a formatted message' do
|
22
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq('*`DEBUG`*: Hello World')
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'message is stripped' do
|
26
|
-
expect(formatter.call('DEBUG', Time.now, ' ', " \nHello World ")).to eq('*`DEBUG`*: Hello World')
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'message is converted to string' do
|
30
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 42)).to eq('*`DEBUG`*: 42')
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'includes progname if given' do
|
34
|
-
expect(formatter.call('DEBUG', Time.now, 'My App', 'Hello World')).to eq('*`DEBUG`* (*My App*): Hello World')
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'formats exception' do
|
38
|
-
exception = RuntimeError.new('BAM!')
|
39
|
-
exception.set_backtrace(['foo', 'bar'])
|
40
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred: BAM!\n\n```foo\nbar```")
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'formats exception with no message' do
|
44
|
-
exception = RuntimeError.new(' ')
|
45
|
-
exception.set_backtrace(['foo', 'bar'])
|
46
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred:\n\n```foo\nbar```")
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'formats exception with no backtrace' do
|
50
|
-
exception = RuntimeError.new('BAM!')
|
51
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred: BAM!")
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'strips exception message' do
|
55
|
-
exception = RuntimeError.new(" BAM! \n")
|
56
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred: BAM!")
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'message never exceed 4000 chars (without exception)' do
|
60
|
-
message = formatter.call('DEBUG', Time.now, nil, 'Bam' * (max_message_length / 2))
|
61
|
-
expect(message.size).to eq(max_message_length)
|
62
|
-
expect(message).to end_with('BamBa...')
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'message never exceed 4000 chars (with exception)' do
|
66
|
-
exception = RuntimeError.new('BAM!')
|
67
|
-
exception.set_backtrace(['a' * (max_message_length - 49)])
|
68
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
69
|
-
expect(message.size).to eq(max_message_length)
|
70
|
-
expect(message).to end_with("aaaaaa...```")
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'can be exactly 4000 chars with trace (without three dots)' do
|
74
|
-
exception = RuntimeError.new('BAM!')
|
75
|
-
exception.set_backtrace(['a' * (max_message_length - 50)])
|
76
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
77
|
-
expect(message.size).to eq(max_message_length)
|
78
|
-
expect(message).to end_with('a```')
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'does not add three dots if less than 4000' do
|
82
|
-
exception = RuntimeError.new('BAM!')
|
83
|
-
exception.set_backtrace(['a' * (max_message_length - 51)])
|
84
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
85
|
-
expect(message.size).to eq(max_message_length - 1)
|
86
|
-
expect(message).to end_with('a```')
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'does not format backtrace if message is too long' do
|
90
|
-
exception = RuntimeError.new('BAM!' * max_message_length)
|
91
|
-
exception.set_backtrace(['hello world'])
|
92
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
93
|
-
expect(message.size).to eq(max_message_length)
|
94
|
-
expect(message).not_to include('hello')
|
95
|
-
expect(message).not_to include('```')
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'message does not exceed 4000 if there is no backtrace' do
|
99
|
-
exception = RuntimeError.new('BAM!' * max_message_length)
|
100
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
101
|
-
expect(message.size).to eq(max_message_length)
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'does not formats a blank backtrace (due to large message)' do
|
105
|
-
exception = RuntimeError.new('a' * (max_message_length - 46))
|
106
|
-
exception.set_backtrace(['hello world'])
|
107
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
108
|
-
expect(message.size).to eq(max_message_length - 8)
|
109
|
-
expect(message).not_to include('```')
|
110
|
-
expect(message).to end_with('a')
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'can format a backtrace with just one char' do
|
114
|
-
exception = RuntimeError.new('a' * (max_message_length - 47))
|
115
|
-
exception.set_backtrace(['hello world'])
|
116
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
117
|
-
expect(message.size).to eq(max_message_length)
|
118
|
-
expect(message).to end_with("aaa\n\n```h```")
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'can format a backtrace with just one char and three dots' do
|
122
|
-
exception = RuntimeError.new('a' * (max_message_length - 50))
|
123
|
-
exception.set_backtrace(['hello world'])
|
124
|
-
message = formatter.call('DEBUG', Time.now, nil, exception)
|
125
|
-
expect(message.size).to eq(max_message_length)
|
126
|
-
expect(message).to end_with("aaa\n\n```h...```")
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
context 'if a block is given' do
|
132
|
-
|
133
|
-
let(:formatter) { SlackLogDevice::Formatter.new { |message| "#{message.reverse} Hey hoy" } }
|
134
|
-
|
135
|
-
it 'returns formatter message with block invoked' do
|
136
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq("*`DEBUG`*: dlroW olleH Hey hoy")
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'invokes block with stripped message' do
|
140
|
-
expect(formatter.call('DEBUG', Time.now, ' ', " Hello World \t")).to eq("*`DEBUG`*: dlroW olleH Hey hoy")
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'does not append block message if blank' do
|
144
|
-
formatter = SlackLogDevice.formatter { ' ' }
|
145
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq('*`DEBUG`*:')
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'converts block value to string' do
|
149
|
-
formatter = SlackLogDevice.formatter { 42 }
|
150
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq('*`DEBUG`*: 42')
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'is correct if block returns nil' do
|
154
|
-
formatter = SlackLogDevice.formatter { nil }
|
155
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq('*`DEBUG`*:')
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'strips block return value' do
|
159
|
-
formatter = SlackLogDevice.formatter { " hey \n" }
|
160
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq('*`DEBUG`*: hey')
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'includes progname if given' do
|
164
|
-
expect(formatter.call('DEBUG', Time.now, 'MyApp', 'Hello World')).to eq("*`DEBUG`* (*MyApp*): dlroW olleH Hey hoy")
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'formats exception' do
|
168
|
-
exception = RuntimeError.new('BAM!')
|
169
|
-
exception.set_backtrace(['foo', 'bar'])
|
170
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred: !MAB Hey hoy\n\n```foo\nbar```")
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'is correct with exception if block returns a blank message' do
|
174
|
-
formatter = SlackLogDevice.formatter { ' ' }
|
175
|
-
exception = RuntimeError.new('BAM!')
|
176
|
-
exception.set_backtrace(['foo', 'bar'])
|
177
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred:\n\n```foo\nbar```")
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'message never exceed 4000 chars (without exception)' do
|
181
|
-
message = formatter.call('DEBUG', Time.now, ' ', 'Hello World' * (max_message_length / 3))
|
182
|
-
expect(message.size).to eq(max_message_length)
|
183
|
-
expect(message).to end_with('olleHdlro...')
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'message never exceed 4000 chars (with exception)' do
|
187
|
-
exception = RuntimeError.new('BAM!')
|
188
|
-
exception.set_backtrace(['a' * max_message_length])
|
189
|
-
message = formatter.call('DEBUG', Time.now, 'My App', exception)
|
190
|
-
expect(message.size).to eq(max_message_length)
|
191
|
-
expect(message).to end_with("aaaaaa...```")
|
192
|
-
end
|
193
|
-
|
194
|
-
end
|
195
|
-
|
196
|
-
context 'with extra metadata' do
|
197
|
-
|
198
|
-
let(:extra_metadata) {{
|
199
|
-
'User ' => " `#{user}` ",
|
200
|
-
' Reversed user' => -> (options) { user.reverse },
|
201
|
-
}}
|
202
|
-
let(:formatter) { SlackLogDevice::Formatter.new(extra_metadata: extra_metadata) }
|
203
|
-
let(:user) { 'John' }
|
204
|
-
|
205
|
-
it 'returns a message formatted' do
|
206
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq("*`DEBUG`*: Hello World\n\n• *User*: `John`\n• *Reversed user*: nhoJ")
|
207
|
-
end
|
208
|
-
|
209
|
-
it 'returns a message formatted (with exception)' do
|
210
|
-
exception = RuntimeError.new('BAM!')
|
211
|
-
exception.set_backtrace(['a', 'b'])
|
212
|
-
message = formatter.call('DEBUG', Time.now, 'My App', exception)
|
213
|
-
expect(message).to eq("*`DEBUG`* (*My App*): A `RuntimeError` occurred: BAM!\n\n• *User*: `John`\n• *Reversed user*: nhoJ\n\n```a\nb```")
|
214
|
-
end
|
215
|
-
|
216
|
-
it 'extra metadata are not added if message is too long' do
|
217
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World' * max_message_length)).not_to include('•')
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'extra metadata are not added if message is too long (with exception)' do
|
221
|
-
exception = RuntimeError.new('BAM!' * max_message_length)
|
222
|
-
exception.set_backtrace(['a'])
|
223
|
-
message = formatter.call('DEBUG', Time.now, 'My App', exception)
|
224
|
-
expect(message).not_to include('•')
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'blocks of extra metadata is invoked with options containing exception' do
|
228
|
-
extra_metadata['Exception class'] = -> (options) { options[:exception].class.name }
|
229
|
-
exception = RuntimeError.new('BAM!')
|
230
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to include('• *Exception class*: RuntimeError')
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'blocks of extra metadata does not add exception option if not present' do
|
234
|
-
extra_metadata['Exception?'] = -> (options) { options.key?(:exception) ? 'Yes' : 'No' }
|
235
|
-
expect(formatter.call('DEBUG', Time.now, nil, 'Hello World')).to include("• *Exception?*: No")
|
236
|
-
end
|
237
|
-
|
238
|
-
end
|
239
|
-
|
240
|
-
context 'with request set in current thread' do
|
241
|
-
|
242
|
-
let(:exception) { RuntimeError.new('BAM!') }
|
243
|
-
let(:formatter) { SlackLogDevice::Formatter.new }
|
244
|
-
let(:request) { double(remote_addr: '127.0.0.1', user_agent: 'Mozilla', method: 'GET', url: 'http://google.com') }
|
245
|
-
|
246
|
-
before :each do
|
247
|
-
Thread.current[:slack_log_device_request] = request
|
248
|
-
end
|
249
|
-
|
250
|
-
after :each do
|
251
|
-
Thread.current[:slack_log_device_request] = nil
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'logs metadata' do
|
255
|
-
expect(formatter.call('DEBUG', Time.now, nil, exception)).to eq("*`DEBUG`*: A `RuntimeError` occurred: BAM!\n\n• *Method*: `GET`\n• *URL*: `http://google.com`\n• *Remote address*: `127.0.0.1`\n• *User-Agent*: `Mozilla`")
|
256
|
-
end
|
257
|
-
|
258
|
-
end
|
259
|
-
|
260
|
-
end
|
261
|
-
|
262
|
-
describe '#extra_metadata' do
|
263
|
-
|
264
|
-
it 'is an empty hash by default' do
|
265
|
-
expect(SlackLogDevice::Formatter.new.extra_metadata).to eq({})
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'can be specified at constructor' do
|
269
|
-
formatter = SlackLogDevice::Formatter.new(extra_metadata: { 'Bar' => 'foo' })
|
270
|
-
expect(formatter.extra_metadata).to eq({ 'Bar' => 'foo' })
|
271
|
-
end
|
272
|
-
|
273
|
-
end
|
274
|
-
|
275
|
-
describe '#initialize' do
|
276
|
-
|
277
|
-
it 'raise an error if an invalid option is given' do
|
278
|
-
expect {
|
279
|
-
SlackLogDevice::Formatter.new(foo: 'bar')
|
280
|
-
}.to raise_error(ArgumentError, 'Unknown key: :foo. Valid keys are: :extra_metadata')
|
281
|
-
end
|
282
|
-
|
283
|
-
end
|
284
|
-
|
285
|
-
end
|
@@ -1,553 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SlackLogDevice do
|
4
|
-
|
5
|
-
let(:device) { SlackLogDevice.new(options) }
|
6
|
-
let(:options) { { username: 'MyApp', webhook_url: 'https://hooks.slack.com/services/test' } }
|
7
|
-
|
8
|
-
before :each do
|
9
|
-
allow(HTTParty).to receive(:post)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'is not a LogDevice instance' do
|
13
|
-
expect(device).not_to be_a(Logger::LogDevice)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '.formatter' do
|
17
|
-
|
18
|
-
it 'returns a SlackLogDevice::Formatter' do
|
19
|
-
expect(SlackLogDevice.formatter).to be_a(SlackLogDevice::Formatter)
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'block is given to formatter constructor' do
|
23
|
-
formatter = SlackLogDevice.formatter { |message| message.reverse }
|
24
|
-
expect(formatter.call('DEBUG', Time.now, ' ', 'Hello World')).to eq("*`DEBUG`*: dlroW olleH")
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'options are forwarded to formatter constructor' do
|
28
|
-
formatter = SlackLogDevice.formatter(extra_metadata: { 'bar' => 'foo' })
|
29
|
-
expect(formatter.extra_metadata).to eq({ 'bar' => 'foo' })
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#auto_flush?' do
|
35
|
-
|
36
|
-
it 'is false by default' do
|
37
|
-
options.delete(:auto_flush)
|
38
|
-
expect(device).not_to be_auto_flush
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'can be set to true' do
|
42
|
-
options[:auto_flush] = true
|
43
|
-
expect(device).to be_auto_flush
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '#close' do
|
49
|
-
|
50
|
-
it 'does nothing' do
|
51
|
-
expect {
|
52
|
-
device.close
|
53
|
-
}.not_to raise_error
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '#channel' do
|
59
|
-
|
60
|
-
it 'is null by default' do
|
61
|
-
options.delete(:channel)
|
62
|
-
expect(device.channel).to be_nil
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'is nil if blank' do
|
66
|
-
options[:channel] = " \n"
|
67
|
-
expect(device.channel).to be_nil
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'can be set' do
|
71
|
-
expect {
|
72
|
-
device.channel = '#foo-bar_42abc'
|
73
|
-
}.to change { device.channel }.from(nil).to('#foo-bar_42abc')
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'raise an error if it contains spaces' do
|
77
|
-
expect {
|
78
|
-
device.channel = '#foo bar'
|
79
|
-
}.to raise_error(ArgumentError, 'Invalid channel specified: "#foo bar", it must start with # or @ and be in lower case with no spaces or special chars and its length must not exceed 22 chars')
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'raise an error if it contains more than 22 chars (including #)' do
|
83
|
-
expect {
|
84
|
-
device.channel = "##{'a' * 22}"
|
85
|
-
}.to raise_error(ArgumentError)
|
86
|
-
device.channel = "##{'a' * 21}" # ok
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'raise an error if it contains upper case letters' do
|
90
|
-
expect {
|
91
|
-
device.channel = '#Foo'
|
92
|
-
}.to raise_error(ArgumentError)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'raise an error if it contains special chars' do
|
96
|
-
expect {
|
97
|
-
device.channel = '#f{oo'
|
98
|
-
}.to raise_error(ArgumentError)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'raise an error if it does not start with a # or @' do
|
102
|
-
expect {
|
103
|
-
device.channel = 'foo'
|
104
|
-
}.to raise_error(ArgumentError)
|
105
|
-
device.channel = '#foo' # ok
|
106
|
-
device.channel = '@foo' # ok
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'raise an error if it only contains prefix' do
|
110
|
-
expect {
|
111
|
-
device.channel = '#'
|
112
|
-
}.to raise_error(ArgumentError)
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
describe '#flush' do
|
118
|
-
|
119
|
-
it 'sends a post to webhook URL with given given message and specified username' do
|
120
|
-
device.write('BAM!')
|
121
|
-
expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!', 'username' => options[:username] }.to_json, headers: { 'Content-Type' => 'application/json' }, timeout: 5)
|
122
|
-
device.flush
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'does not send username if nil' do
|
126
|
-
options.delete(:username)
|
127
|
-
device.write('BAM!')
|
128
|
-
expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!' }.to_json, headers: { 'Content-Type' => 'application/json' }, timeout: 5)
|
129
|
-
device.flush
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'use specified channel' do
|
133
|
-
options[:channel] = '#foo'
|
134
|
-
device.write('BAM!')
|
135
|
-
expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!', 'channel' => '#foo', 'username' => options[:username] }.to_json, headers: { 'Content-Type' => 'application/json' }, timeout: 5)
|
136
|
-
device.flush
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'use specified timeout' do
|
140
|
-
options[:timeout] = 12
|
141
|
-
device.write('BAM!')
|
142
|
-
expect(HTTParty).to receive(:post).with(options[:webhook_url], body: { 'text' => 'BAM!', 'username' => options[:username] }.to_json, headers: { 'Content-Type' => 'application/json' }, timeout: 12)
|
143
|
-
device.flush
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'flushes all message writen separated by a new line' do
|
147
|
-
device.write('BAM!')
|
148
|
-
device.write('BIM!')
|
149
|
-
expect(HTTParty).to receive(:post).twice
|
150
|
-
device.flush
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'returns nil' do
|
154
|
-
device.write('BIM!')
|
155
|
-
expect(device.flush).to be_nil
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'clears buffer' do
|
159
|
-
device.write('BAM!')
|
160
|
-
device.write('BIM!')
|
161
|
-
expect {
|
162
|
-
device.flush
|
163
|
-
}.to change { device.instance_variable_get(:@buffer) }.to([])
|
164
|
-
expect(HTTParty).not_to receive(:post)
|
165
|
-
device.flush
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
describe '#flush?' do
|
171
|
-
|
172
|
-
it 'is true if max_buffer_size is reached' do
|
173
|
-
options[:max_buffer_size] = 2
|
174
|
-
device.write('hello')
|
175
|
-
device.write('world')
|
176
|
-
expect {
|
177
|
-
device.instance_variable_get(:@buffer).send(:<<, 'foo')
|
178
|
-
}.to change { device.flush? }.from(false).to(true)
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'is true if auto_flush option is present' do
|
182
|
-
expect {
|
183
|
-
device.auto_flush = true
|
184
|
-
}.to change { device.flush? }.from(false).to(true)
|
185
|
-
end
|
186
|
-
|
187
|
-
it 'is true if flush delay is 0' do
|
188
|
-
expect {
|
189
|
-
device.flush_delay = 0
|
190
|
-
}.to change { device.flush? }.from(false).to(true)
|
191
|
-
end
|
192
|
-
|
193
|
-
end
|
194
|
-
|
195
|
-
describe '#flush_delay' do
|
196
|
-
|
197
|
-
it 'is 1 by default' do
|
198
|
-
expect(device.flush_delay).to eq(1)
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'can be specified' do
|
202
|
-
options[:flush_delay] = 10
|
203
|
-
expect(device.flush_delay).to be(10)
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'raise an error if invalid' do
|
207
|
-
options[:flush_delay] = 'foo'
|
208
|
-
expect {
|
209
|
-
device
|
210
|
-
}.to raise_error(ArgumentError, 'Invalid flush delay: "foo"')
|
211
|
-
end
|
212
|
-
|
213
|
-
it 'raise an error if negative' do
|
214
|
-
options[:flush_delay] = -1
|
215
|
-
expect {
|
216
|
-
device
|
217
|
-
}.to raise_error(ArgumentError, 'Invalid flush delay: -1')
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'can be zero' do
|
221
|
-
options[:flush_delay] = 0
|
222
|
-
expect(device.flush_delay).to be(0)
|
223
|
-
end
|
224
|
-
|
225
|
-
it 'raise an error if blank' do
|
226
|
-
options[:flush_delay] = ' '
|
227
|
-
expect {
|
228
|
-
device
|
229
|
-
}.to raise_error(ArgumentError, 'Invalid flush delay: " "')
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'raise an error if set as nil' do
|
233
|
-
expect {
|
234
|
-
device.flush_delay = nil
|
235
|
-
}.to raise_error(ArgumentError, 'Invalid flush delay: nil')
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'can be specified as string' do
|
239
|
-
options[:flush_delay] = '42'
|
240
|
-
expect(device.flush_delay).to eq(42)
|
241
|
-
end
|
242
|
-
|
243
|
-
it 'can be set' do
|
244
|
-
expect {
|
245
|
-
device.flush_delay = 15
|
246
|
-
}.to change { device.flush_delay }.from(1).to(15)
|
247
|
-
end
|
248
|
-
|
249
|
-
end
|
250
|
-
|
251
|
-
describe '#initialize' do
|
252
|
-
|
253
|
-
it 'raise an error if an invalid option is given' do
|
254
|
-
expect {
|
255
|
-
SlackLogDevice.new(foo: 'bar')
|
256
|
-
}.to raise_error(ArgumentError, "Unknown key: :foo. Valid keys are: :auto_flush, :channel, :flush_delay, :max_buffer_size, :timeout, :username, :webhook_url")
|
257
|
-
end
|
258
|
-
|
259
|
-
it 'raise an error if webhook option is not given' do
|
260
|
-
expect {
|
261
|
-
SlackLogDevice.new(options.except(:webhook_url))
|
262
|
-
}.to raise_error(ArgumentError, 'Webhook URL must be specified')
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
|
-
|
267
|
-
describe '#max_buffer_size' do
|
268
|
-
|
269
|
-
it 'is 10 by default' do
|
270
|
-
expect(device.max_buffer_size).to eq(10)
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'can be specified' do
|
274
|
-
options[:max_buffer_size] = 42
|
275
|
-
expect(device.max_buffer_size).to be(42)
|
276
|
-
end
|
277
|
-
|
278
|
-
it 'raise an error if invalid' do
|
279
|
-
options[:max_buffer_size] = 'foo'
|
280
|
-
expect {
|
281
|
-
device
|
282
|
-
}.to raise_error(ArgumentError, 'Invalid max buffer size: "foo"')
|
283
|
-
end
|
284
|
-
|
285
|
-
it 'raise an error if negative' do
|
286
|
-
options[:max_buffer_size] = -1
|
287
|
-
expect {
|
288
|
-
device
|
289
|
-
}.to raise_error(ArgumentError, 'Invalid max buffer size: -1')
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'can be zero' do
|
293
|
-
options[:max_buffer_size] = 0
|
294
|
-
expect(device.max_buffer_size).to be_zero
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'raise an error if blank' do
|
298
|
-
options[:max_buffer_size] = ' '
|
299
|
-
expect {
|
300
|
-
device
|
301
|
-
}.to raise_error(ArgumentError, 'Invalid max buffer size: " "')
|
302
|
-
end
|
303
|
-
|
304
|
-
it 'raise an error if set as nil' do
|
305
|
-
expect {
|
306
|
-
device.max_buffer_size = nil
|
307
|
-
}.to raise_error(ArgumentError, 'Invalid max buffer size: nil')
|
308
|
-
end
|
309
|
-
|
310
|
-
it 'can be specified as string' do
|
311
|
-
options[:max_buffer_size] = '42'
|
312
|
-
expect(device.max_buffer_size).to eq(42)
|
313
|
-
end
|
314
|
-
|
315
|
-
it 'can be set' do
|
316
|
-
expect {
|
317
|
-
device.max_buffer_size = 42
|
318
|
-
}.to change { device.max_buffer_size }.from(10).to(42)
|
319
|
-
end
|
320
|
-
|
321
|
-
end
|
322
|
-
|
323
|
-
describe '#timeout' do
|
324
|
-
|
325
|
-
it 'is 5 by default' do
|
326
|
-
expect(device.timeout).to eq(5)
|
327
|
-
end
|
328
|
-
|
329
|
-
it 'can be specified' do
|
330
|
-
options[:timeout] = 10
|
331
|
-
expect(device.timeout).to be(10)
|
332
|
-
end
|
333
|
-
|
334
|
-
it 'raise an error if invalid' do
|
335
|
-
options[:timeout] = 'foo'
|
336
|
-
expect {
|
337
|
-
device
|
338
|
-
}.to raise_error(ArgumentError, 'Invalid timeout: "foo"')
|
339
|
-
end
|
340
|
-
|
341
|
-
it 'raise an error if negative' do
|
342
|
-
options[:timeout] = -1
|
343
|
-
expect {
|
344
|
-
device
|
345
|
-
}.to raise_error(ArgumentError, 'Invalid timeout: -1')
|
346
|
-
end
|
347
|
-
|
348
|
-
it 'raise an error if zero' do
|
349
|
-
options[:timeout] = 0
|
350
|
-
expect {
|
351
|
-
device
|
352
|
-
}.to raise_error(ArgumentError, 'Invalid timeout: 0')
|
353
|
-
end
|
354
|
-
|
355
|
-
it 'raise an error if blank' do
|
356
|
-
options[:timeout] = ' '
|
357
|
-
expect {
|
358
|
-
device
|
359
|
-
}.to raise_error(ArgumentError, 'Invalid timeout: " "')
|
360
|
-
end
|
361
|
-
|
362
|
-
it 'raise an error if set as nil' do
|
363
|
-
expect {
|
364
|
-
device.timeout = nil
|
365
|
-
}.to raise_error(ArgumentError, 'Invalid timeout: nil')
|
366
|
-
end
|
367
|
-
|
368
|
-
it 'can be specified as string' do
|
369
|
-
options[:timeout] = '42'
|
370
|
-
expect(device.timeout).to eq(42)
|
371
|
-
end
|
372
|
-
|
373
|
-
it 'can be set' do
|
374
|
-
expect {
|
375
|
-
device.timeout = 15
|
376
|
-
}.to change { device.timeout }.from(5).to(15)
|
377
|
-
end
|
378
|
-
|
379
|
-
end
|
380
|
-
|
381
|
-
describe '#username' do
|
382
|
-
|
383
|
-
it 'is username set at initialization' do
|
384
|
-
expect(device.username).to eq('MyApp')
|
385
|
-
end
|
386
|
-
|
387
|
-
it 'is nil if not specified' do
|
388
|
-
device = SlackLogDevice.new(options.except(:username))
|
389
|
-
expect(device.username).to be_nil
|
390
|
-
end
|
391
|
-
|
392
|
-
it 'is squished' do
|
393
|
-
options[:username] = "John Doe\n "
|
394
|
-
expect(device.username).to eq('John Doe')
|
395
|
-
end
|
396
|
-
|
397
|
-
it 'is nil if blank' do
|
398
|
-
options[:username] = " \n"
|
399
|
-
expect(device.username).to be_nil
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'can be set' do
|
403
|
-
expect {
|
404
|
-
device.username = 'John Doe'
|
405
|
-
}.to change { device.username }.from(options[:username]).to('John Doe')
|
406
|
-
end
|
407
|
-
|
408
|
-
end
|
409
|
-
|
410
|
-
describe '#webhook_url' do
|
411
|
-
|
412
|
-
it 'is webhook_url set at initialization' do
|
413
|
-
expect(device.webhook_url).to eq('https://hooks.slack.com/services/test')
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'raise an error if invalid' do
|
417
|
-
options[:webhook_url] = 'foo'
|
418
|
-
expect {
|
419
|
-
device
|
420
|
-
}.to raise_error(ArgumentError, 'Invalid webhook URL: "foo"')
|
421
|
-
end
|
422
|
-
|
423
|
-
it 'can be an HTTP URL' do
|
424
|
-
options[:webhook_url] = 'http://google.com'
|
425
|
-
expect(device.webhook_url).to eq('http://google.com')
|
426
|
-
end
|
427
|
-
|
428
|
-
it 'can be an HTTPs URL' do
|
429
|
-
options[:webhook_url] = 'https://google.com'
|
430
|
-
expect(device.webhook_url).to eq('https://google.com')
|
431
|
-
end
|
432
|
-
|
433
|
-
it 'raise an error if not an HTTP(s) url' do
|
434
|
-
options[:webhook_url] = 'ftp://google.com'
|
435
|
-
expect {
|
436
|
-
device
|
437
|
-
}.to raise_error(ArgumentError, 'Invalid webhook URL: "ftp://google.com"')
|
438
|
-
end
|
439
|
-
|
440
|
-
it 'can be set' do
|
441
|
-
expect {
|
442
|
-
device.webhook_url = 'http://google.com'
|
443
|
-
}.to change { device.webhook_url }.from(options[:webhook_url]).to('http://google.com')
|
444
|
-
end
|
445
|
-
|
446
|
-
end
|
447
|
-
|
448
|
-
describe '#write' do
|
449
|
-
|
450
|
-
it 'returns nil' do
|
451
|
-
expect(device.write('BAM!')).to be_nil
|
452
|
-
end
|
453
|
-
|
454
|
-
it 'strips message' do
|
455
|
-
device.write(" BAM !\n")
|
456
|
-
expect(device.instance_variable_get(:@buffer)).to eq(['BAM !'])
|
457
|
-
end
|
458
|
-
|
459
|
-
it 'converts message to string' do
|
460
|
-
device.write(42)
|
461
|
-
expect(device.instance_variable_get(:@buffer)).to eq(['42'])
|
462
|
-
end
|
463
|
-
|
464
|
-
it 'adds given string to existing buffer with a two \n' do
|
465
|
-
device.write('BAM!')
|
466
|
-
expect {
|
467
|
-
device.write('BIM!')
|
468
|
-
}.to change { device.instance_variable_get(:@buffer) }.from(['BAM!']).to(['BAM!', 'BIM!'])
|
469
|
-
end
|
470
|
-
|
471
|
-
it 'does nothing if message is blank' do
|
472
|
-
expect(HTTParty).not_to receive(:post)
|
473
|
-
expect {
|
474
|
-
expect(device.write(" \n")).to be_nil
|
475
|
-
}.not_to change { device.instance_variable_get(:@buffer) }
|
476
|
-
end
|
477
|
-
|
478
|
-
it 'does nothing if message is nil' do
|
479
|
-
expect(HTTParty).not_to receive(:post)
|
480
|
-
expect(device.write(nil)).to be_nil
|
481
|
-
expect(device.instance_variable_get(:@buffer)).to eq([])
|
482
|
-
end
|
483
|
-
|
484
|
-
it 'does not post HTTP message if auto flush is false' do
|
485
|
-
expect(HTTParty).not_to receive(:post)
|
486
|
-
device.write('BAM!')
|
487
|
-
end
|
488
|
-
|
489
|
-
end
|
490
|
-
|
491
|
-
describe Logger, 'with slack log device' do
|
492
|
-
|
493
|
-
let(:logger) { Logger.new(device).tap { |logger| logger.level = Logger::INFO } }
|
494
|
-
|
495
|
-
it 'does nothing if log level is lower than specified one' do
|
496
|
-
expect(HTTParty).not_to receive(:post)
|
497
|
-
logger.debug('BIM!')
|
498
|
-
device.flush
|
499
|
-
end
|
500
|
-
|
501
|
-
it 'send HTTP request if log level is equal to specified one' do
|
502
|
-
expect(HTTParty).to receive(:post)
|
503
|
-
logger.info('BIM!')
|
504
|
-
device.flush
|
505
|
-
end
|
506
|
-
|
507
|
-
it 'send HTTP request if log level is higher to specified one' do
|
508
|
-
expect(HTTParty).to receive(:post)
|
509
|
-
logger.warn('BIM!')
|
510
|
-
device.flush
|
511
|
-
end
|
512
|
-
|
513
|
-
describe '#close' do
|
514
|
-
|
515
|
-
it 'does not raise any error' do
|
516
|
-
expect {
|
517
|
-
logger.close
|
518
|
-
}.not_to raise_error
|
519
|
-
end
|
520
|
-
|
521
|
-
end
|
522
|
-
|
523
|
-
describe '@logdev' do
|
524
|
-
|
525
|
-
let(:logdev) { logger.instance_variable_get(:@logdev) }
|
526
|
-
|
527
|
-
it 'is a LogDevice instance' do
|
528
|
-
expect(logdev).to be_a(Logger::LogDevice)
|
529
|
-
end
|
530
|
-
|
531
|
-
describe '#dev' do
|
532
|
-
|
533
|
-
let(:dev) { logdev.dev }
|
534
|
-
|
535
|
-
it 'is SlackLogDevice instance' do
|
536
|
-
expect(dev).to be(device)
|
537
|
-
end
|
538
|
-
|
539
|
-
end
|
540
|
-
|
541
|
-
describe '#filename' do
|
542
|
-
|
543
|
-
it 'is nil' do
|
544
|
-
expect(logdev.filename).to be_nil
|
545
|
-
end
|
546
|
-
|
547
|
-
end
|
548
|
-
|
549
|
-
end
|
550
|
-
|
551
|
-
end
|
552
|
-
|
553
|
-
end
|