This file is indexed.

/usr/lib/ruby/1.8/needle/logger.rb is in libneedle-ruby1.8 1.3.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#--
# =============================================================================
# Copyright (c) 2004, Jamis Buck (jamis@37signals.com)
# All rights reserved.
#
# This source file is distributed as part of the Needle dependency injection
# library for Ruby. This file (and the library as a whole) may be used only as
# allowed by either the BSD license, or the Ruby license (or, by association
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
# distribution for the texts of these licenses.
# -----------------------------------------------------------------------------
# needle website : http://needle.rubyforge.org
# project website: http://rubyforge.org/projects/needle
# =============================================================================
#++

require 'logger'
require 'strscan'
require 'needle/errors'

module Needle

  # A specialization of the standard Logger class that comes with Ruby. This
  # provides the additional functionality of a fully-customizable message
  # format, whereas the original only provided a customizable date format.
  class Logger < ::Logger

    # The brief name of this logger (derived from #progname).
    attr_reader :name

    # The format string for the message (+nil+ if the default should be used)
    attr_reader :message_format

    # The map of specifier options supported by this class.
    SPECIFIER_OPTIONS = {
      "c" => { :type => "s", :value => "@name" },
      "C" => { :type => "s", :value => "self.progname" },
      "d" => { :type => "s", :value => "opts[:timestamp]" },
      "F" => { :type => "s", :value => "opts[:caller_file]" },
      "l" => { :type => "s", :value => "opts[:caller_info]" },
      "L" => { :type => "d", :value => "opts[:caller_line]" },
      "m" => { :type => "s", :value => "opts[:msg]" },
      "M" => { :type => "s", :value => "opts[:caller_method]" },
      "n" => { :type => "s", :value => "$/" },
      "p" => { :type => "s", :value => "opts[:severity]" },
      "t" => { :type => "d", :value => "Thread.current.__id__" },
      "%" => { :type => "s", :value => "'%'" },
      "P" => { :type => "s", :value => "opts[:progname]" },
      "$" => { :type => "d", :value => "$$" }
    }

    # The regular expression for matching specifier patterns in the
    # format strings.
    SPECIFIER_PATTERN = /(.*?)%(-?\d*(?:\.\d+)?)?([cCdFlLmMnpt%$P])/

    # Extracts the unqualified name from the progname, after setting the
    # progname.
    def progname=( progname )
      super
      @name = progname.split( /\./ ).last
    end

    # Changes the device that the given logger writes to, to be the given
    # device. Does so in a thread-safe manner.
    def write_to( device, shift_age = 0, shift_size = 1048576 )
      saved_critical = Thread.critical
      Thread.critical = true

      if device
        if device.respond_to?( :write ) && device.respond_to?( :close )
          @logdev = device
        else
          @logdev = Logger::LogDevice.new( device,
            :shift_age => shift_age, 
            :shift_size => shift_size )
        end
      end

      device
    ensure
      Thread.critical = saved_critical
    end

    # Set the message format string to the given string. This also pre-parses
    # the format for faster processing.
    #
    # The format string is a printf-formatted string, which supports the following
    # format specifiers:
    #
    # c:: the unqualified name of the logger
    # C:: the fully-qualified name of the logger
    # d:: the date/time string (as formatted by the #datetime_format string)
    # F:: the filename of the calling routine
    # l:: the location of the calling routine
    # L:: the line number of the calling routine
    # m:: the message to log
    # M:: the name of the calling method
    # n:: the newline character
    # p:: the name of the priority (or severity) used to log this method
    # t:: the id of the current thread
    # %:: a percentage character
    # P:: the progname that was passed to the logger method
    # $:: the current process id
    def message_format=( format )
      @message_format = format
      return unless format

      @needs_caller_info = false

      format_string = ""
      format_parameters = []

      @message_format_tokens = []
      format.scan( SPECIFIER_PATTERN ) do |v|
        format_string << v[0] if v[0].length > 0
        opts = SPECIFIER_OPTIONS[ v[2] ]
        format_string << "%#{v[1]}#{opts[:type]}"
        format_parameters << opts[:value]
        @needs_caller_info = true if v[2] =~ /[FlLM]/
      end
      format_string << $' if $'.length > 0
      format_string << "\n"

      definition =
        "proc { |opts| #{format_string.inspect} " +
        "% [ #{format_parameters.join(',')} ] }"
      @message_formatter = eval( definition )
    end

    # Format the message using the given parameters. If a message format has
    # not been given, just call the superclass's implementation. Otherwise,
    # process the tokens from the parsed message format.
    def format_message( severity, timestamp, *args )
      if @message_format.nil?
        super
      else
        msg, progname = args
        
        # check for API change in 1.8.3 and later
        msg, progname = progname, msg if respond_to?(:formatter=)

        opts = {
          :severity => severity,
          :timestamp => timestamp,
          :msg => msg,
          :progname => progname
        }
        
        if @needs_caller_info
          stack = caller
          stack.shift while stack.first =~ /\blogger\.rb/
          opts[:caller_info] = caller_info = stack.first
          match = caller_info.match( /(.*):(\d+)(?::in `(.*)')?/ )
          opts[:caller_file] = match[1]
          opts[:caller_line] = match[2]
          opts[:caller_method] = match[3]
        end

        @message_formatter.call( opts )
      end
    end
    private :format_message

  end

end