steno 1.2.4 → 1.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/NOTICE +14 -0
- data/Rakefile +6 -8
- data/bin/steno-prettify +24 -25
- data/lib/steno/codec/base.rb +1 -1
- data/lib/steno/codec/json.rb +24 -14
- data/lib/steno/codec.rb +2 -2
- data/lib/steno/config.rb +23 -30
- data/lib/steno/context.rb +3 -3
- data/lib/steno/json_prettifier.rb +31 -30
- data/lib/steno/log_level.rb +1 -2
- data/lib/steno/logger.rb +22 -26
- data/lib/steno/record.rb +5 -15
- data/lib/steno/sink/base.rb +2 -3
- data/lib/steno/sink/counter.rb +4 -8
- data/lib/steno/sink/eventlog.rb +16 -17
- data/lib/steno/sink/fluentd.rb +4 -5
- data/lib/steno/sink/io.rb +8 -12
- data/lib/steno/sink/syslog.rb +19 -15
- data/lib/steno/sink.rb +6 -6
- data/lib/steno/tagged_logger.rb +2 -3
- data/lib/steno/version.rb +1 -1
- data/lib/steno.rb +16 -21
- data/spec/spec_helper.rb +4 -4
- data/spec/support/barrier.rb +2 -2
- data/spec/support/shared_context_specs.rb +4 -4
- data/spec/unit/config_spec.rb +134 -133
- data/spec/unit/context_spec.rb +19 -19
- data/spec/unit/core_ext_spec.rb +14 -14
- data/spec/unit/json_codec_spec.rb +43 -23
- data/spec/unit/json_prettifier_spec.rb +25 -25
- data/spec/unit/log_level_spec.rb +8 -9
- data/spec/unit/logger_spec.rb +53 -53
- data/spec/unit/record_spec.rb +15 -15
- data/spec/unit/sink/counter_spec.rb +7 -7
- data/spec/unit/sink/eventlog_spec.rb +14 -15
- data/spec/unit/sink/fluentd_spec.rb +28 -28
- data/spec/unit/sink/io_spec.rb +62 -62
- data/spec/unit/sink/syslog_spec.rb +54 -30
- data/spec/unit/steno_spec.rb +33 -33
- data/spec/unit/tagged_logger_spec.rb +20 -18
- data/steno.gemspec +28 -28
- metadata +62 -53
data/spec/unit/config_spec.rb
CHANGED
@@ -1,221 +1,222 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
3
|
|
4
|
-
require
|
4
|
+
require 'spec_helper'
|
5
5
|
|
6
6
|
describe Steno::Config do
|
7
|
-
|
8
7
|
if Steno::Sink::WINDOWS
|
9
|
-
describe
|
10
|
-
before
|
11
|
-
@log_path =
|
12
|
-
|
13
|
-
@mock_sink_file = double(
|
14
|
-
@mock_sink_file.
|
15
|
-
Steno::Sink::IO.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@mock_sink_eventlog = double(
|
20
|
-
@mock_sink_eventlog.
|
21
|
-
@mock_sink_eventlog.
|
22
|
-
Steno::Sink::Eventlog.
|
23
|
-
|
8
|
+
describe '.from_hash' do
|
9
|
+
before do
|
10
|
+
@log_path = 'some_file'
|
11
|
+
|
12
|
+
@mock_sink_file = double('sink')
|
13
|
+
expect(@mock_sink_file).to receive(:codec=)
|
14
|
+
expect(Steno::Sink::IO).to receive(:for_file).with(@log_path,
|
15
|
+
max_retries: 5)
|
16
|
+
.and_return(@mock_sink_file)
|
17
|
+
|
18
|
+
@mock_sink_eventlog = double('sink')
|
19
|
+
expect(@mock_sink_eventlog).to receive(:codec=)
|
20
|
+
expect(@mock_sink_eventlog).to receive(:open).with('test')
|
21
|
+
expect(Steno::Sink::Eventlog).to receive(:instance).twice
|
22
|
+
.and_return(@mock_sink_eventlog)
|
24
23
|
end
|
25
24
|
|
26
|
-
after
|
25
|
+
after do
|
27
26
|
@config = Steno::Config.from_hash(@hash)
|
28
27
|
|
29
|
-
@config.default_log_level.
|
30
|
-
@config.context.
|
31
|
-
@config.codec.
|
28
|
+
expect(@config.default_log_level).to eq(:debug2)
|
29
|
+
expect(@config.context.class).to eq(Steno::Context::Null)
|
30
|
+
expect(@config.codec.class).to eq(Steno::Codec::Json)
|
32
31
|
|
33
|
-
@config.sinks.size.
|
34
|
-
@config.sinks.
|
32
|
+
expect(@config.sinks.size).to eq(2)
|
33
|
+
expect(@config.sinks).to contain_exactly(@mock_sink_file, @mock_sink_eventlog)
|
35
34
|
end
|
36
35
|
|
37
|
-
it
|
36
|
+
it 'works for symbolized keys' do
|
38
37
|
@hash = {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
file: @log_path,
|
39
|
+
level: 'debug2',
|
40
|
+
default_log_level: 'warn',
|
41
|
+
eventlog: 'test',
|
42
|
+
max_retries: 5
|
44
43
|
}
|
45
44
|
end
|
46
45
|
|
47
|
-
it
|
46
|
+
it 'works for non-symbolized keys' do
|
48
47
|
@hash = {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
'file' => @log_path,
|
49
|
+
'level' => 'debug2',
|
50
|
+
'default_log_level' => 'warn',
|
51
|
+
'eventlog' => 'test',
|
52
|
+
'max_retries' => 5
|
54
53
|
}
|
55
54
|
end
|
56
|
-
|
57
55
|
end
|
58
56
|
else
|
59
|
-
describe
|
60
|
-
before
|
61
|
-
@log_path =
|
62
|
-
|
63
|
-
@mock_sink_file = double(
|
64
|
-
@mock_sink_file.
|
65
|
-
Steno::Sink::IO.
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@mock_sink_syslog = double(
|
70
|
-
@mock_sink_syslog.
|
71
|
-
@mock_sink_syslog.
|
72
|
-
Steno::Sink::Syslog.
|
73
|
-
|
57
|
+
describe '.from_hash' do
|
58
|
+
before do
|
59
|
+
@log_path = 'some_file'
|
60
|
+
|
61
|
+
@mock_sink_file = double('sink')
|
62
|
+
allow(@mock_sink_file).to receive(:codec=)
|
63
|
+
expect(Steno::Sink::IO).to receive(:for_file).with(@log_path,
|
64
|
+
max_retries: 5)
|
65
|
+
.and_return(@mock_sink_file)
|
66
|
+
|
67
|
+
@mock_sink_syslog = double('sink')
|
68
|
+
expect(@mock_sink_syslog).to receive(:codec=)
|
69
|
+
expect(@mock_sink_syslog).to receive(:open).with('test')
|
70
|
+
expect(Steno::Sink::Syslog).to receive(:instance).twice
|
71
|
+
.and_return(@mock_sink_syslog)
|
74
72
|
end
|
75
73
|
|
76
|
-
after
|
74
|
+
after do
|
77
75
|
@config = Steno::Config.from_hash(@hash)
|
78
76
|
|
79
|
-
@config.default_log_level.
|
80
|
-
@config.context.
|
81
|
-
@config.codec.
|
77
|
+
expect(@config.default_log_level).to eq(:debug2)
|
78
|
+
expect(@config.context.class).to eq(Steno::Context::Null)
|
79
|
+
expect(@config.codec.class).to eq(Steno::Codec::Json)
|
82
80
|
|
83
|
-
@config.sinks.size.
|
84
|
-
@config.sinks.
|
81
|
+
expect(@config.sinks.size).to eq(2)
|
82
|
+
expect(@config.sinks).to contain_exactly(@mock_sink_file, @mock_sink_syslog)
|
85
83
|
end
|
86
84
|
|
87
|
-
it
|
85
|
+
it 'works for symbolized keys' do
|
88
86
|
@hash = {
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
87
|
+
file: @log_path,
|
88
|
+
level: 'debug2',
|
89
|
+
default_log_level: 'warn',
|
90
|
+
syslog: 'test',
|
91
|
+
max_retries: 5
|
94
92
|
}
|
95
93
|
end
|
96
94
|
|
97
|
-
it
|
95
|
+
it 'works for non-symbolized keys' do
|
98
96
|
@hash = {
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
97
|
+
'file' => @log_path,
|
98
|
+
'level' => 'debug2',
|
99
|
+
'default_log_level' => 'warn',
|
100
|
+
'syslog' => 'test',
|
101
|
+
'max_retries' => 5
|
104
102
|
}
|
105
103
|
end
|
106
|
-
|
107
104
|
end
|
108
105
|
end
|
109
106
|
|
110
|
-
describe
|
111
|
-
before
|
107
|
+
describe '.from_file' do
|
108
|
+
before do
|
112
109
|
@tmpdir = Dir.mktmpdir
|
113
|
-
@config_path = File.join(@tmpdir,
|
114
|
-
@log_path = File.join(@tmpdir,
|
110
|
+
@config_path = File.join(@tmpdir, 'config.yml')
|
111
|
+
@log_path = File.join(@tmpdir, 'test.log')
|
115
112
|
end
|
116
113
|
|
117
|
-
after
|
114
|
+
after do
|
118
115
|
FileUtils.rm_rf(@tmpdir)
|
119
116
|
end
|
120
117
|
|
121
|
-
it
|
118
|
+
it 'returns Steno::Config instance with sane defaults' do
|
122
119
|
write_config(@config_path, {})
|
123
120
|
|
124
121
|
config = Steno::Config.from_file(@config_path)
|
125
122
|
|
126
|
-
config.sinks.size.
|
127
|
-
config.sinks[0].class.
|
123
|
+
expect(config.sinks.size).to eq(1)
|
124
|
+
expect(config.sinks[0].class).to eq(Steno::Sink::IO)
|
128
125
|
|
129
|
-
config.default_log_level.
|
126
|
+
expect(config.default_log_level).to eq(:info)
|
130
127
|
|
131
|
-
config.context.
|
128
|
+
expect(config.context.class).to eq(Steno::Context::Null)
|
132
129
|
|
133
|
-
config.codec.
|
130
|
+
expect(config.codec.class).to eq(Steno::Codec::Json)
|
131
|
+
expect(config.codec.iso8601_timestamps?).to eq(false)
|
134
132
|
end
|
135
133
|
|
136
|
-
it
|
137
|
-
write_config(@config_path, {
|
138
|
-
Steno::Config.from_file(@config_path)
|
134
|
+
it 'configures json codec with readable dates if iso8601_timestamps is true' do
|
135
|
+
write_config(@config_path, { 'iso8601_timestamps' => 'true' })
|
136
|
+
config = Steno::Config.from_file(@config_path)
|
137
|
+
expect(config.codec.class).to eq(Steno::Codec::Json)
|
138
|
+
expect(config.codec.iso8601_timestamps?).to eq(true)
|
139
|
+
end
|
139
140
|
|
140
|
-
|
141
|
-
|
141
|
+
it 'sets the default_log_level if a key with the same name is supplied' do
|
142
|
+
write_config(@config_path, { 'level' => 'debug2' })
|
143
|
+
expect(Steno::Config.from_file(@config_path).default_log_level).to eq(:debug2)
|
144
|
+
|
145
|
+
write_config(@config_path, { 'default_log_level' => 'debug2' })
|
146
|
+
expect(Steno::Config.from_file(@config_path).default_log_level).to eq(:debug2)
|
142
147
|
end
|
143
148
|
|
144
|
-
it "
|
145
|
-
write_config(@config_path, {
|
146
|
-
|
147
|
-
Steno::Config.from_file(@config_path).default_log_level.
|
149
|
+
it "reads the 'level' key if both default_log_level and level are spscified" do
|
150
|
+
write_config(@config_path, { 'level' => 'debug2',
|
151
|
+
'default_log_level' => 'warn' })
|
152
|
+
expect(Steno::Config.from_file(@config_path).default_log_level).to eq(:debug2)
|
148
153
|
end
|
149
154
|
|
150
|
-
it "
|
151
|
-
write_config(@config_path, {
|
152
|
-
mock_sink = double(
|
153
|
-
mock_sink.
|
155
|
+
it "adds a file sink if the 'file' key is specified" do
|
156
|
+
write_config(@config_path, { 'file' => @log_path, 'max_retries' => 2 })
|
157
|
+
mock_sink = double('sink')
|
158
|
+
expect(mock_sink).to receive(:codec=)
|
154
159
|
|
155
|
-
Steno::Sink::IO.
|
156
|
-
|
160
|
+
expect(Steno::Sink::IO).to receive(:for_file)
|
161
|
+
.with(@log_path, max_retries: 2).and_return(mock_sink)
|
157
162
|
config = Steno::Config.from_file(@config_path)
|
158
|
-
config.sinks.size.
|
159
|
-
config.sinks[0].
|
163
|
+
expect(config.sinks.size).to eq(1)
|
164
|
+
expect(config.sinks[0]).to eq(mock_sink)
|
160
165
|
end
|
161
166
|
|
162
167
|
if Steno::Sink::WINDOWS
|
163
|
-
it "
|
164
|
-
write_config(@config_path, {
|
165
|
-
mock_sink = double(
|
166
|
-
mock_sink.
|
167
|
-
mock_sink.
|
168
|
+
it "adds a event sink if the 'eventlog' key is specified" do
|
169
|
+
write_config(@config_path, { 'eventlog' => 'test' })
|
170
|
+
mock_sink = double('sink')
|
171
|
+
expect(mock_sink).to receive(:open).with('test')
|
172
|
+
expect(mock_sink).to receive(:codec=)
|
168
173
|
|
169
|
-
Steno::Sink::Eventlog.
|
174
|
+
expect(Steno::Sink::Eventlog).to receive(:instance).twice.and_return(mock_sink)
|
170
175
|
|
171
176
|
config = Steno::Config.from_file(@config_path)
|
172
|
-
config.sinks.size.
|
173
|
-
config.sinks[0].
|
177
|
+
expect(config.sinks.size).to eq(1)
|
178
|
+
expect(config.sinks[0]).to eq(mock_sink)
|
174
179
|
end
|
175
180
|
else
|
176
|
-
it "
|
177
|
-
write_config(@config_path, {
|
178
|
-
mock_sink = double(
|
179
|
-
mock_sink.
|
180
|
-
mock_sink.
|
181
|
+
it "adds a syslog sink if the 'syslog' key is specified" do
|
182
|
+
write_config(@config_path, { 'syslog' => 'test' })
|
183
|
+
mock_sink = double('sink')
|
184
|
+
expect(mock_sink).to receive(:open).with('test')
|
185
|
+
expect(mock_sink).to receive(:codec=)
|
181
186
|
|
182
|
-
Steno::Sink::Syslog.
|
187
|
+
expect(Steno::Sink::Syslog).to receive(:instance).twice.and_return(mock_sink)
|
183
188
|
|
184
189
|
config = Steno::Config.from_file(@config_path)
|
185
|
-
config.sinks.size.
|
186
|
-
config.sinks[0].
|
190
|
+
expect(config.sinks.size).to eq(1)
|
191
|
+
expect(config.sinks[0]).to eq(mock_sink)
|
187
192
|
end
|
188
193
|
end
|
189
194
|
|
190
|
-
|
191
|
-
|
192
|
-
it "should add an io sink to stdout if no sinks are explicitly specified in the config file" do
|
195
|
+
it 'adds an io sink to stdout if no sinks are explicitly specified in the config file' do
|
193
196
|
write_config(@config_path, {})
|
194
|
-
mock_sink = double(
|
195
|
-
mock_sink.
|
197
|
+
mock_sink = double('sink')
|
198
|
+
expect(mock_sink).to receive(:codec=)
|
196
199
|
|
197
|
-
Steno::Sink::IO.
|
200
|
+
expect(Steno::Sink::IO).to receive(:new).with(STDOUT).and_return(mock_sink)
|
198
201
|
|
199
202
|
config = Steno::Config.from_file(@config_path)
|
200
|
-
config.sinks.size.
|
201
|
-
config.sinks[0].
|
203
|
+
expect(config.sinks.size).to eq(1)
|
204
|
+
expect(config.sinks[0]).to eq(mock_sink)
|
202
205
|
end
|
203
206
|
|
204
|
-
it
|
205
|
-
write_config(@config_path, {
|
207
|
+
it 'merges supplied overrides with the file based config' do
|
208
|
+
write_config(@config_path, { 'default_log_level' => 'debug' })
|
206
209
|
|
207
210
|
context = Steno::Context::ThreadLocal.new
|
208
211
|
config = Steno::Config.from_file(@config_path,
|
209
|
-
:
|
210
|
-
:
|
211
|
-
config.context.
|
212
|
-
config.default_log_level.
|
212
|
+
default_log_level: 'warn',
|
213
|
+
context: context)
|
214
|
+
expect(config.context).to eq(context)
|
215
|
+
expect(config.default_log_level).to eq(:warn)
|
213
216
|
end
|
214
217
|
end
|
215
218
|
|
216
219
|
def write_config(path, config)
|
217
|
-
File.
|
218
|
-
f.write(YAML.dump({"logging" => config}))
|
219
|
-
end
|
220
|
+
File.write(path, YAML.dump({ 'logging' => config }))
|
220
221
|
end
|
221
222
|
end
|
data/spec/unit/context_spec.rb
CHANGED
@@ -1,37 +1,37 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Steno::Context::Null do
|
4
|
-
include_context
|
4
|
+
include_context 'steno context'
|
5
5
|
|
6
6
|
let(:context) { Steno::Context::Null.new }
|
7
7
|
|
8
|
-
it
|
9
|
-
context.data.
|
10
|
-
context.data[
|
11
|
-
context.data.
|
8
|
+
it 'stores no data' do
|
9
|
+
expect(context.data).to eq({})
|
10
|
+
context.data['foo'] = 'bar'
|
11
|
+
expect(context.data).to eq({})
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe Steno::Context::ThreadLocal do
|
16
|
-
include_context
|
16
|
+
include_context 'steno context'
|
17
17
|
|
18
|
-
let
|
18
|
+
let(:context) { Steno::Context::ThreadLocal.new }
|
19
19
|
|
20
|
-
it
|
20
|
+
it 'stores data local to threads' do
|
21
21
|
b1 = Barrier.new
|
22
22
|
b2 = Barrier.new
|
23
23
|
|
24
24
|
t1 = Thread.new do
|
25
|
-
context.data[
|
25
|
+
context.data['thread'] = 't1'
|
26
26
|
b1.release
|
27
27
|
b2.wait
|
28
|
-
context.data[
|
28
|
+
expect(context.data['thread']).to eq('t1')
|
29
29
|
end
|
30
30
|
|
31
31
|
t2 = Thread.new do
|
32
32
|
b1.wait
|
33
|
-
context.data[
|
34
|
-
context.data[
|
33
|
+
expect(context.data['thread']).to be_nil
|
34
|
+
context.data['thread'] = 't2'
|
35
35
|
b2.release
|
36
36
|
end
|
37
37
|
|
@@ -41,20 +41,20 @@ describe Steno::Context::ThreadLocal do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
describe Steno::Context::FiberLocal do
|
44
|
-
include_context
|
44
|
+
include_context 'steno context'
|
45
45
|
|
46
46
|
let(:context) { Steno::Context::FiberLocal.new }
|
47
47
|
|
48
|
-
it
|
48
|
+
it 'stores data local to fibers' do
|
49
49
|
f2 = Fiber.new do
|
50
|
-
context.data[
|
51
|
-
context.data[
|
50
|
+
expect(context.data['fiber']).to be_nil
|
51
|
+
context.data['fiber'] = 'f2'
|
52
52
|
end
|
53
53
|
|
54
54
|
f1 = Fiber.new do
|
55
|
-
context.data[
|
55
|
+
context.data['fiber'] = 'f1'
|
56
56
|
f2.resume
|
57
|
-
context.data[
|
57
|
+
expect(context.data['fiber']).to eq('f1')
|
58
58
|
end
|
59
59
|
|
60
60
|
f1.resume
|
data/spec/unit/core_ext_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'steno/core_ext'
|
4
4
|
|
5
5
|
module Foo
|
6
6
|
class Bar
|
@@ -8,31 +8,31 @@ module Foo
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe Module do
|
11
|
-
describe
|
12
|
-
it
|
11
|
+
describe '#logger' do
|
12
|
+
it 'requests a logger named after itself' do
|
13
13
|
x = Foo.logger
|
14
|
-
x.
|
15
|
-
x.name.
|
14
|
+
expect(x).to be_a(Steno::Logger)
|
15
|
+
expect(x.name).to include('Foo')
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
describe Class do
|
21
|
-
describe
|
22
|
-
it
|
21
|
+
describe '#logger' do
|
22
|
+
it 'requests a logger named after itself' do
|
23
23
|
x = Foo::Bar.logger
|
24
|
-
x.
|
25
|
-
x.name.
|
24
|
+
expect(x).to be_a(Steno::Logger)
|
25
|
+
expect(x.name).to include('Foo::Bar')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
describe Object do
|
31
|
-
describe
|
32
|
-
it
|
31
|
+
describe '#logger' do
|
32
|
+
it 'requests a logger named after its class' do
|
33
33
|
x = Foo::Bar.new.logger
|
34
|
-
x.
|
35
|
-
x.name.
|
34
|
+
expect(x).to be_a(Steno::Logger)
|
35
|
+
expect(x.name).to include('Foo::Bar')
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -1,48 +1,68 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Steno::Codec::Json do
|
4
4
|
let(:codec) { Steno::Codec::Json.new }
|
5
|
-
let(:record) { make_record(:
|
5
|
+
let(:record) { make_record(data: { 'user' => 'data' }) }
|
6
6
|
|
7
|
-
describe
|
8
|
-
it
|
7
|
+
describe '#encode_record' do
|
8
|
+
it 'encodes records as json hashes' do
|
9
9
|
parsed = Yajl::Parser.parse(codec.encode_record(record))
|
10
|
-
parsed.class.
|
10
|
+
expect(parsed.class).to eq(Hash)
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
13
|
+
it 'encodes the timestamp as a float' do
|
14
14
|
parsed = Yajl::Parser.parse(codec.encode_record(record))
|
15
|
-
parsed[
|
15
|
+
expect(parsed['timestamp'].class).to eq(Float)
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
rec = make_record(:
|
20
|
-
codec.encode_record(rec).
|
18
|
+
it 'escapes newlines' do
|
19
|
+
rec = make_record(message: "newline\ntest")
|
20
|
+
expect(codec.encode_record(rec)).to match(/newline\\ntest/)
|
21
21
|
end
|
22
22
|
|
23
|
-
it
|
24
|
-
rec = make_record(:
|
25
|
-
codec.encode_record(rec).
|
23
|
+
it 'escapes carriage returns' do
|
24
|
+
rec = make_record(message: "newline\rtest")
|
25
|
+
expect(codec.encode_record(rec)).to match(/newline\\rtest/)
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
28
|
+
it 'allows messages with valid encodings to pass through untouched' do
|
29
29
|
msg = "HI\u2600"
|
30
|
-
rec = make_record(:
|
31
|
-
codec.encode_record(rec).
|
30
|
+
rec = make_record(message: msg)
|
31
|
+
expect(codec.encode_record(rec)).to match(/#{msg}/)
|
32
32
|
end
|
33
33
|
|
34
|
-
it
|
35
|
-
msg = "HI\u2026".force_encoding(
|
36
|
-
rec = make_record(:
|
37
|
-
codec.encode_record(rec).
|
34
|
+
it 'treats messages with invalid encodings as binary data' do
|
35
|
+
msg = "HI\u2026".force_encoding('US-ASCII')
|
36
|
+
rec = make_record(message: msg)
|
37
|
+
expect(codec.encode_record(rec)).to match(/HI\\\\xe2\\\\x80\\\\xa6/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not use readable dates by default' do
|
41
|
+
expect(codec.iso8601_timestamps?).to eq(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when iso8601_timestamps is set' do
|
45
|
+
let(:codec) { Steno::Codec::Json.new(iso8601_timestamps: true) }
|
46
|
+
|
47
|
+
it 'encodes timestamps as UTC-formatted strings' do
|
48
|
+
allow(record).to receive(:timestamp).and_return 1_396_473_763.811278 # 2014-04-02 22:22:43 +01:00
|
49
|
+
parsed = Yajl::Parser.parse(codec.encode_record(record))
|
50
|
+
|
51
|
+
expect(parsed['timestamp'].class).to eq(String)
|
52
|
+
expect(parsed['timestamp']).to eq('2014-04-02T21:22:43.811278Z')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'surfaces the property in a getter' do
|
56
|
+
expect(codec.iso8601_timestamps?).to eq(true)
|
57
|
+
end
|
38
58
|
end
|
39
59
|
end
|
40
60
|
|
41
61
|
def make_record(opts = {})
|
42
|
-
Steno::Record.new(opts[:source] ||
|
62
|
+
Steno::Record.new(opts[:source] || 'my_source',
|
43
63
|
opts[:level] || :debug,
|
44
|
-
opts[:message] ||
|
64
|
+
opts[:message] || 'test message',
|
45
65
|
nil,
|
46
|
-
opts[:data]
|
66
|
+
opts[:data] || {})
|
47
67
|
end
|
48
68
|
end
|