semantic_logger 2.3.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: af5bb50d17c02c2223f455fb8d88aa072bd2a85d
4
- data.tar.gz: fe9b9a744c901b75efd79f8facefdce06e0af7ff
3
+ metadata.gz: 986fd023dd3d5b61817027e25aeae6b6919f65f2
4
+ data.tar.gz: 7c94accd89688c3ee66fb05c1f17eaba10183abb
5
5
  SHA512:
6
- metadata.gz: 1ddaf5707fbc254cd56dc1f25eab6e7360bec4678235123935b2911cfd805fc3e9a955c947e718411d64ab04c21fda17d6f87d726568d7b71159a0ab35ca4037
7
- data.tar.gz: 51fd7e505173dd2d701cba1daed8566986bf01d4f03584dda000687afc30bd0e7bcb5f14b7c8928927e98ad1bf0616fe37891cd894212d3e403544807653219b
6
+ metadata.gz: 48eeadcce9890d4d8adb53c8a76c98b259a230f8c7c0c41f3d2ae62ce94bfc850a51c7e6a143064590960aac5e0b12759ec01a396ff9bad93459ecfc81b48778
7
+ data.tar.gz: ce6a05fe76874b04e2a28bfaf0a09aeb790c9fdc119744dd0b975e22286402a0c62909d67f04fe6d885ed1873397e9b31614528ea285ec696d30a69ab852bafd
data/README.md CHANGED
@@ -5,13 +5,13 @@ Improved logging for Ruby
5
5
 
6
6
  * http://github.com/ClarityServices/semantic_logger
7
7
 
8
- ### Note:
8
+ ## Note:
9
9
 
10
10
  As of SemanticLogger V2.0 the Rails logging is no longer automatically replaced
