class Google::Cloud::Logging::Logger

# Logger

An API-compatible replacement for ruby's Logger that logs to the Stackdriver Logging Service.

@example

require "google/cloud/logging"

logging = Google::Cloud::Logging.new

resource = logging.resource "gae_app",
                            module_id: "1",
                            version_id: "20150925t173233"

logger = logging.logger "my_app_log", resource, env: :production
logger.info "Job started."

@example Provide a hash to write a JSON payload to the log:

require "google/cloud/logging"

logging = Google::Cloud::Logging.new

resource = logging.resource "gae_app",
                            module_id: "1",
                            version_id: "20150925t173233"

logger = logging.logger "my_app_log", resource, env: :production

payload = { "stats" => { "a" => 8, "b" => 12.5} }
logger.info payload

Constants

RequestInfo

A RequestInfo represents data about the request being handled by the current thread. It is used to configure logs coming from that thread.

The trace_id is a String that controls the trace ID sent with the log entry. If it is nil, no trace ID is sent.

The log_name is a String that controls the name of the Stackdriver log to write to. If it is nil, the default log_name for this Logger is used.

Attributes

datetime_format[RW]

This logger does not use a formatter, but it implements this attribute for API compatibility with the standard Logger.

formatter[RW]

This logger does not use a formatter, but it provides a default Logger::Formatter for API compatibility with the standard Logger.

labels[R]

The Google Cloud labels to write the log entry with.

level[R]

The logging severity threshold (e.g. `Logger::INFO`)

local_level[R]

The logging severity threshold (e.g. `Logger::INFO`)

log_name[R]

The Google Cloud log_name to write the log entry with.

progname[R]

The Google Cloud log_name to write the log entry with.

project[RW]

The project ID this logger is sending data to. If set, this value is used to set the trace field of log entries.

resource[R]

The Google Cloud resource to write the log entry with.

sev_threshold[R]

The logging severity threshold (e.g. `Logger::INFO`)

silencer[RW]

Boolean flag that indicates whether this logger can be silenced or not.

writer[R]

The Google Cloud writer object that calls to `#write_entries` are made on. Either an AsyncWriter or Project object.

Public Class Methods

new(writer, log_name, resource, labels = nil) click to toggle source

Create a new Logger instance.

