Module: Lumberjack::Utils

Defined in:
lib/lumberjack/utils.rb

Overview

Utils provides utility methods and helper functions used throughout the Lumberjack logging framework.

Class Method Summary collapse

Class Method Details

.current_line(root_path = nil) ⇒ String

Get the current line of code that calls this method. This is useful for debugging purposes to record the exact location in your code that generated a log entry.

Examples:

Adding source location to log entries

logger.info("Something happened", source: Lumberjack::Utils.current_line)
# Logs: "Something happened" with source: "/path/to/file.rb:123:in `method_name'"

Parameters:

  • root_path (String, Pathname, nil) (defaults to: nil)

    An optional root path to strip from the file path.

Returns:

  • (String)

    A string representation of the caller location (file:line:method).



107
108
109
110
111
112
113
114
115
116
# File 'lib/lumberjack/utils.rb', line 107

def current_line(root_path = nil)
  location = caller_locations(1, 1)[0]
  path = location.path
  if root_path
    root_path = root_path.to_s
    root_path = "#{root_path}#{File::SEPARATOR}" unless root_path.end_with?(File::SEPARATOR)
    path = path.delete_prefix(root_path)
  end
  "#{path}:#{location.lineno}:in `#{location.label}'"
end

.deprecated(method, message) { ... } ⇒ Object

Print warning when deprecated methods are called the first time. This can be disabled by setting Lumberjack.deprecation_mode to :silent.

In order to cut down on noise, each deprecated method will only print a warning once per process. You can change this by setting Lumberjack.deprecation_mode to :verbose.

Examples:

def old_method
  Utils.deprecated(:old_method, "Use new_method instead.") do
    # deprecated implementation
  end
end

Parameters:

  • method (String, Symbol)

    The name of the deprecated method.

  • message (String)

    The deprecation message explaining what to use instead.

Yields:

  • The block containing the deprecated functionality to execute.

Returns:

  • (Object)

    The result of the yielded block.



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
# File 'lib/lumberjack/utils.rb', line 40

def deprecated(method, message)
  if Lumberjack.deprecation_mode != :silent && !@deprecations&.include?(method)
    @deprecations_lock ||= Mutex.new
    @deprecations_lock.synchronize do
      @deprecations ||= {}
      unless @deprecations.include?(method)
        trace = ($VERBOSE && Lumberjack.deprecation_mode != :raise) ? caller[3..] : caller[3, 1]
        if trace.first.start_with?(__dir__) && !$VERBOSE
          non_lumberjack_caller = caller[4..].detect { |line| !line.start_with?(__dir__) }
          trace = [non_lumberjack_caller] if non_lumberjack_caller
        end
        message = "DEPRECATION WARNING: #{message} Called from #{trace.join(Lumberjack::LINE_SEPARATOR)}"

        if Lumberjack.deprecation_mode == :raise
          raise DeprecationError, message
        end

        unless Lumberjack.deprecation_mode == :verbose
          @deprecations[method] = true
        end

        warn(message)
      end
    end
  end

  yield if block_given?
end

.expand_attributes(attributes) ⇒ Hash

Expand a hash containing dot notation keys into a nested hash structure. This is the inverse operation of flatten_attributes and is useful for converting flat attribute structures back into nested hashes.

Examples:

Basic expansion

flat = {"user.id" => 123, "user.name" => "Alice", "action" => "login"}
Lumberjack::Utils.expand_attributes(flat)
# => {"user" => {"id" => 123, "name" => "Alice"}, "action" => "login"}

Deep nesting

flat = {"app.db.host" => "localhost", "app.db.port" => 5432, "app.debug" => true}
Lumberjack::Utils.expand_attributes(flat)
# => {"app" => {"db" => {"host" => "localhost", "port" => 5432}, "debug" => true}}

Mixed with existing nested structures

mixed = {"user.id" => 123, "settings" => {"theme" => "dark"}}
Lumberjack::Utils.expand_attributes(mixed)
# => {"user" => {"id" => 123}, "settings" => {"theme" => "dark"}}

Parameters:

  • attributes (Hash)

    The hash with dot notation keys to expand. Non-hash values are ignored.

Returns:

  • (Hash)

    A nested hash with dot notation keys expanded into nested structures.



245
246
247
248
249
# File 'lib/lumberjack/utils.rb', line 245

def expand_attributes(attributes)
  return {} unless attributes.is_a?(Hash)

  expand_dot_notation_hash(attributes)
end

.expand_tags(tags) ⇒ Hash

Deprecated.

Use expand_attributes instead.

Alias for expand_attributes to provide compatibility with the 1.x API. This method will eventually be removed in a future version.

Parameters:

  • tags (Hash)

    The hash to expand.

Returns:

  • (Hash)

    The expanded hash.



257
258
259
260
261
# File 'lib/lumberjack/utils.rb', line 257

def expand_tags(tags)
  Utils.deprecated("Lumberjack::Utils.expand_tags", "Lumberjack::Utils.expand_tags is deprecated and will be removed in version 2.1; use expand_attributes instead.") do
    expand_attributes(tags)
  end
end

.flatten_attributes(attr_hash) ⇒ Hash<String, Object>

Flatten a nested attribute hash into a single-level hash using dot notation for nested keys. This is useful for converting structured data into a flat format suitable for logging systems that don’t support nested structures.

Examples:

Basic flattening

hash = {user: {id: 123, profile: {name: "Alice"}}, action: "login"}
Lumberjack::Utils.flatten_attributes(hash)
# => {"user.id" => 123, "user.profile.name" => "Alice", "action" => "login"}

With mixed types

