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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4d1b60df19e53352219ff825835d2d5c804c1733
4
- data.tar.gz: 936f580069648c8b91d5f3c589671649da3fc726
3
+ metadata.gz: 3a000244f5570ff32c8dcc923f066a131abd7cb0
4
+ data.tar.gz: a9471ed620e7408a195a9292f41730c68ea54e98
5
5
  SHA512:
6
- metadata.gz: b10df7ef8e1561f90f7f07c3f427cd63b90be885fe1b45f5d01c4a78b01dadda2040e416bd7dfc77d409815505ee0394ee2f47e9a1c4fbfaed495b9c9b3b835c
7
- data.tar.gz: 10444abc156d65cd7cab0a788bc5f311b0e1751ec8bf96761ce89d759d9521f91f17b12ea0332f98fd7e247560afba7435fdbf7a9ffaae9461484ebacaef3406
6
+ metadata.gz: 0667f6ef71190a16d66849493630a43f7dce3e8ae2786b38972f84b992cf3f2081995eb4e01c0d72ee47e0b378b49d844dd5883b561db40831f28d20abbff053
7
+ data.tar.gz: d81cddd57a426da87b14b4df0b2b212926e0c5b8405be8d103aa518348d4f65f0d8689bf066b6cf189d85e704b77c9929e874fbe6be9318579e6f6651ee85159
@@ -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 initialization
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['Ruby Thread Dump']
199
+ logger = SemanticLogger['Thread Dump']
200
200
  Thread.list.each do |thread|
201
- backtrace = thread.backtrace ? thread.backtrace.join("\n") : ''
202
- logger.warn "#{thread.name}\n#{backtrace}"
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
 
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger #:nodoc
2
- VERSION = "2.13.1"
2
+ VERSION = "2.14.0"
3
3
  end
@@ -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.13.1
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-02-13 00:00:00.000000000 Z
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: '1.0'
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: '1.0'
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.5
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
- }