@param [#write_entries] writer The object that will transmit log

entries. Generally, to create a logger that blocks on transmitting
log entries, pass the Project; otherwise, to create a logger that
transmits log entries in the background, pass an AsyncWriter. You
may also pass any other object that responds to `#write_entries`.

@param [String] log_name A log resource name to be associated with the

written log entries.

@param [Google::Cloud::Logging::Resource] resource The monitored

resource to be associated with written log entries.

@param [Hash] labels A set of user-defined data to be associated with

written log entries.

@return [Google::Cloud::Logging::Logger] a Logger object that can be

used in place of a ruby standard library logger object.

@example

require "google/cloud/logging"

logging = Google::Cloud::Logging.new

writer = logging.async_writer max_queue_size: 1000

resource = logging.resource "gae_app", labels: {
                              "module_id" => "1",
                              "version_id" => "20150925t173233"
                            }

logger = Google::Cloud::Logging::Logger.new writer,
                                            "my_app_log",
                                            resource,
                                            env: :production
logger.info "Job started."
# File lib/google/cloud/logging/logger.rb, line 169
def initialize writer, log_name, resource, labels = nil
  @writer = writer
  @log_name = log_name
  @resource = resource
  @labels = labels || {}
  @level = 0 # DEBUG is the default behavior
  @request_info_var = Concurrent::ThreadLocalVar.new
  @closed = false
  # Unused, but present for API compatibility
  @formatter = ::Logger::Formatter.new
  @datetime_format = ""
  @silencer = true

  # The writer is usually a Project or AsyncWriter.
  logging = @writer.respond_to?(:logging) ? @writer.logging : @writer
  @project = logging.project if logging.respond_to? :project
end

Public Instance Methods

<<(msg) click to toggle source

Logs the given message at UNKNOWN severity.

@param [String] msg The log entry payload as a string.

# File lib/google/cloud/logging/logger.rb, line 329
def << msg
  unknown msg
  self
end
add(severity, message = nil, progname = nil) { |: progname| ... } click to toggle source

Log a message if the given severity is high enough. This is the generic logging method. Users will be more inclined to use {#debug}, {#info}, {#warn}, {#error}, and {#fatal}.

@param [Integer, String, Symbol] severity the integer code for or the

name of the severity level

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 310
def add severity, message = nil, progname = nil
  return if @closed

  severity = derive_severity(severity) || ::Logger::UNKNOWN
  return true if severity < @level

  message ||= block_given? ? yield : progname
  # TODO: Figure out what to do with the progname

  write_entry severity, message unless @closed
  true
end
Also aliased as: log
add_request_info(info: nil, env: nil, trace_id: nil, log_name: nil, trace_sampled: nil) click to toggle source

Associate request data with the current Thread. You may provide either the individual pieces of data (trace ID, log name) or a populated RequestInfo object.

@param [RequestInfo] info Info about the current request. Optional.

If not present, a new RequestInfo is created using the remaining
parameters.

@param [String, nil] trace_id The trace ID, or `nil` if no trace ID

should be logged.

@param [String, nil] log_name The log name to use, or nil to use

this logger's default.

@param [Hash, nil] env The request's Rack environment or `nil` if not

available.
# File lib/google/cloud/logging/logger.rb, line 453
def add_request_info info: nil, env: nil, trace_id: nil, log_name: nil,
                     trace_sampled: nil
  info ||= RequestInfo.new trace_id, log_name, env, trace_sampled

  @request_info_var.value = info

  info
end
add_trace_id(trace_id) click to toggle source

Track a given trace_id by associating it with the current Thread

@deprecated Use add_request_info

# File lib/google/cloud/logging/logger.rb, line 434
def add_trace_id trace_id
  add_request_info trace_id: trace_id
end
close() click to toggle source

Close the logging “device”. This effectively disables logging from this logger; any further log messages will be silently ignored. The logger may be re-enabled by calling reopen.

# File lib/google/cloud/logging/logger.rb, line 411
def close
  @closed = true
  self
end
debug(message = nil, &block) click to toggle source

Log a `DEBUG` entry.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 197
def debug message = nil, &block
  if block_given?
    add ::Logger::DEBUG, nil, message, &block
  else
    add ::Logger::DEBUG, message
  end
end
debug?() click to toggle source

Returns `true` if the current severity level allows for sending `DEBUG` messages.

# File lib/google/cloud/logging/logger.rb, line 337
def debug?
  @level <= ::Logger::DEBUG
end
delete_request_info() click to toggle source

Untrack the RequestInfo that's associated with current Thread

@return [RequestInfo] The info that's being deleted

# File lib/google/cloud/logging/logger.rb, line 477
def delete_request_info
  @request_info_var.value = nil
end
Also aliased as: delete_trace_id
delete_trace_id()

@deprecated Use delete_request_info

Alias for: delete_request_info
error(message = nil, &block) click to toggle source

Log an `ERROR` entry.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 251
def error message = nil, &block
  if block_given?
    add ::Logger::ERROR, nil, message, &block
  else
    add ::Logger::ERROR, message
  end
end
error?() click to toggle source

Returns `true` if the current severity level allows for sending `ERROR` messages.

# File lib/google/cloud/logging/logger.rb, line 358
def error?
  @level <= ::Logger::ERROR
end
fatal(message = nil, &block) click to toggle source

Log a `FATAL` entry.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 269
def fatal message = nil, &block
  if block_given?
    add ::Logger::FATAL, nil, message, &block
  else
    add ::Logger::FATAL, message
  end
end
fatal?() click to toggle source

Returns `true` if the current severity level allows for sending `FATAL` messages.

# File lib/google/cloud/logging/logger.rb, line 365
def fatal?
  @level <= ::Logger::FATAL
end
flush() click to toggle source

No-op method. Created to match the spec of ActiveSupport::Logger#flush method when used in Rails application.

# File lib/google/cloud/logging/logger.rb, line 488
def flush
  self
end
info(message = nil, &block) click to toggle source

Log an `INFO` entry.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 215
def info message = nil, &block
  if block_given?
    add ::Logger::INFO, nil, message, &block
  else
    add ::Logger::INFO, message
  end
end
info?() click to toggle source

Returns `true` if the current severity level allows for sending `INFO` messages.

# File lib/google/cloud/logging/logger.rb, line 344
def info?
  @level <= ::Logger::INFO
end
level=(severity) click to toggle source

Sets the logging severity level.

@param [Integer, String, Symbol] severity the integer code for or the

name of the severity level

@example

require "google/cloud/logging"

logging = Google::Cloud::Logging.new

resource = logging.resource "gae_app",
                            module_id: "1",
                            version_id: "20150925t173233"

logger = logging.logger "my_app_log", resource, env: :production

logger.level = "INFO"
logger.debug "Job started." # No log entry written
# File lib/google/cloud/logging/logger.rb, line 396
def level= severity
  new_level = derive_severity severity
  if new_level.nil?
    raise ArgumentError, "invalid log level: #{severity}"
  end
  @level = new_level
end
Also aliased as: sev_threshold=, local_level=
local_level=(severity)
Alias for: level=
log(severity, message = nil, progname = nil)
Alias for: add
progname=(name) click to toggle source

This logger treats progname as an alias for log_name.

# File lib/google/cloud/logging/logger.rb, line 113
def progname= name
  @log_name = name
end
reopen(_logdev = nil) click to toggle source

Re-enable logging if the logger has been closed.

Note that this method accepts a “logdev” argument for compatibility with the standard Ruby Logger class; however, this argument is ignored because this logger does not use a log device.

# File lib/google/cloud/logging/logger.rb, line 423
def reopen _logdev = nil
  @closed = false
  self
end
request_info() click to toggle source

Get the request data for the current Thread

@return [RequestInfo, nil] The request data for the current thread,

or `nil` if there is no data set.
# File lib/google/cloud/logging/logger.rb, line 468
def request_info
  @request_info_var.value
end
sev_threshold=(severity)
Alias for: level=
silence(temp_level = ::Logger::ERROR) { |self| ... } click to toggle source

Filter out low severity messages within block.

@param [Integer] temp_level Severity threshold to filter within the

block. Messages with lower severity will be blocked. Default
::Logger::ERROR

@example

require "google/cloud/logging"

logging = Google::Cloud::Logging.new

resource = logging.resource "gae_app",
                            module_id: "1",
                            version_id: "20150925t173233"

logger = logging.logger "my_app_log", resource, env: :production

logger.silence do
  logger.info "Info message"   # No log entry written
  logger.error "Error message" # Log entry written
end
# File lib/google/cloud/logging/logger.rb, line 514
def silence temp_level = ::Logger::ERROR
  if silencer
    begin
      old_level = level
      self.level = temp_level

      yield self
    ensure
      self.level = old_level
    end
  else
    yield self
  end
end
trace_ids() click to toggle source

A Hash of Thread IDs to Stackdriver request trace ID. The Stackdriver trace ID is a shared request identifier across all Stackdriver services.

This method is deprecated and returns a Hash containing only the current Thread ID/trace_id now.

@deprecated Use request_info

# File lib/google/cloud/logging/logger.rb, line 127
def trace_ids
  current_request_info = request_info
  return {} if current_request_info.nil?
  { current_thread_id => current_request_info.trace_id }
end
unknown(message = nil, &block) click to toggle source

Log an `UNKNOWN` entry. This will be printed no matter what the logger's current severity level is.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 288
def unknown message = nil, &block
  if block_given?
    add ::Logger::UNKNOWN, nil, message, &block
  else
    add ::Logger::UNKNOWN, message
  end
end
unknown?() click to toggle source

Returns `true` if the current severity level allows for sending `UNKNOWN` messages.

# File lib/google/cloud/logging/logger.rb, line 372
def unknown?
  @level <= ::Logger::UNKNOWN
end
warn(message = nil, &block) click to toggle source

Log a `WARN` entry.

@param [String, Hash] message The log entry payload, represented as

either a string, a hash (JSON), or a hash (protocol buffer).

@yield Evaluates to the message to log. This is not evaluated unless

the logger's level is sufficient to log the message. This allows you
to create potentially expensive logging messages that are only
called when the logger is configured to show them.
# File lib/google/cloud/logging/logger.rb, line 233
def warn message = nil, &block
  if block_given?
    add ::Logger::WARN, nil, message, &block
  else
    add ::Logger::WARN, message
  end
end
warn?() click to toggle source

Returns `true` if the current severity level allows for sending `WARN` messages.

# File lib/google/cloud/logging/logger.rb, line 351
def warn?
  @level <= ::Logger::WARN
end

Protected Instance Methods

current_thread_id() click to toggle source

@private Get current thread id

# File lib/google/cloud/logging/logger.rb, line 598
def current_thread_id
  Thread.current.object_id
end
derive_severity(severity) click to toggle source

@private Get the logger level number from severity value object.

# File lib/google/cloud/logging/logger.rb, line 574
def derive_severity severity
  return severity if severity.is_a? Integer

  downcase_severity = severity.to_s.downcase
  case downcase_severity
  when "debug".freeze then ::Logger::DEBUG
  when "info".freeze then ::Logger::INFO
  when "warn".freeze then ::Logger::WARN
  when "error".freeze then ::Logger::ERROR
  when "fatal".freeze then ::Logger::FATAL
  when "unknown".freeze then ::Logger::UNKNOWN
  end
end
entry_labels(info) click to toggle source

@private generate the labels hash for a log entry.

# File lib/google/cloud/logging/logger.rb, line 557
def entry_labels info
  merged_labels = {}

  if info && !info.trace_id.nil?
    merged_labels["traceId"] = info.trace_id
    if Google::Cloud.env.app_engine?
      merged_labels["appengine.googleapis.com/trace_id"] = info.trace_id
    end
  end

  request_env = info&.env || {}

  compute_labels(request_env).merge merged_labels
end
gcloud_severity(severity_int) click to toggle source

@private Get Google Cloud deverity from logger level number.

# File lib/google/cloud/logging/logger.rb, line 590
def gcloud_severity severity_int
  [:DEBUG, :INFO, :WARNING, :ERROR, :CRITICAL, :DEFAULT][severity_int]
rescue StandardError
  :DEFAULT
end
write_entry(severity, message) click to toggle source

@private Write a log entry to the Stackdriver Logging service.

# File lib/google/cloud/logging/logger.rb, line 533
def write_entry severity, message
  entry = Entry.new.tap do |e|
    e.timestamp = Time.now
    e.severity = gcloud_severity severity
    e.payload = message
  end

  actual_log_name = log_name
  info = request_info
  if info
    actual_log_name = info.log_name || actual_log_name
    unless info.trace_id.nil? || @project.nil?
      entry.trace = "projects/#{@project}/traces/#{info.trace_id}"
    end
    entry.trace_sampled = info.trace_sampled if entry.trace_sampled.nil?
  end

  writer.write_entries entry, log_name: actual_log_name,
                              resource: resource,
                              labels:   entry_labels(info)
end

Private Instance Methods

compute_label_value(request_env, value_or_proc) click to toggle source

@private Compute individual label value. Value can be a Proc (function of the request env) or a static value.

# File lib/google/cloud/logging/logger.rb, line 615
def compute_label_value request_env, value_or_proc
  if value_or_proc.respond_to? :call
    value_or_proc.call request_env
  else
    value_or_proc
  end
end
compute_labels(request_env) click to toggle source

@private Compute values for labels

# File lib/google/cloud/logging/logger.rb, line 606
def compute_labels request_env
  labels.to_h.transform_values do |value_or_proc|
    compute_label_value request_env, value_or_proc
  end
end