1require 'grpc' 2require 'raven/base' 3 4require_relative 'sentry.rb' 5module GitalyServer 6 class SentryInterceptor < GRPC::ServerInterceptor 7 # Intercept a unary request response call 8 def request_response(request: nil, call: nil, method: nil) 9 start = Time.now 10 yield 11 rescue => e 12 time_ms = Time.now - start 13 handle_exception(e, call, method, time_ms) 14 end 15 16 # Intercept a server streaming call 17 def server_streamer(request: nil, call: nil, method: nil) 18 start = Time.now 19 yield 20 rescue => e 21 time_ms = Time.now - start 22 handle_exception(e, call, method, time_ms) 23 end 24 25 # Intercept a client streaming call 26 def client_streamer(call: nil, method: nil) 27 start = Time.now 28 yield 29 rescue => e 30 time_ms = Time.now - start 31 handle_exception(e, call, method, time_ms) 32 end 33 34 # Intercept a BiDi streaming call 35 def bidi_streamer(requests: nil, call: nil, method: nil) 36 start = Time.now 37 yield 38 rescue => e 39 time_ms = Time.now - start 40 handle_exception(e, call, method, time_ms) 41 end 42 43 private 44 45 def handle_exception(exc, call, method, time_ms) 46 raise exc unless GitalyServer::Sentry.enabled? 47 48 grpc_method = "#{method.owner.name}##{method.name}" 49 tags = { 50 'system' => 'gitaly-ruby', 51 'gitaly-ruby.method' => grpc_method, 52 'gitaly-ruby.time_ms' => format("%.0f", (time_ms * 1000)), 53 Labkit::Correlation::CorrelationId::LOG_KEY => Labkit::Correlation::CorrelationId.current_id 54 } 55 tags.merge!(call.metadata) 56 57 Raven.tags_context(tags) 58 Raven.capture_exception(exc, fingerprint: ['gitaly-ruby', grpc_method, exc.message]) 59 60 raise exc 61 end 62 end 63end 64