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.