11
11
  when including SemanticLogger. Include the [rails_semantic_logger](http://github.com/ClarityServices/rails_semantic_logger)
12
12
  gem to replace the Rails default logger with SemanticLogger
13
13
 
14
- ### Overview
14
+ ## Overview
15
15
 
16
16
  Semantic Logger takes logging in Ruby to a new level by adding several new
17
17
  capabilities to the commonly used Logging API:
@@ -132,7 +132,7 @@ Thread Safe
132
132
  * Tagged logging keeps any tagging data on a per-thread basis to ensure that
133
133
  tags from different threads are not inter-mingled
134
134
 
135
- ### Introduction
135
+ ## Introduction
136
136
 
137
137
  Semantic Logger is a Logger that supports logging of meta-data, along with text messages
138
138
  to multiple appenders
@@ -183,9 +183,9 @@ Since Semantic Logger can call existing Loggers, it does not force end-users
183
183
  to have to adopt a Semantic aware adapter. Although, such adapters create
184
184
  tremendous value in the problem monitoring and determination processes.
185
185
 
186
- ### Logging API
186
+ ## Logging API
187
187
 
188
- #### Standard Logging methods
188
+ ### Standard Logging methods
189
189
 
190
190
  The Semantic Logger logging API supports the existing logging interface for
191
191
  the Rails and Ruby Loggers. For example:
@@ -231,7 +231,7 @@ logger.debug("Calling Supplier", :request => 'update', :user => 'Jack')
231
231
  logger.debug { "A total of #{result.inject(0) {|sum, i| i+sum }} were processed" }
232
232
  ```
233
233
 
234
- ### Exceptions
234
+ ## Exceptions
235
235
 
236
236
  The Semantic Logger adds an optional parameter to the existing log methods so that
237
237
  a corresponding Exception can be logged in a standard way
@@ -246,7 +246,7 @@ rescue Exception => exception
246
246
  end
247
247
  ```
248
248
 
249
- #### Payload
249
+ ### Payload
250
250
 
251
251
  The Semantic Logger adds an extra parameter to the existing log methods so that
252
252
  additional payload can be logged, such as a Hash or a Ruby Exception object.
@@ -260,7 +260,7 @@ regular expressions so that a program can analyze log output. With the MongoDB
260
260
  appender the payload is written directly to MongoDB as part of the document and
261
261
  is therefore fully searchable
262
262
 
263
- #### Benchmarking
263
+ ### Benchmarking
264
264
 
265
265
  Another common logging requirement is to measure the time it takes to execute a block
266
266
  of code based on the log level. For example:
@@ -317,7 +317,7 @@ Parameters
317
317
  Optional, Ruby Exception object to log along with the duration of the supplied block
318
318
  ```
319
319
 
320
- #### Logging levels
320
+ ### Logging levels
321
321
 
322
322
  The following logging levels are available through Semantic Logger
323
323
 
@@ -336,7 +336,7 @@ in the development environment for low level trace logging of methods calls etc.
336
336
  If only the rails logger is being used, then :trace level calls will be logged
337
337
  as debug calls only if the log level is set to trace
338
338
 
339
- #### Changing the Class name for Log Entries
339
+ ### Changing the Class name for Log Entries
340
340
 
341
341
  When Semantic Logger is included in a Rails project it automatically replaces the
342
342
  loggers for Rails, ActiveRecord::Base, ActionController::Base, and ActiveResource::Base
@@ -375,7 +375,7 @@ This will result in the log output identifying the log entry as from the Externa
375
375
 
376
376
  2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] (5.2ms) ExternalSupplier -- Calling external interface
377
377
 
378
- #### Tagged Logging
378
+ ### Tagged Logging
379
379
 
380
380
  Semantic Logger allows any Ruby or Rails program to also include tagged logging.
381
381
 
@@ -393,7 +393,7 @@ logger.tagged(tracking_number) do
393
393
  end
394
394
  ```
395
395
 
396
- #### Beyond Tagged Logging
396
+ ### Beyond Tagged Logging
397
397
 
398
398
  Blocks of code can be tagged with not only values, but can be tagged with
399
399
  entire hashes of data. The additional hash of data will be merged into
@@ -409,7 +409,7 @@ logger.with_payload(:user => 'Jack', :zip_code => 12345) do
409
409
  end
410
410
  ```
411
411
 
412
- ### Using SemanticLogger
412
+ ## Standalone SemanticLogger
413
413
 
414
414
  When using SemanticLogger inside of Rails all we need to do is include the
415
415
  rails_semantic_logger gem and the default Rails logger will be replaced with
@@ -533,17 +533,34 @@ class ExternalSupplier
533
533
  end
534
534
  ```
535
535
 
536
- ### Configuration
536
+ ### Logging to Syslog
537
+
538
+ Log to a local Syslog:
539
+ ```ruby
540
+ require 'semantic_logger'
541
+ SemanticLogger.default_level = :trace
542
+ SemanticLogger.add_appender(SemanticLogger::Appender::Syslog.new)
543
+ ```
544
+
545
+ Log to a local file and to a remote Syslog server such as syslog-ng over TCP:
546
+ ```ruby
547
+ require 'semantic_logger'
548
+ SemanticLogger.default_level = :trace
549
+ SemanticLogger.add_appender('development.log')
550
+ SemanticLogger.add_appender(SemanticLogger::Appender::Syslog.new(:server => 'tcp://myloghost:514'))
551
+ ```
552
+
553
+ ## Configuration
537
554
 
538
555
  The Semantic Logger follows the principle where multiple appenders can be active
539
556
  at the same time. For example, this allows one to log to MongoDB and the Rails
540
557
  log file at the same time.
541
558
 
542
- #### Rails Configuration
559
+ ### Rails Configuration
543
560
 
544
561
  To automatically replace the Rails logger with Semantic Logger use the gem [rails_semantic_logger](http://github.com/ClarityServices/rails_semantic_logger)
545
562
 
546
- ### Log Struct
563
+ ## Log Struct
547
564
 
548
565
  Internally all log messages are passed around in a Log Struct. In order
549
566
  to write your own custom formatter or log appender it is necessary to understand
@@ -589,7 +606,7 @@ level_index [Integer]
589
606
 
590
607
  * Internal use only. Index of the log level
591
608
 
592
- #### Mixing Logging Levels
609
+ ### Mixing Logging Levels
593
610
 
594
611
  It is sometimes useful to log a subset of the log messages to a separate file
595
612
  or appender. For example, log :error and :fatal level messages to a special
@@ -627,7 +644,7 @@ The output is as follows:
627
644
  2013-08-02 14:15:56.735273 W [35669:70176909690580] MyClass -- This is a warning message
628
645
  ```
629
646
 
630
- #### Custom Formatters
647
+ ### Custom Formatters
631
648
 
632
649
  The formatting for each appender can be replaced with custom code. To replace the
633
650
  existing formatter supply a block of code when creating the appender.
@@ -704,21 +721,7 @@ end
704
721
  SemanticLogger.add_appender(mongodb_appender)
705
722
  ```
706
723
 
707
- ### SysLog and other standard loggers
708
-
709
- To write log entries to a Syslog logger or any other logger of your choice,
710
- that conforms the standard Ruby Logger API, Semantic Logger has an Appender to
711
- use that logger.
712
-
713
- For example to configure rails to also log to the Syslogger gem:
714
- ```ruby
715
- config.after_initialize do
716
- # Besides logging to the local file also log to Syslogger
717
- config.semantic_logger.appenders << SemanticLogger::Appender::Wrapper.new(Syslogger.new("yourappname"))
718
- end
719
- ```
720
-
721
- ### Performance
724
+ ## Performance
722
725
 
723
726
  The traditional logging implementations write their log information to file in the
724
727
  same thread of execution as the program itself. This means that for every log entry
@@ -731,12 +734,12 @@ Also, since the logging is in this separate thread there is no impact to program
731
734
  execution if we decided to add another appender.
732
735
  For example, log to both a file and a MongoDB collection.
733
736
 
734
- ### Log Rotation
737
+ ## Log Rotation
735
738
 
736
739
  Since the log file is not re-opened with every call, when the log file needs
737
740
  to be rotated, use a copy-truncate operation over deleting the file.
738
741
 
739
- ### Why Semantic logging?
742
+ ## Why Semantic logging?
740
743
 
741
744
  Just as there is the initiative to add Semantic information to data on the web
742
745
  so that computers can directly understand the content without having to resort
@@ -750,7 +753,7 @@ Once the logging data is in the NOSQL data store it can be queried quickly and
750
753
  efficiently. Some SQL data stores also allow complex data types that could be used
751
754
  for storing and querying the logging data
752
755
 
753
- ### Architecture & Performance
756
+ ## Architecture & Performance
754
757
 
755
758
  In order to ensure that logging does not hinder the performance of the application
756
759
  all log entries are written to thread-safe Queue. A separate thread is responsible
@@ -766,7 +769,7 @@ terminates it will call flush on each of the appenders.
766
769
  Calling SemanticLogger::Logger#flush will wait until all outstanding log messages
767
770
  have been written and flushed to their respective appenders before returning.
768
771
 
769
- ### Write your own Appender
772
+ ## Write your own Appender
770
773
 
771
774
  To write your own appender it should meet the following requirements:
772
775
 
@@ -821,12 +824,12 @@ instructions below.
821
824
  Very Important: New appenders will not be accepted without complete working tests.
822
825
  See the [MongoDB Appender Test](https://github.com/ClarityServices/semantic_logger/blob/master/test/appender_mongodb_test.rb) for an example.
823
826
 
824
- ### Dependencies
827
+ ## Dependencies
825
828
 
826
829
  - Ruby MRI 1.8.7, 1.9.3 (or above) Or, JRuby 1.6.3 (or above)
827
830
  - Optional: To log to MongoDB, Mongo Ruby Driver 1.5.2 or above
828
831
 
829
- ### Install
832
+ ## Install
830
833
 
831
834
  gem install semantic_logger
832
835
 
@@ -834,7 +837,7 @@ To log to MongoDB, it also needs the Ruby Mongo Driver
834
837
 
835
838
  gem install mongo
836
839
 
837
- ### Future
840
+ ## Future
838
841
 
839
842
  - Add support for a configuration file that can set log level by class name
840
843
  - Configuration file to support adding appenders
@@ -850,15 +853,20 @@ Meta
850
853
 
851
854
  This project uses [Semantic Versioning](http://semver.org/).
852
855
 
853
- Authors
856
+ Author
854
857
  -------
855
858
 
856
859
  Reid Morrison :: reidmo@gmail.com :: @reidmorrison
857
860
 
861
+ Contributors
862
+ ------------
863
+
864
+ Marc Bellingrath :: marrrc.b@gmail.com
865
+
858
866
  License
859
867
  -------
860
868
 
861
- Copyright 2012,2013 Clarity Services, Inc.
869
+ Copyright 2012,2013 Reid Morrison
862
870
 
863
871
  Licensed under the Apache License, Version 2.0 (the "License");
864
872
  you may not use this file except in compliance with the License.
@@ -13,5 +13,6 @@ module SemanticLogger
13
13
  autoload :File, 'semantic_logger/appender/file'
14
14
  autoload :Wrapper, 'semantic_logger/appender/wrapper'
15
15
  autoload :MongoDB, 'semantic_logger/appender/mongodb'
16
+ autoload :Syslog, 'semantic_logger/appender/syslog'
16
17
  end
17
18
  end
@@ -41,22 +41,33 @@ module SemanticLogger
41
41
  #
42
42
  def initialize(filename, level=nil, &block)
43
43
  raise "filename cannot be null when initializing the SemanticLogging::Appender::File" unless filename
44
- @filename = filename
45
44
  @log = if filename.respond_to?(:write) and filename.respond_to?(:close)
46
45
  filename
47
46
  else
48
- @log = open(filename, (::File::WRONLY | ::File::APPEND | ::File::CREAT))
49
- # Force all log entries to write immediately without buffering
50
- # Allows multiple processes to write to the same log file simultaneously
51
- @log.sync = true
52
- @log.set_encoding(Encoding::BINARY) if @log.respond_to?(:set_encoding)
53
- @log
47
+ @filename = filename
48
+ reopen
54
49
  end
55
50
 
56
51
  # Set the log level and formatter if supplied
57
52
  super(level, &block)
58
53
  end
59
54
 
55
+ # After forking an active process call #reopen to re-open
56
+ # open the file handles etc to resources
57
+ #
58
+ # Note: This method will only work if a String filename was supplied
59
+ # on the initializer.
60
+ def reopen
61
+ return unless @filename
62
+
63
+ @log = open(@filename, (::File::WRONLY | ::File::APPEND | ::File::CREAT))
64
+ # Force all log entries to write immediately without buffering
65
+ # Allows multiple processes to write to the same log file simultaneously
66
+ @log.sync = true
67
+ @log.set_encoding(Encoding::BINARY) if @log.respond_to?(:set_encoding)
68
+ @log
69
+ end
70
+
60
71
  # Pass log calls to the underlying Rails, log4j or Ruby logger
61
72
  # trace entries are mapped to debug since :trace is not supported by the
62
73
  # Ruby or Rails Loggers
@@ -0,0 +1,249 @@
1
+ # syslog appender for SemanticLogger - Supports local and remote syslog (over TCP or UDP)
2
+ #
3
+ # Example 1
4
+ # Log to the local syslog.
5
+ #
6
+ # require 'semantic_logger'
7
+ # SemanticLogger.default_level = :trace
8
+ #
9
+ # syslog_appender = SemanticLogger::Appender::Syslog.new
10
+ # SemanticLogger.add_appender(syslog_appender)
11
+ #
12
+ # logger = SemanticLogger['SyslogAppenderExample']
13
+ # logger.info "Info Hello! - This message should appear in the local syslog!"
14
+ #
15
+ #
16
+ # Example 2
17
+ # Send to a remote syslog appender - myloghost - over TCP on port 514.
18
+ # Tested with syslog-ng as part of an ELSA installation.
19
+ # https://code.google.com/p/enterprise-log-search-and-archive/
20
+ #
21
+ # require 'semantic_logger'
22
+ # # Only log warn and above messages to the remote syslog.
23
+ # syslog_appender = SemanticLogger::Appender::Syslog.new(level: :warn, server: 'tcp://myloghost:514')
24
+ # SemanticLogger.add_appender(syslog_appender)
25
+ #
26
+ # logger = SemanticLogger['SyslogAppenderExample']
27
+ # logger.info "Info Hello! - The log level is too low and will not be logged."
28
+ # logger.error "Error! Error! - This message should appear in the remote syslog!"
29
+ #
30
+ require 'syslog'
31
+ require 'uri'
32
+ require 'socket'
33
+
34
+ module SemanticLogger
35
+ module Appender
36
+ class Syslog < SemanticLogger::Appender::Base
37
+
38
+ attr_reader :remote_syslog, :server, :host, :port, :protocol, :facility, :local_hostname
39
+
40
+ # Default mapping of ruby log levels to syslog log levels
41
+ #
42
+ # ::Syslog::LOG_EMERG - "System is unusable"
43
+ # ::Syslog::LOG_ALERT - "Action needs to be taken immediately"
44
+ # ::Syslog::LOG_CRIT - "A critical condition has occurred"
45
+ # ::Syslog::LOG_ERR - "An error occurred"
46
+ # ::Syslog::LOG_WARNING - "Warning of a possible problem"
47
+ # ::Syslog::LOG_NOTICE - "A normal but significant condition occurred"
48
+ # ::Syslog::LOG_INFO - "Informational message"
49
+ # ::Syslog::LOG_DEBUG - "Debugging information"
50
+ DEFAULT_LEVEL_MAP = {
51
+ :fatal => ::Syslog::LOG_CRIT,
52
+ :error => ::Syslog::LOG_ERR,
53
+ :warn => ::Syslog::LOG_WARNING,
54
+ :info => ::Syslog::LOG_NOTICE,
55
+ :debug => ::Syslog::LOG_INFO,
56
+ :trace => ::Syslog::LOG_DEBUG
57
+ }
58
+
59
+ # For more information on the Syslog constants used below see http://ruby-doc.org/stdlib-2.0.0/libdoc/syslog/rdoc/Syslog.html
60
+ # Parameters
61
+ #
62
+ # :ident [String]
63
+ # Identity of the program
64
+ # Default: 'ruby'
65
+ #
66
+ # :options [Integer]
67
+ # Default: ::Syslog::LOG_PID | ::Syslog::LOG_CONS
68
+ # Any of the following (options can be logically OR'd together)
69
+ # ::Syslog::LOG_CONS
70
+ # ::Syslog::LOG_NDELAY
71
+ # ::Syslog::LOG_NOWAIT
72
+ # ::Syslog::LOG_ODELAY
73
+ # ::Syslog::LOG_PERROR
74
+ # ::Syslog::LOG_PID
75
+ #
76
+ # :facility [Integer]
77
+ # Default: ::Syslog::LOG_USER
78
+ # Type of program (can be logically OR'd together)
79
+ # ::Syslog::LOG_AUTH
80
+ # ::Syslog::LOG_AUTHPRIV
81
+ # ::Syslog::LOG_CONSOLE
82
+ # ::Syslog::LOG_CRON
83
+ # ::Syslog::LOG_DAEMON
84
+ # ::Syslog::LOG_FTP
85
+ # ::Syslog::LOG_KERN
86
+ # ::Syslog::LOG_LRP
87
+ # ::Syslog::LOG_MAIL
88
+ # ::Syslog::LOG_NEWS
89
+ # ::Syslog::LOG_NTP
90
+ # ::Syslog::LOG_SECURITY
91
+ # ::Syslog::LOG_SYSLOG
92
+ # ::Syslog::LOG_USER
93
+ # ::Syslog::LOG_UUCP
94
+ # ::Syslog::LOG_LOCAL0
95
+ # ::Syslog::LOG_LOCAL1
96
+ # ::Syslog::LOG_LOCAL2
97
+ # ::Syslog::LOG_LOCAL3
98
+ # ::Syslog::LOG_LOCAL4
99
+ # ::Syslog::LOG_LOCAL5
100
+ # ::Syslog::LOG_LOCAL6
101
+ # ::Syslog::LOG_LOCAL7
102
+ #
103
+ # :level [Symbol]
104
+ # Default: SemanticLogger's log level.
105
+ # The minimum level at which this appender will write logs. Any log messages below this level will be ignored.
106
+ #
107
+ # :level_map [Hash]
108
+ # Supply a custom map of SemanticLogger levels to syslog levels.
109
+ # For example, passing in { :warn => ::Syslog::LOG_NOTICE }
110
+ # would result in a log mapping that matches the default level map,
111
+ # except for :warn, which ends up with a LOG_NOTICE level instead of a
112
+ # LOG_WARNING one.
113
+ # Without overriding any parameters, the level map will be
114
+ # LEVEL_MAP = {
115
+ # :fatal => ::Syslog::LOG_CRIT,
116
+ # :error => ::Syslog::LOG_ERR,
117
+ # :warn => ::Syslog::LOG_WARNING,
118
+ # :info => ::Syslog::LOG_NOTICE,
119
+ # :debug => ::Syslog::LOG_INFO,
120
+ # :trace => ::Syslog::LOG_DEBUG
121
+ # }
122
+ #
123
+ # :local_hostname [String]
124
+ # Default: Socket.gethostname || `hostname`.strip
125
+ # Hostname to provide to the remote syslog.
126
+ #
127
+ # :server [String]
128
+ # Default: 'syslog://localhost'
129
+ # For writing logs to a remote syslog server
130
+ # URI of server: protocol://host:port
131
+ # Uses port 514 by default for TCP and UDP.
132
+ # local syslog example: 'syslog://localhost'
133
+ # TCP example with default port: 'tcp://logger'
134
+ # TCP example with custom port: 'tcp://logger:8514'
135
+ # UDP example with default port: 'udp://logger'
136
+ # UDP example with custom port: 'udp://logger:8514'
137
+ # When using the :syslog protocol, logs will always be sent to the localhost syslog
138
+ #
139
+ # :tcp_client [Hash]
140
+ # Default: {}
141
+ # Only used with the TCP protocol.
142
+ # Specify custom parameters to pass into ResilientSocket.TCPClient.new
143
+ # For a list of options see the resilient_socket documentation:
144
+ # https://github.com/reidmorrison/resilient_socket/blob/master/lib/resilient_socket/tcp_client.rb
145
+ def initialize(params = {}, &block)
146
+ params = params.dup
147
+ @ident = params.delete(:ident) || 'ruby'
148
+ options = params.delete(:options) || (::Syslog::LOG_PID | ::Syslog::LOG_CONS)
149
+ @facility = params.delete(:facility) || ::Syslog::LOG_USER
150
+ level = params.delete(:level)
151
+ level_map = params.delete(:level_map)
152
+ @level_map = DEFAULT_LEVEL_MAP.dup
153
+ @level_map.update(level_map) if level_map
154
+ @server = params.delete(:server) || 'syslog://localhost'
155
+ uri = URI(@server)
156
+ @host = uri.host || 'localhost'
157
+ @protocol = (uri.scheme || :syslog).to_sym
158
+ raise "Unknown protocol #{@protocol}!" unless [:syslog, :tcp, :udp].include?(@protocol)
159
+ @host = 'localhost' if @protocol == :syslog
160
+ @port = URI(@server).port || 514
161
+ @local_hostname = params.delete(:local_hostname) || Socket.gethostname || `hostname`.strip
162
+ tcp_client_options = params.delete(:tcp_client)
163
+
164
+ # Warn about any unknown configuration options.
165
+ params.each_pair { |key,val| SemanticLogger::Logger.logger.warn "Ignoring unknown configuration option: #{key.inspect} => #{val.inspect}" }
166
+
167
+ # The syslog_protocol gem is required when logging over TCP or UDP.
168
+ if [:tcp, :udp].include?(@protocol)
169
+ begin
170
+ require 'syslog_protocol'
171
+ rescue LoadError
172
+ raise 'Missing gem: syslog_protocol. This gem is required when logging over TCP or UDP. To fix this error: gem install syslog_protocol'
173
+ end
174
+ end
175
+
176
+ case @protocol
177
+ when :syslog
178
+ ::Syslog.open(@ident, options, @facility)
179
+ when :tcp
180
+ # The resilient_socket gem is required when logging over TCP.
181
+ begin
182
+ require 'resilient_socket'
183
+ rescue LoadError
184
+ raise 'Missing gem: resilient_socket. This gem is required when logging over TCP. To fix this error: gem install resilient_socket'
185
+ end
186
+ options = tcp_client_options || {}
187
+ options[:server] = "#{@host}:#{@port}"
188
+ @remote_syslog = ResilientSocket::TCPClient.new(options)
189
+ # Use the local logger for @remote_syslog so errors with the remote logger can be recorded locally.
190
+ @remote_syslog.logger = SemanticLogger::Logger.logger
191
+ when :udp
192
+ @remote_syslog = UDPSocket.new
193
+ else
194
+ raise "Unsupported protocol: #{protocol}"
195
+ end
196
+
197
+ super(level, &block)
198
+ end
199
+
200
+ # Write the log using the specified protocol and host.
201
+ def log(log)
202
+ if level_index <= (log.level_index || 0)
203
+ case @protocol
204
+ when :syslog
205
+ ::Syslog.log @level_map[log.level], formatter.call(log)
206
+ when :tcp
207
+ @remote_syslog.retry_on_connection_failure { @remote_syslog.write("#{syslog_packet_formatter(log)}\r\n") }
208
+ when :udp
209
+ @remote_syslog.send syslog_packet_formatter(log), 0, @host, @port
210
+ else
211
+ raise "Unsupported protocol: #{protocol}"
212
+ end
213
+ end
214
+ end
215
+
216
+ # Flush is called by the semantic_logger during shutdown.
217
+ def flush
218
+ # TODO Add flush for :tcp.
219
+ end
220
+
221
+ # Custom log formatter for syslog
222
+ def default_formatter
223
+ Proc.new do |log|
224
+ tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
225
+
226
+ message = log.message.to_s
227
+ message << " -- " << log.payload.inspect if log.payload
228
+ message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
229
+
230
+ duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
231
+
232
+ "#{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{duration_str}#{log.name} -- #{message}"
233
+ end
234
+ end
235
+
236
+ # Format the syslog packet so it can be sent over TCP or UDP
237
+ def syslog_packet_formatter(log)
238
+ packet = SyslogProtocol::Packet.new
239
+ packet.hostname = @local_hostname
240
+ packet.facility = @facility
241
+ packet.severity = @level_map[log.level]
242
+ packet.tag = @ident
243
+ packet.content = default_formatter.call(log)
244
+ packet.to_s
245
+ end
246
+
247
+ end
248
+ end
249
+ end
@@ -122,6 +122,14 @@ module SemanticLogger
122
122
  SemanticLogger::Logger.flush
123
123
  end
124
124
 
125
+ # After forking an active process call SemanticLogger.reopen to re-open
126
+ # any open file handles etc to resources
127
+ #
128
+ # Note: Only appenders that implement the reopen method will be called
129
+ def self.reopen
130
+ @@appenders.each {|appender| appender.reopen if appender.respond_to?(:reopen)}
131
+ end
132
+
125
133
  ############################################################################
126
134
  protected
127
135
 
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger #:nodoc
2
- VERSION = "2.3.1"
2
+ VERSION = "2.4.0"
3
3
  end
@@ -0,0 +1,50 @@
1
+ # Allow test to be run in-place without requiring a gem install
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'shoulda'
7
+ require 'mocha/setup'
8
+ require 'semantic_logger'
9
+ require 'socket'
10
+ require 'resilient_socket'
11
+ require 'syslog_protocol'
12
+
13
+ # Unit Test for SemanticLogger::Appender::Syslog
14
+ #
15
+ class AppenderSyslogTest < Test::Unit::TestCase
16
+ context SemanticLogger::Appender::Syslog do
17
+
18
+ should 'handle local syslog' do
19
+ ::Syslog.expects(:open).once
20
+ ::Syslog.expects(:log).once
21
+ syslog_appender = SemanticLogger::Appender::Syslog.new
22
+ syslog_appender.debug 'AppenderSyslogTest log message'
23
+ end
24
+
25
+ should 'handle remote syslog over TCP' do
26
+ ::ResilientSocket::TCPClient.any_instance.stubs('closed?').returns(false)
27
+ ::ResilientSocket::TCPClient.any_instance.stubs('connect')
28
+ ::ResilientSocket::TCPClient.any_instance.expects(:write).with{ |message| message =~ /<70>(.*?)SemanticLogger::Appender::Syslog -- AppenderSyslogTest log message\r\n/ }
29
+ syslog_appender = SemanticLogger::Appender::Syslog.new(:server => 'tcp://localhost:88888')
30
+ syslog_appender.debug 'AppenderSyslogTest log message'
31
+ end
32
+
33
+ should 'handle remote syslog over UDP' do
34
+ ::UDPSocket.any_instance.expects(:send).with{ |*params| params[0] =~ /<70>(.*?)SemanticLogger::Appender::Syslog -- AppenderSyslogTest log message/ }
35
+ syslog_appender = SemanticLogger::Appender::Syslog.new(:server => 'udp://localhost:88888')
36
+ syslog_appender.debug 'AppenderSyslogTest log message'
37
+ end
38
+
39
+ # Should be able to log each level.
40
+ SemanticLogger::LEVELS.each do |level|
41
+ should "log #{level} information" do
42
+ ::Syslog.expects(:open).once
43
+ ::Syslog.expects(:log).once
44
+ syslog_appender = SemanticLogger::Appender::Syslog.new
45
+ syslog_appender.send(level, 'AppenderSyslogTest #{level.to_s} message')
46
+ end
47
+ end
48
+
49
+ end
50
+ 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.3.1
4
+ version: 2.4.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: 2013-09-24 00:00:00.000000000 Z
11
+ date: 2013-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sync_attr
@@ -49,6 +49,7 @@ files:
49
49
  - lib/semantic_logger/appender/base.rb
50
50
  - lib/semantic_logger/appender/file.rb
51
51
  - lib/semantic_logger/appender/mongodb.rb
52
+ - lib/semantic_logger/appender/syslog.rb
52
53
  - lib/semantic_logger/appender/wrapper.rb
53
54
  - lib/semantic_logger/base.rb
54
55
  - lib/semantic_logger/loggable.rb
@@ -61,6 +62,7 @@ files:
61
62
  - README.md
62
63
  - test/appender_file_test.rb
63
64
  - test/appender_mongodb_test.rb
65
+ - test/appender_syslog_test.rb
64
66
  - test/appender_wrapper_test.rb
65
67
  - test/loggable_test.rb
66
68
  - test/logger_test.rb
@@ -92,6 +94,7 @@ summary: Improved logging for Ruby
92
94
  test_files:
93
95
  - test/appender_file_test.rb
94
96
  - test/appender_mongodb_test.rb
97
+ - test/appender_syslog_test.rb
95
98
  - test/appender_wrapper_test.rb
96
99
  - test/loggable_test.rb
97
100
  - test/logger_test.rb