logsly 1.2.0 → 1.3.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/lib/logsly/colors.rb +2 -2
  4. data/lib/logsly/logging182/appender.rb +290 -0
  5. data/lib/logsly/logging182/appenders/buffering.rb +398 -0
  6. data/lib/logsly/logging182/appenders/console.rb +81 -0
  7. data/lib/logsly/logging182/appenders/email.rb +178 -0
  8. data/lib/logsly/logging182/appenders/file.rb +85 -0
  9. data/lib/logsly/logging182/appenders/growl.rb +200 -0
  10. data/lib/logsly/logging182/appenders/io.rb +84 -0
  11. data/lib/logsly/logging182/appenders/rolling_file.rb +338 -0
  12. data/lib/logsly/logging182/appenders/string_io.rb +92 -0
  13. data/lib/logsly/logging182/appenders/syslog.rb +215 -0
  14. data/lib/logsly/logging182/appenders.rb +64 -0
  15. data/lib/logsly/logging182/color_scheme.rb +248 -0
  16. data/lib/logsly/logging182/config/configurator.rb +187 -0
  17. data/lib/logsly/logging182/config/yaml_configurator.rb +190 -0
  18. data/lib/logsly/logging182/diagnostic_context.rb +332 -0
  19. data/lib/logsly/logging182/layout.rb +132 -0
  20. data/lib/logsly/logging182/layouts/basic.rb +38 -0
  21. data/lib/logsly/logging182/layouts/parseable.rb +256 -0
  22. data/lib/logsly/logging182/layouts/pattern.rb +568 -0
  23. data/lib/logsly/logging182/layouts.rb +9 -0
  24. data/lib/logsly/logging182/log_event.rb +44 -0
  25. data/lib/logsly/logging182/logger.rb +509 -0
  26. data/lib/logsly/logging182/proxy.rb +59 -0
  27. data/lib/logsly/logging182/rails_compat.rb +36 -0
  28. data/lib/logsly/logging182/repository.rb +231 -0
  29. data/lib/logsly/logging182/root_logger.rb +60 -0
  30. data/lib/logsly/logging182/stats.rb +277 -0
  31. data/lib/logsly/logging182/utils.rb +231 -0
  32. data/lib/logsly/logging182.rb +559 -0
  33. data/lib/logsly/outputs.rb +5 -5
  34. data/lib/logsly/version.rb +1 -1
  35. data/lib/logsly.rb +6 -6
  36. data/logsly.gemspec +4 -2
  37. data/test/unit/colors_tests.rb +3 -3
  38. data/test/unit/logsly_tests.rb +14 -14
  39. data/test/unit/outputs_tests.rb +34 -24
  40. metadata +45 -6
