Class: Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor

Inherits:
ServerInterceptor show all
Defined in:
lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb

Overview

Handles Rails-style request logging for gruf services.

This is added by default to gruf servers; if you have Gruf.use_default_hooks = false, you can add it back manually by doing:

Gruf::Instrumentation::Registry.add(:request_logging, Gruf::Instrumentation::RequestLogging::Hook)

Constant Summary collapse

LOG_LEVEL_MAP =

Default mappings of codes to log levels...

{
  'GRPC::Ok' => :debug,
  'GRPC::InvalidArgument' => :debug,
  'GRPC::NotFound' => :debug,
  'GRPC::AlreadyExists' => :debug,
  'GRPC::OutOfRange' => :debug,
  'GRPC::Unauthenticated' => :warn,
  'GRPC::PermissionDenied' => :warn,
  'GRPC::Unknown' => :error,
  'GRPC::Internal' => :error,
  'GRPC::DataLoss' => :error,
  'GRPC::FailedPrecondition' => :error,
  'GRPC::Unavailable' => :error,
  'GRPC::DeadlineExceeded' => :error,
  'GRPC::Cancelled' => :error
}.freeze

Instance Attribute Summary

Attributes inherited from Base

#error, #options, #request

Instance Method Summary collapse

Methods included from Errors::Helpers

#fail!

Methods inherited from Base

#initialize

Constructor Details

This class inherits a constructor from Gruf::Interceptors::Base

Instance Method Details

#call(&block) ⇒ String

Log the request, sending it to the appropriate formatter

Returns:

  • (String)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb', line 61

def call(&block)
  return yield if options.fetch(:ignore_methods, [])&.include?(request.method_name)

  result = Gruf::Interceptors::Timer.time(&block)

  # Fetch log level options and merge with default...
  log_level_map = LOG_LEVEL_MAP.merge(options.fetch(:log_levels, {}))

  # A result is either successful, or, some level of feedback handled in the else block...
  if result.successful?
    type = log_level_map['GRPC::Ok'] || :debug
    status_name = 'GRPC::Ok'
  else
    type = log_level_map[result.message_class_name] || :error
    status_name = result.message_class_name
  end

  payload = {}
  if !request.client_streamer? && !request.bidi_streamer?
    payload[:params] = sanitize(request.message.to_h) if options.fetch(:log_parameters, false)
    payload[:message] = message(request, result)
    payload[:status] = status(result.message, result.successful?)
  else
    payload[:params] = {}
    payload[:message] = ''
    payload[:status] = GRPC::Core::StatusCodes::OK
  end

  payload[:service] = request.service_key
  payload[:method] = request.method_key
  payload[:action] = request.method_key
  payload[:grpc_status] = status_name
  payload[:duration] = result.elapsed_rounded
  payload[:thread_id] = Thread.current.object_id
  payload[:time] = Time.now.to_s
  payload[:host] = Socket.gethostname

  logger.send(type, formatter.format(payload, request: request, result: result))

  raise result.message unless result.successful?

  result.message
end