hash = {config: {db: {host: "localhost", port: 5432}}, debug: true}
Lumberjack::Utils.flatten_attributes(hash)
# => {"config.db.host" => "localhost", "config.db.port" => 5432, "debug" => true}

Parameters:

  • attr_hash (Hash)

    The hash to flatten. Non-hash values are ignored.

Returns:

  • (Hash<String, Object>)

    A flattened hash with dot-notation keys.



206
207
208
209
210
# File 'lib/lumberjack/utils.rb', line 206

def flatten_attributes(attr_hash)
  return {} unless attr_hash.is_a?(Hash)

  flatten_hash_recursive(attr_hash)
end

.flatten_tags(tag_hash) ⇒ Hash<String, Object>

Deprecated.

Use flatten_attributes instead.

Alias for flatten_attributes to provide compatibility with the 1.x API. This method will eventually be removed in a future version.

Parameters:

  • tag_hash (Hash)

    The hash to flatten.

Returns:

  • (Hash<String, Object>)

    The flattened hash.



218
219
220
221
222
# File 'lib/lumberjack/utils.rb', line 218

def flatten_tags(tag_hash)
  Utils.deprecated("Lumberjack::Utils.flatten_tags", "Lumberjack::Utils.flatten_tags is deprecated and will be removed in version 2.1; use flatten_attributes instead.") do
    flatten_attributes(tag_hash)
  end
end

.force_utf8(str) ⇒ String?

Force encode a string to UTF-8, handling invalid byte sequences gracefully. Any invalid or undefined byte sequences will be replaced with an empty string, ensuring the result is always valid UTF-8.

Examples:

# Handles strings with invalid encoding
bad_string = "Hello\xff\xfeWorld".force_encoding("ASCII-8BIT")
Lumberjack::Utils.force_utf8(bad_string)  # => "HelloWorld"

Parameters:

  • str (String, nil)

    The string to encode. Returns nil if input is nil.

Returns:

  • (String, nil)

    The UTF-8 encoded string, or nil if input was nil.



184
185
186
187
188
# File 'lib/lumberjack/utils.rb', line 184

def force_utf8(str)
  return nil if str.nil?

  str.dup.force_encoding("ASCII-8BIT").encode("UTF-8", invalid: :replace, undef: :replace, replace: "")
end

.global_pid(pid = Process.pid) ⇒ String

Generate a global process identifier that includes the hostname and process ID. This creates a unique identifier that can distinguish processes across different machines.

Examples:

Lumberjack::Utils.global_pid
# => "server1-12345"

Returns:

  • (String)

    The global process ID in the format “hostname-pid”.



135
136
137
138
139
140
141
# File 'lib/lumberjack/utils.rb', line 135

def global_pid(pid = Process.pid)
  if hostname
    "#{hostname}-#{pid}"
  else
    pid.to_s
  end
end

.global_thread_idString

Generate a global thread identifier that includes the global process ID and thread name. This creates a unique identifier for threads across processes and machines.

Examples:

Lumberjack::Utils.global_thread_id
# => "server1-12345-main" or "server1-12345-worker-1"

Returns:

  • (String)

    The global thread ID in the format “hostname-pid-threadname”.



151
152
153
# File 'lib/lumberjack/utils.rb', line 151

def global_thread_id
  "#{global_pid}-#{thread_name}"
end

.hostnameString

Get the hostname of the machine. The returned value will be in UTF-8 encoding. The hostname is cached after the first call for performance.

Returns:

  • (String)

    The hostname of the machine in UTF-8 encoding.



91
92
93
94
95
96
# File 'lib/lumberjack/utils.rb', line 91

def hostname
  if @hostname.equal?(UNDEFINED)
    @hostname = force_utf8(Socket.gethostname)
  end
  @hostname
end

.hostname=(hostname) ⇒ void

This method returns an undefined value.

Set the hostname to a specific value. This overrides the system hostname. Useful for testing or when you want to use a specific identifier.

Parameters:

  • hostname (String)

    The hostname to use.



123
124
125
# File 'lib/lumberjack/utils.rb', line 123

def hostname=(hostname)
  @hostname = force_utf8(hostname)
end

.thread_name(thread = Thread.current) ⇒ String

Get a safe name for a thread. Uses the thread’s assigned name if available, otherwise generates a unique identifier based on the thread’s object ID. Non-alphanumeric characters (except underscores, dashes, and periods) are replaced with dashes to create URL-safe identifiers.

Examples:

Thread.current.name = "worker-thread"
Lumberjack::Utils.thread_name  # => "worker-thread"

# For unnamed threads
Lumberjack::Utils.thread_name  # => "2c001a80c" (based on object_id)

Parameters:

  • thread (Thread) (defaults to: Thread.current)

    The thread to get the name for. Defaults to the current thread.

Returns:

  • (String)

    A safe string identifier for the thread.



169
170
171
# File 'lib/lumberjack/utils.rb', line 169

def thread_name(thread = Thread.current)
  thread.name ? slugify(thread.name) : thread.object_id.to_s(36)
end

.with_deprecation_mode(mode) { ... } ⇒ Object

Helper method for tests to silence deprecation warnings within a block. You should not use this in production code since it will silence all deprecation warnings globally across all threads.

Parameters:

  • mode (Symbol, String)

    The deprecation mode to set within the block. Valid values are :normal, :verbose, :silent, and :raise.

Yields:

  • The block in which to silence deprecation warnings.

Returns:

  • (Object)

    The result of the yielded block.



77
78
79
80
81
82
83
84
85
# File 'lib/lumberjack/utils.rb', line 77

def with_deprecation_mode(mode)
  save_mode = Lumberjack.deprecation_mode
  begin
    Lumberjack.deprecation_mode = mode
    yield
  ensure
    Lumberjack.deprecation_mode = save_mode
  end
end