@@ -0,0 +1,568 @@
1
+
2
+ module Logsly::Logging182::Layouts
3
+
4
+ # Accessor / Factory for the Pattern layout.
5
+ #
6
+ def self.pattern( *args )
7
+ return ::Logsly::Logging182::Layouts::Pattern if args.empty?
8
+ ::Logsly::Logging182::Layouts::Pattern.new(*args)
9
+ end
10
+
11
+ # A flexible layout configurable with pattern string.
12
+ #
13
+ # The goal of this class is to format a LogEvent and return the results as
14
+ # a String. The results depend on the conversion pattern.
15
+ #
16
+ # The conversion pattern is closely related to the conversion pattern of
17
+ # the sprintf function. A conversion pattern is composed of literal text
18
+ # and format control expressions called conversion specifiers.
19
+ #
20
+ # You are free to insert any literal text within the conversion pattern.
21
+ #
22
+ # Each conversion specifier starts with a percent sign (%) and is followed
23
+ # by optional format modifiers and a conversion character. The conversion
24
+ # character specifies the type of data, e.g. logger, level, date, thread
25
+ # ID. The format modifiers control such things as field width, padding,
26
+ # left and right justification. The following is a simple example.
27
+ #
28
+ # Let the conversion pattern be "%-5l [%c]: %m\n" and assume that the
29
+ # logging environment was set to use a Pattern layout. Then the statements
30
+ #
31
+ # root = Logsly::Logging182.logger[:root]
32
+ # root.debug("Message 1")
33
+ # root.warn("Message 2")
34
+ #
35
+ # would yield the output
36
+ #
37
+ # DEBUG [root]: Message 1
38
+ # WARN [root]: Message 2
39
+ #
40
+ # Note that there is no explicit separator between text and conversion
41
+ # specifiers. The pattern parser knows when it has reached the end of a
42
+ # conversion specifier when it reads a conversion character. In the example
43
+ # above the conversion specifier %-5l means the level of the logging event
44
+ # should be left justified to a width of five characters. The recognized
45
+ # conversion characters are
46
+ #
47
+ # [c] Used to output the name of the logger that generated the log
48
+ # event. Supports an optional "precision" described further below.
49
+ # [d] Used to output the date of the log event. The format of the
50
+ # date is specified using the :date_pattern option when the Layout
51
+ # is created. ISO8601 format is assumed if not date pattern is given.
52
+ # [F] Used to output the file name where the logging request was issued.
53
+ # [l] Used to output the level of the log event.
54
+ # [L] Used to output the line number where the logging request was
55
+ # issued.
56
+ # [m] Used to output the application supplied message associated with
57
+ # the log event.
58
+ # [M] Used to output the method name where the logging request was
59
+ # issued.
60
+ # [p] Used to output the process ID of the currently running program.
61
+ # [r] Used to output the number of milliseconds elapsed from the
62
+ # construction of the Layout until creation of the log event.
63
+ # [t] Used to output the object ID of the thread that generated the
64
+ # log event.
65
+ # [T] Used to output the name of the thread that generated the log event.
66
+ # Name can be specified using Thread.current[:name] notation. Output
67
+ # empty string if name not specified. This option helps to create
68
+ # more human readable output for multi-threaded application logs.
69
+ # [X] Used to output values from the Mapped Diagnostic Context. Requires
70
+ # a key name to lookup the value from the context. More details are
71
+ # listed below.
72
+ # [x] Used to output values from the Nested Diagnostic Context. Supports
73
+ # an optional context separator string. More details are listed below.
74
+ # [%] The sequence '%%' outputs a single percent sign.
75
+ #
76
+ # The logger name directive 'c' accepts an optional precision that will
77
+ # only print the rightmost number of namespace identifiers for the logger.
78
+ # By default the logger name is printed in full. For example, for the
79
+ # logger name "Foo::Bar::Baz" the pattern %c{2} will output "Bar::Baz".
80
+ #
81
+ # The directives F, L, and M will only work if the Logger generating the
82
+ # events is configured to generate tracing information. If this is not
83
+ # the case these fields will always be empty.
84
+ #
85
+ # The directives for include diagnostic context information in the log
86
+ # messages are X and x. For the Mapped Diagnostic Context the directive must
87
+ # be accompanied by the key identifying the value to insert into the log
88
+ # message. The X directive can appear multiple times to include multiple
89
+ # values from the mapped context.
90
+ #
91
+ # %X{Cookie} Insert the current session cookie
92
+ # %X{X-Session} Insert a session identifier
93
+ #
94
+ # For the Nested Diagnostic Context you need only include the directive
95
+ # once. All contexts currently in the stack will be added to the log message
96
+ # separated by spaces. If spaces are not your style, a separator string can
97
+ # be given, too.
98
+ #
99
+ # %x Insert all contexts separated by spaces
100
+ # %x{, } Insert all contexts separate by a comma and a space
101
+ #
102
+ # By default the relevant information is output as is. However, with the
103
+ # aid of format modifiers it is possible to change the minimum field width,
104
+ # the maximum field width and justification.
105
+ #
106
+ # The optional format modifier is placed between the percent sign and the
107
+ # conversion character.
108
+ #
109
+ # The first optional format modifier is the left justification flag which
110
+ # is just the minus (-) character. Then comes the optional minimum field
111
+ # width modifier. This is a decimal constant that represents the minimum
112
+ # number of characters to output. If the data item requires fewer
113
+ # characters, it is padded on either the left or the right until the
114
+ # minimum width is reached. The default is to pad on the left (right
115
+ # justify) but you can specify right padding with the left justification
116
+ # flag. The padding character is space. If the data item is larger than the
117
+ # minimum field width, the field is expanded to accommodate the data. The
118
+ # value is never truncated.
119
+ #
120
+ # This behavior can be changed using the maximum field width modifier which
121
+ # is designated by a period followed by a decimal constant. If the data
122
+ # item is longer than the maximum field, then the extra characters are
123
+ # removed from the end of the data item.
124
+ #
125
+ # Below are various format modifier examples for the category conversion
126
+ # specifier.
127
+ #
128
+ # %20c Left pad with spaces if the logger name is less than 20
129
+ # characters long
130
+ # %-20c Right pad with spaces if the logger name is less than 20
131
+ # characters long
132
+ # %.30c Truncates the logger name if it is longer than 30 characters
133
+ # %20.30c Left pad with spaces if the logger name is shorter than
134
+ # 20 characters. However, if the logger name is longer than
135
+ # 30 characters, then truncate the name.
136
+ # %-20.30c Right pad with spaces if the logger name is shorter than
137
+ # 20 characters. However, if the logger name is longer than
138
+ # 30 characters, then truncate the name.
139
+ #
140
+ # Below are examples of some conversion patterns.
141
+ #
142
+ # %.1l, [%d] %5l -- %c: %m\n
143
+ #
144
+ # This is how the Logger class in the Ruby standard library formats
145
+ # messages. The main difference will be in the date format (the Pattern
146
+ # Layout uses the ISO8601 date format). Set the :date_method on the
147
+ # Pattern Layout to be 'to_s' and then the date formats will agree.
148
+ #
149
+ class Pattern < ::Logsly::Logging182::Layout
150
+
151
+ # default date format
152
+ ISO8601 = "%Y-%m-%d %H:%M:%S".freeze
153
+
154
+ # call-seq:
155
+ # Pattern.create_date_format_methods( pf )
156
+ #
157
+ # This method will create the +date_format+ method in the given Pattern
158
+ # Layout _pf_ based on the configured date patten and/or date method
159
+ # specified by the user.
160
+ #
161
+ def self.create_date_format_methods( pf )
162
+ code = "undef :format_date if method_defined? :format_date\n"
163
+ code << "def format_date( time )\n"
164
+ if pf.date_method.nil?
165
+ if pf.date_pattern =~ %r/%s/
166
+ code << <<-CODE
167
+ dp = '#{pf.date_pattern}'.gsub('%s','%06d' % time.usec)
168
+ time.strftime dp
169
+ CODE
170
+ else
171
+ code << "time.strftime '#{pf.date_pattern}'\n"
172
+ end
173
+ else
174
+ code << "time.#{pf.date_method}\n"
175
+ end
176
+ code << "end\n"
177
+ ::Logsly::Logging182.log_internal(0) {code}
178
+
179
+ pf._meta_eval(code, __FILE__, __LINE__)
180
+ end
181
+
182
+ # call-seq:
183
+ # Pattern.create_format_method( pl )
184
+ #
185
+ # This method will create the `format` method in the given Pattern
186
+ # Layout `pl` based on the configured format pattern specified by the
187
+ # user.
188
+ #
189
+ def self.create_format_method( pl )
190
+ builder = FormatMethodBuilder.new(pl)
191
+ code = builder.build_code
192
+
193
+ ::Logsly::Logging182.log_internal(0) {code}
194
+
195
+ pl._meta_eval(code, __FILE__, __LINE__)
196
+ end
197
+ # :startdoc:
198
+
199
+ # call-seq:
200
+ # Pattern.new( opts )
201
+ #
202
+ # Creates a new Pattern layout using the following options.
203
+ #
204
+ # :pattern => "[%d] %-5l -- %c : %m\n"
205
+ # :date_pattern => "%Y-%m-%d %H:%M:%S"
206
+ # :date_method => 'usec' or 'to_s'
207
+ # :color_scheme => :default
208
+ #
209
+ # If used, :date_method will supersede :date_pattern.
210
+ #
211
+ # The :color_scheme is used to apply color formatting to the log messages.
212
+ # Individual tokens can be colorized witch the level token [%l] receiving
213
+ # distinct colors based on the level of the log event. The entire
214
+ # generated log message can also be colorized based on the level of the
215
+ # log event. See the ColorScheme documentation for more details.
216
+ #
217
+ def initialize( opts = {} )
218
+ super
219
+ @created_at = Time.now
220
+
221
+ @date_pattern = opts.getopt(:date_pattern)
222
+ @date_method = opts.getopt(:date_method)
223
+ @date_pattern = ISO8601 if @date_pattern.nil? and @date_method.nil?
224
+
225
+ @pattern = opts.getopt(:pattern,
226
+ "[%d] %-#{::Logsly::Logging182::MAX_LEVEL_LENGTH}l -- %c : %m\n")
227
+
228
+ cs_name = opts.getopt(:color_scheme)
229
+ @color_scheme =
230
+ case cs_name
231
+ when false, nil; nil
232
+ when true; ::Logsly::Logging182::ColorScheme[:default]
233
+ else ::Logsly::Logging182::ColorScheme[cs_name] end
234
+
235
+ Pattern.create_date_format_methods(self)
236
+ Pattern.create_format_method(self)
237
+ end
238
+
239
+ attr_reader :pattern, :date_pattern, :date_method, :color_scheme
240
+
241
+ # call-seq:
242
+ # appender.pattern = "[%d] %-5l -- %c : %m\n"
243
+ #
244
+ # Set the message formatting pattern to be used by the layout.
245
+ #
246
+ def pattern=( var )
247
+ @pattern = var
248
+ Pattern.create_format_method(self)
249
+ end
250
+
251
+ # call-seq:
252
+ # appender.date_pattern = "%Y-%m-%d %H:%M:%S"
253
+ #
254
+ # Set the date formatting pattern to be used when outputting timestamps
255
+ # in the log messages.
256
+ #
257
+ def date_pattern=( var )
258
+ @date_pattern = var
259
+ Pattern.create_date_format_methods(self)
260
+ end
261
+
262
+ # call-seq:
263
+ # appender.date_method = 'to_s'
264
+ # appender.date_method = :usec
265
+ #
266
+ # Set the date method to be used when outputting timestamps in the log
267
+ # messages. If a date method is configured, the output of that method
268
+ # will be used in leu of the date pattern.
269
+ #
270
+ def date_method=( var )
271
+ @date_method = var
272
+ Pattern.create_date_format_methods(self)
273
+ end
274
+
275
+ # :stopdoc:
276
+
277
+ # call-seq:
278
+ # _meta_eval( code )
279
+ #
280
+ # Evaluates the given string of _code_ if the singleton class of this
281
+ # Pattern Layout object.
282
+ #
283
+ def _meta_eval( code, file = nil, line = nil )
284
+ meta = class << self; self end
285
+ meta.class_eval code, file, line
286
+ end
287
+ # :startdoc:
288
+
289
+ # This class is used to build the `format` method for the Pattern layout. It
290
+ # parses the user defined pattern and emits Ruby source code (as a string)
291
+ # that can be `eval`d in the context of the Pattern layout instance.
292
+ class FormatMethodBuilder
293
+ # Matches the first directive encountered and the stuff around it.
294
+ #
295
+ # * $1 is the stuff before directive or "" if not applicable
296
+ # * $2 is the %#.# match within directive group
297
+ # * $3 is the directive letter
298
+ # * $4 is the precision specifier for the logger name
299
+ # * $5 is the stuff after the directive or "" if not applicable
300
+ DIRECTIVE_RGXP = %r/([^%]*)(?:(%-?\d*(?:\.\d+)?)([a-zA-Z%])(?:\{([^\}]+)\})?)?(.*)/m
301
+
302
+ # Arguments to sprintf keyed to directive letters
303
+ DIRECTIVE_TABLE = {
304
+ 'c' => 'event.logger'.freeze,
305
+ 'd' => 'format_date(event.time)'.freeze,
306
+ 'F' => 'event.file'.freeze,
307
+ 'l' => 'Logsly::Logging182::LNAMES[event.level]'.freeze,
308
+ 'L' => 'event.line'.freeze,
309
+ 'm' => 'format_obj(event.data)'.freeze,
310
+ 'M' => 'event.method'.freeze,
311
+ 'h' => "'#{Socket.gethostname}'".freeze,
312
+ 'p' => 'Process.pid'.freeze,
313
+ 'r' => 'Integer((event.time-@created_at)*1000).to_s'.freeze,
314
+ 't' => 'Thread.current.object_id.to_s'.freeze,
315
+ 'T' => 'Thread.current[:name]'.freeze,
316
+ 'X' => :placeholder,
317
+ 'x' => :placeholder,
318
+ '%' => :placeholder
319
+ }.freeze
320
+
321
+ # Human name aliases for directives - used for colorization of tokens
322
+ COLOR_ALIAS_TABLE = {
323
+ 'c' => :logger,
324
+ 'd' => :date,
325
+ 'm' => :message,
326
+ 'h' => :hostname,
327
+ 'p' => :pid,
328
+ 'r' => :time,
329
+ 'T' => :thread,
330
+ 't' => :thread_id,
331
+ 'F' => :file,
332
+ 'L' => :line,
333
+ 'M' => :method,
334
+ 'X' => :mdc,
335
+ 'x' => :ndc
336
+ }.freeze
337
+
338
+ attr_reader :layout
339
+ attr_accessor :pattern
340
+ attr_reader :color_scheme
341
+ attr_reader :sprintf_args
342
+ attr_reader :format_string
343
+ attr_accessor :name_map_count
344
+
345
+ # Creates the format method builder and initializes some variables from
346
+ # the given Patter layout instance.
347
+ #
348
+ # pattern_layout - The Pattern Layout instance
349
+ #
350
+ def initialize( pattern_layout )
351
+ @layout = pattern_layout
352
+ @pattern = layout.pattern.dup
353
+ @color_scheme = layout.color_scheme
354
+
355
+ @sprintf_args = []
356
+ @format_string = '"'
357
+ @name_map_count = 0
358
+ end
359
+
360
+ # Returns `true` if the log messages should be colorized.
361
+ def colorize?
362
+ color_scheme && !color_scheme.lines?
363
+ end
364
+
365
+ # Returns `true` if the log messages should be colorized by line.
366
+ def colorize_lines?
367
+ color_scheme && color_scheme.lines?
368
+ end
369
+
370
+ # Returns `true` if the log levels have special colorization defined.
371
+ def colorize_levels?
372
+ color_scheme && color_scheme.levels?
373
+ end
374
+
375
+ # This method returns a String which can be `eval`d in the context of the
376
+ # Pattern layout. When it is `eval`d, a `format` method is defined in the
377
+ # Pattern layout.
378
+ #
379
+ # At the heart of the format method is `sprintf`. The conversion pattern
380
+ # specified in the Pattern layout is parsed and converted into a format
381
+ # string and corresponding arguments list. The format string and arguments
382
+ # are then processed by `sprintf` to format log events.
383
+ #
384
+ # Returns a Ruby code as a String.
385
+ def build_code
386
+ build_format_string
387
+
388
+ sprintf = "sprintf("
389
+ sprintf << format_string
390
+ sprintf << ', ' + sprintf_args.join(', ') unless sprintf_args.empty?
391
+ sprintf << ")"
392
+
393
+ if colorize_lines?
394
+ sprintf = "color_scheme.color(#{sprintf}, Logsly::Logging182::LNAMES[event.level])"
395
+ end
396
+
397
+ code = "undef :format if method_defined? :format\n"
398
+ code << "def format( event )\n#{sprintf}\nend\n"
399
+ end
400
+
401
+ # This method builds the format string used by `sprintf` to format log
402
+ # events. The conversion pattern given by the user is iteratively parsed
403
+ # by a regular expression into separate format directives. Each directive
404
+ # builds up the format string and the corresponding arguments list that
405
+ # will be formatted.
406
+ #
407
+ # The actual building of the format string is handled by separate
408
+ # directive specific methods. Those handlers also populate the arguments
409
+ # list passed to `sprintf`.
410
+ #
411
+ # Returns the format String.
412
+ def build_format_string
413
+ while true
414
+ match = DIRECTIVE_RGXP.match(pattern)
415
+ _, pre, format, directive, precision, post = *match
416
+ format_string << pre unless pre.empty?
417
+
418
+ case directive
419
+ when '%'; format_string << '%%'
420
+ when 'c'; handle_logger( format, directive, precision )
421
+ when 'l'; handle_level( format, directive, precision )
422
+ when 'X'; handle_mdc( format, directive, precision )
423
+ when 'x'; handle_ndc( format, directive, precision )
424
+
425
+ when *DIRECTIVE_TABLE.keys
426
+ handle_directives(format, directive, precision)
427
+
428
+ when nil; break
429
+ else
430
+ raise ArgumentError, "illegal format character - '#{directive}'"
431
+ end
432
+
433
+ break if post.empty?
434
+ self.pattern = post
435
+ end
436
+
437
+ format_string << '"'
438
+ end
439
+
440
+ # Add the logger name to the `format_string` and the `sprintf_args`. The
441
+ # `slice` argument is a little interesting - this is the number of logger
442
+ # name segments to keep. If we have a logger named "Foo::Bar::Baz" and our
443
+ # `slice` is 2, then "Bar::Baz" will appear in the generated log message.
444
+ # So the `slice` selects the last two parts of the logger name.
445
+ #
446
+ # format - format String
447
+ # directive - the directive character ('c')
448
+ # slice - the number of name segments to keep
449
+ #
450
+ # Returns nil
451
+ def handle_logger( format, directive, slice )
452
+ fmt = format + 's'
453
+ fmt = color_scheme.color(fmt, COLOR_ALIAS_TABLE[directive]) if colorize?
454
+
455
+ format_string << fmt
456
+ sprintf_args << DIRECTIVE_TABLE[directive].dup
457
+
458
+ if slice
459
+ numeric = Integer(slice) rescue nil
460
+ if numeric
461
+ raise ArgumentError, "logger name slice must be an integer greater than zero: #{numeric}" unless numeric > 0
462
+ sprintf_args.last <<
463
+ ".split(Logsly::Logging182::Repository::PATH_DELIMITER)" \
464
+ ".last(#{slice}).join(Logsly::Logging182::Repository::PATH_DELIMITER)"
465
+ else
466
+ format_string << "{#{slice}}"
467
+ end
468
+ end
469
+
470
+ nil
471
+ end
472
+
473
+ # Add the log event level to the `format_string` and the `sprintf_args`.
474
+ # The color scheme is taken into account when formatting the log event
475
+ # level.
476
+ #
477
+ # format - format String
478
+ # directive - the directive character ('l')
479
+ # precision - added back to the format string
480
+ #
481
+ # Returns nil
482
+ def handle_level( format, directive, precision )
483
+ if colorize_levels?
484
+ name_map = Logsly::Logging182::LNAMES.map do |name|
485
+ color_scheme.color(("#{format}s" % name), name)
486
+ end
487
+ var = "@name_map_#{name_map_count}"
488
+ layout.instance_variable_set(var.to_sym, name_map)
489
+ self.name_map_count += 1
490
+
491
+ format_string << '%s'
492
+ format_string << "{#{precision}}" if precision
493
+ sprintf_args << "#{var}[event.level]"
494
+ else
495
+ format_string << format + 's'
496
+ format_string << "{#{precision}}" if precision
497
+ sprintf_args << DIRECTIVE_TABLE[directive]
498
+ end
499
+
500
+ nil
501
+ end
502
+
503
+ # Add a Mapped Diagnostic Context to the `format_string` and the
504
+ # `sprintf_args`. Only one MDC value is added at a time, so this directive
505
+ # can appear multiple times using various keys.
506
+ #
507
+ # format - format String
508
+ # directive - the directive character ('X')
509
+ # key - which MDC value to add to the log message
510
+ #
511
+ # Returns nil
512
+ def handle_mdc( format, directive, key )
513
+ raise ArgumentError, "MDC must have a key reference" unless key
514
+ fmt = format + 's'
515
+ fmt = color_scheme.color(fmt, COLOR_ALIAS_TABLE[directive]) if colorize?
516
+
517
+ format_string << fmt
518
+ sprintf_args << "::Logging.mdc['#{key}']"
519
+
520
+ nil
521
+ end
522
+
523
+ # Add a Nested Diagnostic Context to the `format_string` and the
524
+ # `sprintf_args`. Since the NDC is an Array of values, the directive will
525
+ # appear only once in the conversion pattern. A `separator` is inserted
526
+ # between the values in generated log message.
527
+ #
528
+ # format - format String
529
+ # directive - the directive character ('x')
530
+ # separator - used to separate the values in the NDC array
531
+ #
532
+ # Returns nil
533
+ def handle_ndc( format, directive, separator )
534
+ fmt = format + 's'
535
+ fmt = color_scheme.color(fmt, COLOR_ALIAS_TABLE[directive]) if colorize?
536
+
537
+ format_string << fmt
538
+ separator = separator.to_s
539
+ separator = ' ' if separator.empty?
540
+ sprintf_args << "::Logging.ndc.context.join('#{separator}')"
541
+
542
+ nil
543
+ end
544
+
545
+ # Handles the rest of the directives; none of these need any special
546
+ # handling.
547
+ #
548
+ # format - format String
549
+ # directive - the directive character
550
+ # precision - added back to the format string
551
+ #
552
+ # Returns nil
553
+ def handle_directives( format, directive, precision )
554
+ fmt = format + 's'
555
+ fmt = color_scheme.color(fmt, COLOR_ALIAS_TABLE[directive]) if colorize?
556
+
557
+ format_string << fmt
558
+ format_string << "{#{precision}}" if precision
559
+ sprintf_args << DIRECTIVE_TABLE[directive]
560
+
561
+ nil
562
+ end
563
+ end
564
+ # :startdoc:
565
+
566
+ end # Pattern
567
+ end # Logsly::Logging182::Layouts
568
+
@@ -0,0 +1,9 @@
1
+
2
+ module Logsly::Logging182
3
+ module Layouts; end
4
+
5
+ require 'logsly/logging182/layouts/basic'
6
+ require 'logsly/logging182/layouts/parseable'
7
+ require 'logsly/logging182/layouts/pattern'
8
+ end # Logsly::Logging182
9
+
@@ -0,0 +1,44 @@
1
+
2
+ module Logsly::Logging182
3
+
4
+ # This class defines a logging event.
5
+ #
6
+ LogEvent = Struct.new( :logger, :level, :data, :time, :file, :line, :method ) {
7
+ # :stopdoc:
8
+
9
+ # Regular expression used to parse out caller information
10
+ #
11
+ # * $1 == filename
12
+ # * $2 == line number
13
+ # * $3 == method name (might be nil)
14
+ CALLER_RGXP = %r/([-\.\/\(\)\w]+):(\d+)(?::in `(\w+)')?/o
15
+ #CALLER_INDEX = 2
16
+ CALLER_INDEX = ((defined? JRUBY_VERSION and JRUBY_VERSION > '1.6') or (defined? RUBY_ENGINE and RUBY_ENGINE[%r/^rbx/i])) ? 1 : 2
17
+ # :startdoc:
18
+
19
+ # call-seq:
20
+ # LogEvent.new( logger, level, [data], trace )
21
+ #
22
+ # Creates a new log event with the given _logger_ name, numeric _level_,
23
+ # array of _data_ from the user to be logged, and boolean _trace_ flag.
24
+ # If the _trace_ flag is set to +true+ then Kernel::caller will be
25
+ # invoked to get the execution trace of the logging method.
26
+ #
27
+ def initialize( logger, level, data, trace )
28
+ f = l = m = ''
29
+
30
+ if trace
31
+ stack = Kernel.caller[CALLER_INDEX]
32
+ return if stack.nil?
33
+
34
+ match = CALLER_RGXP.match(stack)
35
+ f = match[1]
36
+ l = Integer(match[2])
37
+ m = match[3] unless match[3].nil?
38
+ end
39
+
40
+ super(logger, level, data, Time.now, f, l, m)
41
+ end
42
+ }
43
+ end # module Logsly::Logging182
44
+