class THTP::Server::Instrumentation::Logging
A THTP::Server
subscriber for RPC logging and exception recording
Public Class Methods
# File lib/thtp/server/instrumentation.rb, line 75 def initialize(logger, backtrace_lines: 10) @logger = logger @backtrace_lines = backtrace_lines end
Public Instance Methods
An unknown error occurred @param request [Rack::Request] The inbound HTTP request @param error [Exception] The to-be-serialized exception @param time [Integer] Milliseconds of execution wall time
# File lib/thtp/server/instrumentation.rb, line 138 def internal_error(request:, error:, time:) @logger.error :server do { http: http_request_to_hash(request), internal_error: error_to_hash(error), elapsed_ms: time, } end end
Handler raised an unexpected error @param request [Rack::Request] The inbound HTTP request @param rpc [Symbol] The name of the RPC @param args [Thrift::Struct?] The deserialized thrift args @param error [THTP::ServerError] The to-be-serialized exception @param time [Integer] Milliseconds of execution wall time
# File lib/thtp/server/instrumentation.rb, line 122 def rpc_error(request:, rpc:, args:, error:, time:) @logger.error :rpc do { rpc: rpc, http: http_request_to_hash(request), request: args_to_hash(args), error: error_to_hash(error), elapsed_ms: time, } end end
Handler raised an exception defined in the schema @param request [Rack::Request] The inbound HTTP request @param rpc [Symbol] The name of the RPC @param args [Thrift::Struct] The deserialized thrift args @param exception [Thrift::Struct] The to-be-serialized thrift exception @param time [Integer] Milliseconds of execution wall time
# File lib/thtp/server/instrumentation.rb, line 104 def rpc_exception(request:, rpc:, args:, exception:, time:) @logger.info :rpc do { rpc: rpc, http: http_request_to_hash(request), request: args_to_hash(args), exception: result_to_hash(exception), elapsed_ms: time, } end end
Everything went according to plan @param request [Rack::Request] The inbound HTTP request @param rpc [Symbol] The name of the RPC @param args [Thrift::Struct] The deserialized thrift args @param result [Thrift::Struct] The to-be-serialized thrift response @param time [Integer] Milliseconds of execution wall time
# File lib/thtp/server/instrumentation.rb, line 86 def rpc_success(request:, rpc:, args:, result:, time:) @logger.info :rpc do { rpc: rpc, http: http_request_to_hash(request), request: args_to_hash(args), result: result_to_hash(result), elapsed_ms: time, } end end
Private Instance Methods
# File lib/thtp/server/instrumentation.rb, line 160 def args_to_hash(rpc_args) jsonify(rpc_args) end
converts non-schema errors to an ELK-compatible format (JSON-serialisable hash)
# File lib/thtp/server/instrumentation.rb, line 186 def error_to_hash(error, backtrace: true) error_info = { message: error.message, repr: error.inspect } error_info[:backtrace] = error.backtrace.first(@backtrace_lines) if backtrace { canonical_name(error.class) => error_info } end
# File lib/thtp/server/instrumentation.rb, line 150 def http_request_to_hash(rack_request) { user_agent: rack_request.user_agent, content_type: rack_request.content_type, verb: rack_request.request_method, path: rack_request.path_info, ssl: rack_request.ssl?, } end
converts all possible Thrift result types to JSON, inferring types from collections, with the intent of producing ELK-compatible output (i.e., no multiple-type-mapped fields)
# File lib/thtp/server/instrumentation.rb, line 167 def result_to_hash(result) case result when nil nil # nulls are ok in ELK land when Array { list: { canonical_name(result.first.class) => jsonify(result) } } when Set { set: { canonical_name(result.first.class) => jsonify(result) } } when Hash ktype, vtype = result.first.map { |obj| canonical_name(obj.class) } { hash: { ktype => { vtype => jsonify(result) } } } when StandardError error_to_hash(result, backtrace: false) else # primitives { canonical_name(result.class) => jsonify(result) } end end