lib/google/cloud/logging/logger.rb in google-cloud-logging-0.23.0 vs lib/google/cloud/logging/logger.rb in google-cloud-logging-0.23.1
- old
+ new
@@ -19,11 +19,12 @@
module Cloud
module Logging
##
# # Logger
#
- # A (mostly) API-compatible logger for ruby's 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
@@ -35,31 +36,70 @@
# logger = logging.logger "my_app_log", resource, env: :production
# logger.info "Job started."
#
class Logger
##
+ # 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.
+ RequestInfo = ::Struct.new :trace_id, :log_name
+
+ ##
# The Google Cloud writer object that calls to {#write_entries} are made
# on. Either an AsyncWriter or Project object.
attr_reader :writer
##
# The Google Cloud log_name to write the log entry with.
attr_reader :log_name
+ alias_method :progname, :log_name
##
# The Google Cloud resource to write the log entry with.
attr_reader :resource
##
# The Google Cloud labels to write the log entry with.
attr_reader :labels
##
+ # The logging severity threshold (e.g. `Logger::INFO`)
+ attr_reader :level
+ alias_method :sev_threshold, :level
+
+ ##
+ # This logger does not use a formatter, but it provides a default
+ # Logger::Formatter for API compatibility with the standard Logger.
+ attr_accessor :formatter
+
+ ##
+ # This logger does not use a formatter, but it implements this
+ # attribute for API compatibility with the standard Logger.
+ attr_accessor :datetime_format
+
+ ##
+ # This logger treats progname as an alias for log_name.
+ def progname= name
+ @log_name = name
+ end
+
+ ##
# A OrderedHash of Thread IDs to Stackdriver request trace ID. The
# Stackdriver trace ID is a shared request identifier across all
# Stackdriver services.
- attr_reader :trace_ids
+ #
+ # @deprecated Use request_info
+ #
+ def trace_ids
+ @request_info.inject({}) { |r, (k, v)| r[k] = v.trace_id }
+ end
##
# Create a new Logger instance.
#
# @param [#write_entries] writer The object that will transmit log
@@ -99,11 +139,15 @@
@writer = writer
@log_name = log_name
@resource = resource
@labels = labels
@level = 0 # DEBUG is the default behavior
- @trace_ids = OrderedHash.new
+ @request_info = OrderedHash.new
+ @closed = false
+ # Unused, but present for API compatibility
+ @formatter = ::Logger::Formatter.new
+ @datetime_format = ""
end
##
# Log a `DEBUG` entry.
#
@@ -238,15 +282,26 @@
message = progname
# progname = nil # TODO: Figure out what to do with the progname
end
end
- write_entry severity, message
+ write_entry severity, message unless @closed
+ true
end
alias_method :log, :add
##
+ # Logs the given message at UNKNOWN severity.
+ #
+ # @param [String] msg The log entry payload as a string.
+ #
+ def << msg
+ unknown msg
+ self
+ end
+
+ ##
# Returns `true` if the current severity level allows for sending
# `DEBUG` messages.
def debug?
@level <= 0
end
@@ -305,32 +360,91 @@
@level = new_level
end
alias_method :sev_threshold=, :level=
##
+ # 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.
+ #
+ def close
+ @closed = true
+ self
+ end
+
+ ##
+ # 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.
+ #
+ def reopen _logdev = nil
+ @closed = false
+ self
+ end
+
+ ##
# Track a given trace_id by associating it with the current
# Thread
#
- # @param [String] trace_id The HTTP_X_CLOUD_TRACE_CONTEXT HTTP request
- # header that's shared and tracked by all Stackdriver services
+ # @deprecated Use add_request_info
+ #
def add_trace_id trace_id
- trace_ids[current_thread_id] = trace_id
+ add_request_id trace_id: trace_id
+ end
+ ##
+ # 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.
+ #
+ def add_request_info info: nil,
+ trace_id: nil,
+ log_name: nil
+ info ||= RequestInfo.new trace_id, log_name
+ @request_info[current_thread_id] = info
+
# Start removing old entries if hash gets too large.
# This should never happen, because middleware should automatically
# remove entries when a request is finished
- trace_ids.shift if trace_ids.size > 10_000
+ @request_info.shift while @request_info.size > 10_000
+
+ info
end
##
- # Untrack the trace_id that's associated with current Thread
+ # Get the request data for the current Thread
#
- # @return [String] The trace_id that's being deleted
- def delete_trace_id
- trace_ids.delete current_thread_id
+ # @return [RequestInfo, nil] The request data for the current thread,
+ # or `nil` if there is no data set.
+ #
+ def request_info
+ @request_info[current_thread_id]
end
+ ##
+ # Untrack the RequestInfo that's associated with current Thread
+ #
+ # @return [RequestInfo] The info that's being deleted
+ #
+ def delete_request_info
+ @request_info.delete current_thread_id
+ end
+
+ ##
+ # @deprecated Use delete_request_info
+ alias_method :delete_trace_id, :delete_request_info
+
protected
##
# @private Write a log entry to the Stackdriver Logging service.
def write_entry severity, message
@@ -338,15 +452,21 @@
e.timestamp = Time.now
e.severity = gcloud_severity(severity)
e.payload = message
end
- # merge input labels and trace_id
- trace_id = trace_ids[current_thread_id]
- merged_labels = trace_id.nil? ? {} : { traceId: trace_id }
+ # merge input labels and request info
+ merged_labels = {}
+ actual_log_name = log_name
+ info = request_info
+ if info
+ actual_log_name = info.log_name || actual_log_name
+ merged_labels["traceId"] = info.trace_id unless info.trace_id.nil?
+ end
merged_labels = labels.merge(merged_labels) unless labels.nil?
- writer.write_entries entry, log_name: log_name, resource: resource,
+ writer.write_entries entry, log_name: actual_log_name,
+ resource: resource,
labels: merged_labels
end
##
# @private Get the logger level number from severity value object.