semantic_logger 2.13.1 → 2.14.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 +4 -4
- data/lib/semantic_logger.rb +1 -0
- data/lib/semantic_logger/appender/bugsnag.rb +81 -0
- data/lib/semantic_logger/loggable.rb +1 -3
- data/lib/semantic_logger/semantic_logger.rb +10 -3
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender_bugsnag_test.rb +61 -0
- metadata +10 -9
- data/lib/LogGC.java +0 -26
- data/lib/LogGC_1.java +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a000244f5570ff32c8dcc923f066a131abd7cb0
|
4
|
+
data.tar.gz: a9471ed620e7408a195a9292f41730c68ea54e98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0667f6ef71190a16d66849493630a43f7dce3e8ae2786b38972f84b992cf3f2081995eb4e01c0d72ee47e0b378b49d844dd5883b561db40831f28d20abbff053
|
7
|
+
data.tar.gz: d81cddd57a426da87b14b4df0b2b212926e0c5b8405be8d103aa518348d4f65f0d8689bf066b6cf189d85e704b77c9929e874fbe6be9318579e6f6651ee85159
|
data/lib/semantic_logger.rb
CHANGED
@@ -16,6 +16,7 @@ module SemanticLogger
|
|
16
16
|
autoload :Syslog, 'semantic_logger/appender/syslog'
|
17
17
|
autoload :NewRelic, 'semantic_logger/appender/new_relic'
|
18
18
|
autoload :Splunk, 'semantic_logger/appender/splunk'
|
19
|
+
autoload :Bugsnag, 'semantic_logger/appender/bugsnag'
|
19
20
|
end
|
20
21
|
|
21
22
|
if defined?(JRuby)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
=begin
|
2
|
+
Bugsnag appender for SemanticLogger
|
3
|
+
|
4
|
+
Skips the fatal log level because unrescued exceptions get logged as fatal and will be reported automatically by Bugsnag.
|
5
|
+
|
6
|
+
Note: Payload information is not filtered, so take care not to push any sensitive information when logging with tags or a payload.
|
7
|
+
|
8
|
+
Example 1
|
9
|
+
|
10
|
+
Adding the Bugsnag appender will send :error log entries to Bugsnag with the error severity.
|
11
|
+
|
12
|
+
For a Rails application already configured to use SemanticLogger and Bugsnag, create a file called <Rails Root>/config/initializers/bugsnag_appender.rb with the following contents and restart the application:
|
13
|
+
|
14
|
+
# Send :error and log messages to Bugsnag
|
15
|
+
SemanticLogger.add_appender(SemanticLogger::Appender::Bugsnag.new)
|
16
|
+
Rails.logger.info 'SemanticLogger Bugsnag Appender added.'
|
17
|
+
|
18
|
+
Example 2
|
19
|
+
|
20
|
+
For a non-Rails application, send :info and more severe log entries to a file called application.log and also send :error log entries to Bugsnag.
|
21
|
+
|
22
|
+
require 'semantic_logger'
|
23
|
+
require 'bugsnag'
|
24
|
+
|
25
|
+
# Bugsnag setup
|
26
|
+
Bugsnag.configure do |config|
|
27
|
+
config.api_key = 'abc123'
|
28
|
+
end
|
29
|
+
|
30
|
+
# SemanticLogger setup
|
31
|
+
SemanticLogger.default_level = :info
|
32
|
+
SemanticLogger.add_appender('application.log')
|
33
|
+
SemanticLogger.add_appender(SemanticLogger::Appender::Bugsnag.new)
|
34
|
+
logger = SemanticLogger['Example']
|
35
|
+
|
36
|
+
# Log some messages
|
37
|
+
logger.info 'This is only written to application.log'
|
38
|
+
logger.error 'This is written to application.log and will also be sent to Bugsnag as an error event'
|
39
|
+
|
40
|
+
# The appender will send payloads to Bugsnag
|
41
|
+
logger.error 'Something bad happened', info: 'Related information'
|
42
|
+
=end
|
43
|
+
|
44
|
+
require 'bugsnag'
|
45
|
+
|
46
|
+
class SemanticLogger::Appender::Bugsnag < SemanticLogger::Appender::Base
|
47
|
+
# Allow the level for this appender to be overwritten
|
48
|
+
# Default: :error
|
49
|
+
# Note: Not recommended to set the log level to :info, :debug, or :trace as that would flood Bugsnag with Error notices
|
50
|
+
def initialize(level = :error, &block)
|
51
|
+
super(level, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns [Hash] of parameters to send to Bugsnag.
|
55
|
+
def default_formatter
|
56
|
+
proc do |log|
|
57
|
+
{ :severity => log_level(log), tags: log.tags }.merge(log.payload || {})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Send an error notification to Bugsnag
|
62
|
+
def log(log)
|
63
|
+
# Only log if level is warn, or error.
|
64
|
+
# We don't want to send fatal as those are already captured by Bugsnag.
|
65
|
+
return false if (level_index > (log.level_index || 0)) || !include_message?(log)
|
66
|
+
return false if log.level == :fatal
|
67
|
+
# Ignore logs coming from Bugsnag itself
|
68
|
+
return false if log.message.to_s.include?(Bugsnag::LOG_PREFIX)
|
69
|
+
|
70
|
+
# For more documentation on the Bugsnag.notify method see:
|
71
|
+
# https://bugsnag.com/docs/notifiers/ruby#sending-handled-exceptions
|
72
|
+
Bugsnag.notify(log.exception || log.message, formatter.call(log))
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def log_level(log)
|
79
|
+
log.level.to_s.gsub('warn', 'warning')
|
80
|
+
end
|
81
|
+
end
|
@@ -31,9 +31,7 @@ module SemanticLogger
|
|
31
31
|
|
32
32
|
def self.included(base)
|
33
33
|
base.class_eval do
|
34
|
-
# Thread safe class variable
|
35
|
-
include SyncAttr
|
36
|
-
|
34
|
+
# Thread safe logger class variable initializer
|
37
35
|
sync_cattr_reader :logger do
|
38
36
|
SemanticLogger[self]
|
39
37
|
end
|
@@ -196,10 +196,17 @@ module SemanticLogger
|
|
196
196
|
end if log_level_signal
|
197
197
|
|
198
198
|
Signal.trap(thread_dump_signal) do
|
199
|
-
logger = SemanticLogger['
|
199
|
+
logger = SemanticLogger['Thread Dump']
|
200
200
|
Thread.list.each do |thread|
|
201
|
-
|
202
|
-
|
201
|
+
next if thread == Thread.current
|
202
|
+
message = thread.name
|
203
|
+
if backtrace = thread.backtrace
|
204
|
+
message += "\n"
|
205
|
+
message << backtrace.join("\n")
|
206
|
+
end
|
207
|
+
tags = thread[:semantic_logger_tags]
|
208
|
+
tags = tags.nil? ? [] : tags.clone
|
209
|
+
logger.tagged(tags) { logger.warn(message) }
|
203
210
|
end
|
204
211
|
end if thread_dump_signal
|
205
212
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
# Unit Test for SemanticLogger::Appender::Bugsnag
|
5
|
+
#
|
6
|
+
class AppenderBugsnagTest < Minitest::Test
|
7
|
+
context SemanticLogger::Appender::Bugsnag do
|
8
|
+
setup do
|
9
|
+
@appender = SemanticLogger::Appender::Bugsnag.new(:warn)
|
10
|
+
@message = 'AppenderBugsnagTest log message'
|
11
|
+
end
|
12
|
+
|
13
|
+
(SemanticLogger::LEVELS - [:warn, :error]).each do |level|
|
14
|
+
should "not send :#{level} notifications to Bugsnag" do
|
15
|
+
message = hash = nil
|
16
|
+
Bugsnag.stub(:notify, -> msg, h { message = msg; hash = h }) do
|
17
|
+
@appender.send(level, "AppenderBugsnagTest #{level.to_s} message")
|
18
|
+
end
|
19
|
+
assert_nil message
|
20
|
+
assert_nil hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
should "send error notifications to Bugsnag with severity" do
|
25
|
+
message = hash = nil
|
26
|
+
Bugsnag.stub(:notify, -> msg, h { message = msg; hash = h }) do
|
27
|
+
@appender.error @message
|
28
|
+
end
|
29
|
+
assert_equal @message, message
|
30
|
+
assert_equal 'error', hash[:severity]
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'send warn notifications to Bugsnag replace warn severity with warning' do
|
34
|
+
message = hash = nil
|
35
|
+
Bugsnag.stub(:notify, -> msg, h { message = msg; hash = h }) do
|
36
|
+
@appender.warn @message
|
37
|
+
end
|
38
|
+
assert_equal @message, message
|
39
|
+
assert_equal 'warning', hash[:severity]
|
40
|
+
end
|
41
|
+
|
42
|
+
should 'send notification to Bugsnag with custom attributes' do
|
43
|
+
message = hash = nil
|
44
|
+
Bugsnag.stub(:notify, -> msg, h { message = msg; hash = h }) do
|
45
|
+
@appender.error @message, {:key1 => 1, :key2 => 'a'}
|
46
|
+
end
|
47
|
+
assert_equal @message, message
|
48
|
+
assert_equal(1, hash[:key1], hash)
|
49
|
+
assert_equal('a', hash[:key2], hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
should 'send notification to Bugsnag with exception' do
|
53
|
+
message = hash = nil
|
54
|
+
error = RuntimeError
|
55
|
+
Bugsnag.stub(:notify, -> msg, h { message = msg; hash = h }) do
|
56
|
+
@appender.error error
|
57
|
+
end
|
58
|
+
assert_equal error, message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semantic_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sync_attr
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thread_safe
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.1'
|
41
41
|
description: Next generation logging system for Ruby to support highly concurrent,
|
42
|
-
high throughput, low latency systems
|
42
|
+
high throughput, low latency enterprise systems
|
43
43
|
email:
|
44
44
|
- reidmo@gmail.com
|
45
45
|
executables: []
|
@@ -49,10 +49,9 @@ files:
|
|
49
49
|
- LICENSE.txt
|
50
50
|
- README.md
|
51
51
|
- Rakefile
|
52
|
-
- lib/LogGC.java
|
53
|
-
- lib/LogGC_1.java
|
54
52
|
- lib/semantic_logger.rb
|
55
53
|
- lib/semantic_logger/appender/base.rb
|
54
|
+
- lib/semantic_logger/appender/bugsnag.rb
|
56
55
|
- lib/semantic_logger/appender/file.rb
|
57
56
|
- lib/semantic_logger/appender/mongodb.rb
|
58
57
|
- lib/semantic_logger/appender/new_relic.rb
|
@@ -67,6 +66,7 @@ files:
|
|
67
66
|
- lib/semantic_logger/logger.rb
|
68
67
|
- lib/semantic_logger/semantic_logger.rb
|
69
68
|
- lib/semantic_logger/version.rb
|
69
|
+
- test/appender_bugsnag_test.rb
|
70
70
|
- test/appender_file_test.rb
|
71
71
|
- test/appender_mongodb_test.rb
|
72
72
|
- test/appender_new_relic_test.rb
|
@@ -99,11 +99,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
99
|
version: '0'
|
100
100
|
requirements: []
|
101
101
|
rubyforge_project:
|
102
|
-
rubygems_version: 2.4.
|
102
|
+
rubygems_version: 2.4.6
|
103
103
|
signing_key:
|
104
104
|
specification_version: 4
|
105
|
-
summary: Scalable, next generation logging for Ruby
|
105
|
+
summary: Scalable, next generation enterprise logging for Ruby
|
106
106
|
test_files:
|
107
|
+
- test/appender_bugsnag_test.rb
|
107
108
|
- test/appender_file_test.rb
|
108
109
|
- test/appender_mongodb_test.rb
|
109
110
|
- test/appender_new_relic_test.rb
|
data/lib/LogGC.java
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
//get all the info and pretty print it
|
2
|
-
duration =
|
3
|
-
//System.out.println("GcInfo CompositeType: " + info.getGcInfo().getCompositeType());
|
4
|
-
//System.out.println("GcInfo MemoryUsageAfterGc: " + info.getGcInfo().getMemoryUsageAfterGc());
|
5
|
-
//System.out.println("GcInfo MemoryUsageBeforeGc: " + info.getGcInfo().getMemoryUsageBeforeGc());
|
6
|
-
|
7
|
-
//Get the information about each memory space, and pretty print it
|
8
|
-
Map<String, MemoryUsage> membefore = info.getGcInfo().getMemoryUsageBeforeGc();
|
9
|
-
Map<String, MemoryUsage> mem = info.getGcInfo().getMemoryUsageAfterGc();
|
10
|
-
for (Entry<String, MemoryUsage> entry : mem.entrySet()) {
|
11
|
-
String name = entry.getKey();
|
12
|
-
MemoryUsage memdetail = entry.getValue();
|
13
|
-
long memInit = memdetail.getInit();
|
14
|
-
long memCommitted = memdetail.getCommitted();
|
15
|
-
long memMax = memdetail.getMax();
|
16
|
-
long memUsed = memdetail.getUsed();
|
17
|
-
MemoryUsage before = membefore.get(name);
|
18
|
-
long beforepercent = ((before.getUsed() * 1000L) / before.getCommitted());
|
19
|
-
long percent = ((memUsed * 1000L) / before.getCommitted()); //>100% when it gets expanded
|
20
|
-
|
21
|
-
System.out.print(name + (memCommitted == memMax ? "(fully expanded)" : "(still expandable)") + "used: " + (beforepercent / 10) + "." + (beforepercent % 10) + "%->" + (percent / 10) + "." + (percent % 10) + "%(" + ((memUsed / 1048576) + 1) + "MB) / ");
|
22
|
-
}
|
23
|
-
System.out.println();
|
24
|
-
totalGcDuration += info.getGcInfo().getDuration();
|
25
|
-
long percent = totalGcDuration * 1000L / info.getGcInfo().getEndTime();
|
26
|
-
System.out.println("GC cumulated overhead " + (percent / 10) + "." + (percent % 10) + "%");
|
data/lib/LogGC_1.java
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// http://docs.oracle.com/javase/7/docs/jre/api/management/extension/com/sun/management/GarbageCollectionNotificationInfo.html
|
3
|
-
public class LogGC {
|
4
|
-
|
5
|
-
public static void installGCMonitoring() {
|
6
|
-
//get all the GarbageCollectorMXBeans - there's one for each heap generation
|
7
|
-
//so probably two - the old generation and young generation
|
8
|
-
List<GarbageCollectorMXBean> gcbeans = java.lang.management.ManagementFactory.getGarbageCollectorMXBeans();
|
9
|
-
//Install a notifcation handler for each bean
|
10
|
-
for (GarbageCollectorMXBean gcbean : gcbeans) {
|
11
|
-
System.out.println(gcbean);
|
12
|
-
NotificationEmitter emitter = (NotificationEmitter) gcbean;
|
13
|
-
//use an anonymously generated listener for this example
|
14
|
-
// - proper code should really use a named class
|
15
|
-
NotificationListener listener = new NotificationListener() {
|
16
|
-
//keep a count of the total time spent in GCs
|
17
|
-
long totalGcDuration = 0;
|
18
|
-
|
19
|
-
//implement the notifier callback handler
|
20
|
-
@Override
|
21
|
-
public void handleNotification(Notification notification, Object handback) {
|
22
|
-
//we only handle GARBAGE_COLLECTION_NOTIFICATION notifications here
|
23
|
-
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
|
24
|
-
//get the information associated with this notification
|
25
|
-
GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());
|
26
|
-
//get all the info and pretty print it
|
27
|
-
long duration = info.getGcInfo().getDuration();
|
28
|
-
String gctype = info.getGcAction();
|
29
|
-
if ("end of minor GC".equals(gctype)) {
|
30
|
-
gctype = "Young Gen GC";
|
31
|
-
} else if ("end of major GC".equals(gctype)) {
|
32
|
-
gctype = "Old Gen GC";
|
33
|
-
}
|
34
|
-
System.out.println();
|
35
|
-
System.out.println(gctype + ": - " + info.getGcInfo().getId() + " " + info.getGcName() + " (from " + info.getGcCause() + ") " + duration + " microseconds; start-end times " + info.getGcInfo().getStartTime() + "-" + info.getGcInfo().getEndTime());
|
36
|
-
//System.out.println("GcInfo CompositeType: " + info.getGcInfo().getCompositeType());
|
37
|
-
//System.out.println("GcInfo MemoryUsageAfterGc: " + info.getGcInfo().getMemoryUsageAfterGc());
|
38
|
-
//System.out.println("GcInfo MemoryUsageBeforeGc: " + info.getGcInfo().getMemoryUsageBeforeGc());
|
39
|
-
|
40
|
-
//Get the information about each memory space, and pretty print it
|
41
|
-
Map<String, MemoryUsage> membefore = info.getGcInfo().getMemoryUsageBeforeGc();
|
42
|
-
Map<String, MemoryUsage> mem = info.getGcInfo().getMemoryUsageAfterGc();
|
43
|
-
for (Entry<String, MemoryUsage> entry : mem.entrySet()) {
|
44
|
-
String name = entry.getKey();
|
45
|
-
MemoryUsage memdetail = entry.getValue();
|
46
|
-
long memInit = memdetail.getInit();
|
47
|
-
long memCommitted = memdetail.getCommitted();
|
48
|
-
long memMax = memdetail.getMax();
|
49
|
-
long memUsed = memdetail.getUsed();
|
50
|
-
MemoryUsage before = membefore.get(name);
|
51
|
-
long beforepercent = ((before.getUsed() * 1000L) / before.getCommitted());
|
52
|
-
long percent = ((memUsed * 1000L) / before.getCommitted()); //>100% when it gets expanded
|
53
|
-
|
54
|
-
System.out.print(name + (memCommitted == memMax ? "(fully expanded)" : "(still expandable)") + "used: " + (beforepercent / 10) + "." + (beforepercent % 10) + "%->" + (percent / 10) + "." + (percent % 10) + "%(" + ((memUsed / 1048576) + 1) + "MB) / ");
|
55
|
-
}
|
56
|
-
System.out.println();
|
57
|
-
totalGcDuration += info.getGcInfo().getDuration();
|
58
|
-
long percent = totalGcDuration * 1000L / info.getGcInfo().getEndTime();
|
59
|
-
System.out.println("GC cumulated overhead " + (percent / 10) + "." + (percent % 10) + "%");
|
60
|
-
}
|
61
|
-
}
|
62
|
-
};
|
63
|
-
|
64
|
-
//Add the listener
|
65
|
-
emitter.addNotificationListener(listener, null, null);
|
66
|
-
}
|
67
|
-
}
|
68
|
-
}
|