semantic_logger 4.3.1 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/semantic_logger.rb +7 -1
- data/lib/semantic_logger/appender.rb +3 -0
- data/lib/semantic_logger/appender/async.rb +29 -10
- data/lib/semantic_logger/appender/rabbitmq.rb +120 -0
- data/lib/semantic_logger/appenders.rb +89 -0
- data/lib/semantic_logger/base.rb +3 -3
- data/lib/semantic_logger/concerns/compatibility.rb +2 -2
- data/lib/semantic_logger/formatters.rb +1 -0
- data/lib/semantic_logger/formatters/base.rb +28 -6
- data/lib/semantic_logger/formatters/color.rb +4 -3
- data/lib/semantic_logger/formatters/fluentd.rb +37 -0
- data/lib/semantic_logger/formatters/json.rb +4 -2
- data/lib/semantic_logger/formatters/raw.rb +2 -2
- data/lib/semantic_logger/formatters/signalfx.rb +4 -3
- data/lib/semantic_logger/levels.rb +38 -0
- data/lib/semantic_logger/log.rb +11 -6
- data/lib/semantic_logger/loggable.rb +1 -1
- data/lib/semantic_logger/logger.rb +43 -1
- data/lib/semantic_logger/processor.rb +10 -130
- data/lib/semantic_logger/reporters/minitest.rb +49 -0
- data/lib/semantic_logger/semantic_logger.rb +40 -75
- data/lib/semantic_logger/version.rb +1 -1
- metadata +9 -81
- data/test/appender/async_batch_test.rb +0 -60
- data/test/appender/async_test.rb +0 -44
- data/test/appender/bugsnag_test.rb +0 -81
- data/test/appender/elasticsearch_http_test.rb +0 -74
- data/test/appender/elasticsearch_test.rb +0 -248
- data/test/appender/file_test.rb +0 -120
- data/test/appender/graylog_test.rb +0 -82
- data/test/appender/honeybadger_test.rb +0 -45
- data/test/appender/http_test.rb +0 -63
- data/test/appender/kafka_test.rb +0 -35
- data/test/appender/mongodb_test.rb +0 -104
- data/test/appender/new_relic_test.rb +0 -80
- data/test/appender/newrelic_rpm.rb +0 -14
- data/test/appender/sentry_test.rb +0 -47
- data/test/appender/splunk_http_test.rb +0 -79
- data/test/appender/splunk_test.rb +0 -83
- data/test/appender/syslog_test.rb +0 -61
- data/test/appender/tcp_test.rb +0 -66
- data/test/appender/udp_test.rb +0 -59
- data/test/appender/wrapper_test.rb +0 -95
- data/test/concerns/compatibility_test.rb +0 -117
- data/test/debug_as_trace_logger_test.rb +0 -81
- data/test/formatters/color_test.rb +0 -153
- data/test/formatters/default_test.rb +0 -175
- data/test/formatters/one_line_test.rb +0 -60
- data/test/formatters/signalfx_test.rb +0 -197
- data/test/formatters_test.rb +0 -36
- data/test/in_memory_appender.rb +0 -8
- data/test/in_memory_appender_helper.rb +0 -43
- data/test/in_memory_batch_appender.rb +0 -8
- data/test/in_memory_metrics_appender.rb +0 -13
- data/test/loggable_test.rb +0 -103
- data/test/logger_test.rb +0 -334
- data/test/measure_test.rb +0 -346
- data/test/metric/new_relic_test.rb +0 -35
- data/test/metric/signalfx_test.rb +0 -77
- data/test/semantic_logger_test.rb +0 -303
- data/test/test_helper.rb +0 -31
@@ -1,60 +0,0 @@
|
|
1
|
-
require_relative '../test_helper'
|
2
|
-
|
3
|
-
module SemanticLogger
|
4
|
-
module Formatters
|
5
|
-
class DefaultTest < Minitest::Test
|
6
|
-
describe Default do
|
7
|
-
let(:log_time) do
|
8
|
-
Time.utc(2017, 1, 14, 8, 32, 5.375276)
|
9
|
-
end
|
10
|
-
|
11
|
-
let(:level) do
|
12
|
-
:debug
|
13
|
-
end
|
14
|
-
|
15
|
-
let(:log) do
|
16
|
-
log = SemanticLogger::Log.new('DefaultTest', level)
|
17
|
-
log.time = log_time
|
18
|
-
log
|
19
|
-
end
|
20
|
-
|
21
|
-
let(:set_exception) do
|
22
|
-
begin
|
23
|
-
raise 'Oh no'
|
24
|
-
rescue Exception => exc
|
25
|
-
log.exception = exc
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:formatter) do
|
30
|
-
formatter = SemanticLogger::Formatters::OneLine.new
|
31
|
-
# Does not use the logger instance for formatting purposes
|
32
|
-
formatter.call(log, nil)
|
33
|
-
formatter
|
34
|
-
end
|
35
|
-
|
36
|
-
describe 'message' do
|
37
|
-
it 'logs message' do
|
38
|
-
log.message = "Hello \nWorld\n"
|
39
|
-
assert_equal '-- Hello World', formatter.message
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'skips empty message' do
|
43
|
-
refute formatter.message
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe 'exception' do
|
48
|
-
it 'logs exception' do
|
49
|
-
set_exception
|
50
|
-
assert_equal '-- Exception: RuntimeError: Oh no', formatter.exception
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'skips nil exception' do
|
54
|
-
refute formatter.exception
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,197 +0,0 @@
|
|
1
|
-
require_relative '../test_helper'
|
2
|
-
require 'net/http'
|
3
|
-
|
4
|
-
module SemanticLogger
|
5
|
-
module Formatters
|
6
|
-
class SignalfxTest < Minitest::Test
|
7
|
-
describe SemanticLogger::Formatters::Signalfx do
|
8
|
-
let :average_metric_name do
|
9
|
-
'Application.average'
|
10
|
-
end
|
11
|
-
|
12
|
-
let :counter_metric_name do
|
13
|
-
'Application.counter'
|
14
|
-
end
|
15
|
-
|
16
|
-
let :log do
|
17
|
-
metric = '/user/login'
|
18
|
-
log = SemanticLogger::Log.new('User', :debug)
|
19
|
-
log.metric = metric
|
20
|
-
log
|
21
|
-
end
|
22
|
-
|
23
|
-
let :logs do
|
24
|
-
3.times.collect do |i|
|
25
|
-
l = log.dup
|
26
|
-
l.metric = "/user/login#{i + 1}"
|
27
|
-
l
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
let :same_logs do
|
32
|
-
3.times.collect do |_i|
|
33
|
-
l = log.dup
|
34
|
-
l.metric = '/user/login'
|
35
|
-
l
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
let :dimensions do
|
40
|
-
{action: 'hit', user: 'jbloggs', state: 'FL'}
|
41
|
-
end
|
42
|
-
|
43
|
-
let :all_dimensions do
|
44
|
-
dims = dimensions.merge(
|
45
|
-
host: SemanticLogger.host,
|
46
|
-
application: SemanticLogger.application,
|
47
|
-
environment: 'test'
|
48
|
-
)
|
49
|
-
string_keys = {}
|
50
|
-
dims.each_pair { |k, v| string_keys[k.to_s] = v }
|
51
|
-
string_keys
|
52
|
-
end
|
53
|
-
|
54
|
-
let :appender do
|
55
|
-
Net::HTTP.stub_any_instance(:start, true) do
|
56
|
-
SemanticLogger::Metric::Signalfx.new(token: 'TEST')
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
let :formatter do
|
61
|
-
appender.formatter
|
62
|
-
end
|
63
|
-
|
64
|
-
describe 'format single log' do
|
65
|
-
let :result do
|
66
|
-
JSON.parse(formatter.call(log, appender))
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'send counter metric when there is no duration' do
|
70
|
-
hash = result
|
71
|
-
assert counters = hash['counter'], hash
|
72
|
-
assert counter = counters.first, hash
|
73
|
-
assert_equal counter_metric_name, counter['metric'], counter
|
74
|
-
assert_equal 1, counter['value'], counter
|
75
|
-
assert_equal (log.time.to_i * 1_000).to_i, counter['timestamp'], counter
|
76
|
-
assert counter.key?('dimensions')
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'send gauge metric when log includes duration' do
|
80
|
-
log.duration = 1234
|
81
|
-
hash = result
|
82
|
-
assert counters = hash['gauge'], hash
|
83
|
-
assert counter = counters.first, hash
|
84
|
-
assert_equal average_metric_name, counter['metric'], counter
|
85
|
-
assert_equal 1234, counter['value'], counter
|
86
|
-
assert_equal (log.time.to_i * 1_000).to_i, counter['timestamp'], counter
|
87
|
-
assert counter.key?('dimensions')
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'also sends counter metric when gauge metric is sent' do
|
91
|
-
log.duration = 1234
|
92
|
-
hash = result
|
93
|
-
assert counters = hash['counter'], hash
|
94
|
-
assert counter = counters.first, hash
|
95
|
-
assert_equal counter_metric_name, counter['metric'], counter
|
96
|
-
assert_equal 1, counter['value'], counter
|
97
|
-
assert_equal (log.time.to_i * 1_000).to_i, counter['timestamp'], counter
|
98
|
-
assert counter.key?('dimensions')
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'only forwards whitelisted dimensions from named_tags' do
|
102
|
-
log.named_tags = {user_id: 47, tracking_number: 7474, session_id: 'hsdhngsd'}
|
103
|
-
formatter.dimensions = %i[user_id application]
|
104
|
-
hash = result
|
105
|
-
assert counters = hash['counter'], hash
|
106
|
-
assert counter = counters.first, hash
|
107
|
-
assert_equal({'class' => 'user', 'action' => 'login', 'environment' => 'test', 'user_id' => '47', 'host' => SemanticLogger.host, 'application' => SemanticLogger.application}, counter['dimensions'], counter)
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'raises exception with both a whitelist and blacklist' do
|
111
|
-
assert_raises ArgumentError do
|
112
|
-
SemanticLogger::Formatters::Signalfx.new(token: 'TEST', dimensions: [:user_id], exclude_dimensions: [:tracking_number])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'send custom counter metric when there is no duration' do
|
117
|
-
log.metric = 'Filter/count'
|
118
|
-
log.dimensions = dimensions
|
119
|
-
hash = result
|
120
|
-
|
121
|
-
assert counters = hash['counter'], hash
|
122
|
-
assert counter = counters.first, hash
|
123
|
-
assert_equal 'Filter.count', counter['metric'], counter
|
124
|
-
assert_equal 1, counter['value'], counter
|
125
|
-
assert_equal (log.time.to_i * 1_000).to_i, counter['timestamp'], counter
|
126
|
-
assert_equal all_dimensions, counter['dimensions']
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe 'format batch logs' do
|
131
|
-
let :result do
|
132
|
-
JSON.parse(formatter.batch(logs, appender))
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'send metrics' do
|
136
|
-
hash = result
|
137
|
-
|
138
|
-
assert counters = hash['counter'], hash
|
139
|
-
assert_equal 3, counters.size
|
140
|
-
assert_equal counter_metric_name, counters[0]['metric']
|
141
|
-
assert_equal 1, counters[0]['value']
|
142
|
-
assert_equal counter_metric_name, counters[1]['metric']
|
143
|
-
assert_equal counter_metric_name, counters[2]['metric']
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'sends gauge metrics' do
|
147
|
-
logs.each { |log| log.duration = 3.5 }
|
148
|
-
hash = result
|
149
|
-
assert gauges = hash['gauge'], hash
|
150
|
-
assert_equal 3, gauges.size
|
151
|
-
assert_equal average_metric_name, gauges[0]['metric']
|
152
|
-
assert_equal 3.5, gauges[0]['value']
|
153
|
-
assert_equal average_metric_name, gauges[1]['metric']
|
154
|
-
assert_equal average_metric_name, gauges[2]['metric']
|
155
|
-
end
|
156
|
-
|
157
|
-
describe 'send custom' do
|
158
|
-
let :logs do
|
159
|
-
3.times.collect do |_i|
|
160
|
-
l = log.dup
|
161
|
-
l.metric = 'Filter/count'
|
162
|
-
l.dimensions = dimensions
|
163
|
-
l
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'counter metric when there is no duration' do
|
168
|
-
hash = result
|
169
|
-
|
170
|
-
assert counters = hash['counter'], hash
|
171
|
-
assert counter = counters.first, hash
|
172
|
-
assert_equal 'Filter.count', counter['metric'], counter
|
173
|
-
assert_equal 3, counter['value'], counter
|
174
|
-
assert_equal (log.time.to_i * 1_000).to_i, counter['timestamp'], counter
|
175
|
-
assert_equal all_dimensions, counter['dimensions']
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
describe 'format batch logs with aggregation' do
|
181
|
-
let :result do
|
182
|
-
JSON.parse(formatter.batch(same_logs, appender))
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'sends counter metrics' do
|
186
|
-
hash = result
|
187
|
-
|
188
|
-
assert counters = hash['counter'], hash
|
189
|
-
assert_equal 1, counters.size
|
190
|
-
assert_equal counter_metric_name, counters[0]['metric']
|
191
|
-
assert_equal 3, counters[0]['value']
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
data/test/formatters_test.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class FormattersTest < Minitest::Test
|
4
|
-
describe SemanticLogger::Formatters do
|
5
|
-
describe '.factory' do
|
6
|
-
let :log do
|
7
|
-
SemanticLogger::Log.new('Test', :info)
|
8
|
-
end
|
9
|
-
|
10
|
-
let :appender do
|
11
|
-
SemanticLogger::Appender::File.new(io: STDOUT)
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'from a symbol' do
|
15
|
-
assert formatter = SemanticLogger::Formatters.factory(:raw)
|
16
|
-
assert formatter.is_a?(SemanticLogger::Formatters::Raw)
|
17
|
-
assert_equal 'Test', formatter.call(log, appender)[:name]
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'from a Hash (Symbol with options)' do
|
21
|
-
assert formatter = SemanticLogger::Formatters.factory(raw: {time_format: '%Y%m%d'})
|
22
|
-
assert formatter.is_a?(SemanticLogger::Formatters::Raw)
|
23
|
-
assert result = formatter.call(log, appender)
|
24
|
-
assert_equal 'Test', result[:name]
|
25
|
-
assert_equal Time.now.strftime('%Y%m%d'), result[:time]
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'from block' do
|
29
|
-
my_formatter = ->(log, _appender) { log.name }
|
30
|
-
assert formatter = SemanticLogger::Formatters.factory(my_formatter)
|
31
|
-
assert formatter.is_a?(Proc)
|
32
|
-
assert_equal 'Test', formatter.call(log, appender)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/test/in_memory_appender.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'minitest/shared_description'
|
2
|
-
|
3
|
-
InMemoryAppenderHelper = shared_description do
|
4
|
-
let :log_message do
|
5
|
-
SemanticLogger.flush
|
6
|
-
appender.message
|
7
|
-
end
|
8
|
-
|
9
|
-
let :appender do
|
10
|
-
InMemoryAppender.new
|
11
|
-
end
|
12
|
-
|
13
|
-
let :thread_name do
|
14
|
-
Thread.current.name
|
15
|
-
end
|
16
|
-
|
17
|
-
let :payload do
|
18
|
-
{session_id: 'HSSKLEU@JDK767', tracking_number: 12_345}
|
19
|
-
end
|
20
|
-
|
21
|
-
let :logger do
|
22
|
-
SemanticLogger['TestLogger']
|
23
|
-
end
|
24
|
-
|
25
|
-
let :appender_options do
|
26
|
-
{appender: appender}
|
27
|
-
end
|
28
|
-
|
29
|
-
let :added_appender do
|
30
|
-
SemanticLogger.add_appender(appender_options)
|
31
|
-
end
|
32
|
-
|
33
|
-
before do
|
34
|
-
SemanticLogger.default_level = :trace
|
35
|
-
SemanticLogger.backtrace_level = :trace
|
36
|
-
SemanticLogger.flush
|
37
|
-
added_appender
|
38
|
-
end
|
39
|
-
|
40
|
-
after do
|
41
|
-
SemanticLogger.appenders.each { |appender| SemanticLogger.remove_appender(appender) }
|
42
|
-
end
|
43
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# Store in memory the last log message received.
|
2
|
-
class InMemoryMetricsAppender < SemanticLogger::Subscriber
|
3
|
-
attr_accessor :message
|
4
|
-
|
5
|
-
def log(log)
|
6
|
-
self.message = log
|
7
|
-
end
|
8
|
-
|
9
|
-
# Only forward log entries that contain metrics.
|
10
|
-
def should_log?(log)
|
11
|
-
log.metric && meets_log_level?(log) && !filtered?(log)
|
12
|
-
end
|
13
|
-
end
|
data/test/loggable_test.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
class TestAttribute
|
5
|
-
include SemanticLogger::Loggable
|
6
|
-
end
|
7
|
-
|
8
|
-
# Unit Test for SemanticLogger::Appender::File
|
9
|
-
#
|
10
|
-
class AppenderFileTest < Minitest::Test
|
11
|
-
module Perform
|
12
|
-
def perform
|
13
|
-
logger.info 'perform'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Base
|
18
|
-
include SemanticLogger::Loggable
|
19
|
-
include Perform
|
20
|
-
end
|
21
|
-
|
22
|
-
module Process
|
23
|
-
def process
|
24
|
-
logger.info 'process'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Subclass < Base
|
29
|
-
include Process
|
30
|
-
end
|
31
|
-
|
32
|
-
describe SemanticLogger::Loggable do
|
33
|
-
describe 'inheritance' do
|
34
|
-
it 'should give child classes their own logger' do
|
35
|
-
assert_equal Subclass.name, Subclass.logger.name
|
36
|
-
assert_equal Base.name, Base.logger.name
|
37
|
-
assert_equal Subclass.name, Subclass.logger.name
|
38
|
-
child_logger = Subclass.logger
|
39
|
-
refute_equal child_logger, Base.logger
|
40
|
-
assert_equal child_logger.object_id, Subclass.logger.object_id
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should give child objects their own logger' do
|
44
|
-
subclass = Subclass.new
|
45
|
-
base = Base.new
|
46
|
-
assert_equal subclass.class.name, subclass.logger.name
|
47
|
-
assert_equal base.class.name, base.logger.name
|
48
|
-
assert_equal subclass.class.name, subclass.logger.name
|
49
|
-
child_logger = subclass.logger
|
50
|
-
refute_equal child_logger, base.logger
|
51
|
-
assert_equal child_logger.object_id, subclass.logger.object_id
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should allow mixins to call parent logger' do
|
55
|
-
base = Base.new
|
56
|
-
base.perform
|
57
|
-
called = false
|
58
|
-
Base.logger.stub(:info, ->(description) { called = true if description == 'perform' }) do
|
59
|
-
base.perform
|
60
|
-
end
|
61
|
-
assert called, 'Did not call the correct logger'
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should allow child mixins to call parent logger' do
|
65
|
-
subclass = Subclass.new
|
66
|
-
subclass.process
|
67
|
-
called = false
|
68
|
-
Subclass.logger.stub(:info, ->(description) { called = true if description == 'process' }) do
|
69
|
-
subclass.process
|
70
|
-
end
|
71
|
-
assert called, 'Did not call the correct logger'
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe 'logger' do
|
76
|
-
include InMemoryAppenderHelper
|
77
|
-
|
78
|
-
describe 'for each log level' do
|
79
|
-
# Ensure that any log level can be logged
|
80
|
-
SemanticLogger::LEVELS.each do |level|
|
81
|
-
it "logs #{level} information with class attribute" do
|
82
|
-
TestAttribute.logger.send(level, "hello #{level}", payload)
|
83
|
-
|
84
|
-
assert log = log_message
|
85
|
-
assert_equal "hello #{level}", log.message
|
86
|
-
assert_equal level, log.level
|
87
|
-
assert_equal 'TestAttribute', log.name
|
88
|
-
assert_equal payload, log.payload
|
89
|
-
end
|
90
|
-
|
91
|
-
it "log #{level} information with instance attribute" do
|
92
|
-
TestAttribute.new.logger.send(level, "hello #{level}", payload)
|
93
|
-
assert log = log_message
|
94
|
-
assert_equal "hello #{level}", log.message
|
95
|
-
assert_equal level, log.level
|
96
|
-
assert_equal 'TestAttribute', log.name
|
97
|
-
assert_equal payload, log.payload
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|