lib/google/cloud/logging/middleware.rb in google-cloud-logging-0.23.0 vs lib/google/cloud/logging/middleware.rb in google-cloud-logging-0.23.1

- old
+ new

@@ -11,15 +11,22 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +require "stackdriver/core" + module Google module Cloud module Logging class Middleware ## + # A default value for the log_name_map argument. Directs health check + # logs to a separate log name so they don't spam the main log. + DEFAULT_LOG_NAME_MAP = { "/_ah/health" => "ruby_health_check_log" } + + ## # The Google::Cloud::Logging::Logger instance attr_reader :logger ## # Create a new AppEngine logging Middleware. @@ -27,17 +34,22 @@ # @param [Rack Application] app Rack application # @param [Google::Cloud::Logging::Logger] logger A logger to be used by # this middleware. The middleware will be interacting with the logger # to track Stackdriver request trace ID. It also properly sets # env["rack.logger"] to this assigned logger for accessing. + # @param [Hash] log_name_map A map from URI path to log name override. + # The path may be a string or regex. If a request path matches an + # entry in this map, the log name is set accordingly, otherwise the + # logger's default log_name is used. # # @return [Google::Cloud::Logging::Middleware] A new # Google::Cloud::Logging::Middleware instance # - def initialize app, logger: nil + def initialize app, logger: nil, log_name_map: DEFAULT_LOG_NAME_MAP @app = app @logger = logger + @log_name_map = log_name_map end ## # Rack middleware entry point. In most Rack based frameworks, a request # is served by one thread. So entry point, we associate the GCP request @@ -49,32 +61,51 @@ # # @return [Rack::Response] The response from downstream Rack app # def call env env["rack.logger"] = logger - trace_id = extract_trace_id(env) - logger.add_trace_id trace_id - + trace_id = get_trace_id env + log_name = get_log_name env + logger.add_request_info trace_id: trace_id, log_name: log_name begin @app.call env ensure - logger.delete_trace_id + logger.delete_request_info end end ## - # Extract the trace_id from HTTP request header - # HTTP_X_CLOUD_TRACE_CONTEXT. + # Determine the trace ID for this request. # - # @return [String] The trace_id or nil if trace_id is empty. - def extract_trace_id env - trace_context = env["HTTP_X_CLOUD_TRACE_CONTEXT"].to_s - return nil if trace_context.empty? - trace_context.sub(%r{/.*}, "") + # @private + # @param [Hash] env The Rack environment. + # @return [String] The trace ID. + # + def get_trace_id env + trace_context = Stackdriver::Core::TraceContext.parse_rack_env env + trace_context.trace_id end ## + # Determine the log name override for this request, if any. + # + # @private + # @param [Hash] env The Rack environment. + # @return [String, nil] The log name override, or `nil` if there is + # no override. + # + def get_log_name env + return nil unless @log_name_map + path = "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}" + path = "/#{path}" unless path.start_with? "/" + @log_name_map.each do |k, v| + return v if k === path + end + nil + end + + ## # Construct a monitored resource based on the given type and label if # both are provided. Otherwise, construct a default monitored resource # based on the current environment. # # @example If both type and labels are provided, it returns resource: @@ -134,28 +165,32 @@ ## # @private Extract information from current environment and construct # the correct monitoring resource types and labels. # # @example If running from GAE, returns default resource: - # rc = Google::Cloud::Logging::Middleware.build_monitored_resource + # rc = Google::Cloud::Logging::Middleware.send \ + # :default_monitored_resource # rc.type #=> "gae_app" # rc.labels # { module_id: [GAE module name], # # version_id: [GAE module version] } # # @example If running from GKE, returns default resource: - # rc = Google::Cloud::Logging::Middleware.build_monitored_resource + # rc = Google::Cloud::Logging::Middleware.send \ + # :default_monitored_resource # rc.type #=> "container" # rc.labels # { cluster_name: [GKE cluster name], # # namespace_id: [GKE namespace_id] } # # @example If running from GCE, return default resource: - # rc = Google::Cloud::Logging::Middleware.build_monitored_resource + # rc = Google::Cloud::Logging::Middleware.send \ + # :default_monitored_resource # rc.type #=> "gce_instance" # rc.labels # { instance_id: [GCE VM instance id], # # zone: [GCE vm group zone] } # # @example Otherwise default to generic "global" type: - # rc = Google::Cloud::Logging::Middleware.build_monitored_resource + # rc = Google::Cloud::Logging::Middleware.send \ + # :default_monitored_resource # rc.type #=> "global" # rc.labels #=> {} # # Reference https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource # for a full list of monitoring resources