# Copyright (c) 2013 AppNeta, Inc. # All rights reserved. module Oboe module API ## # Provides the higher-level tracing interface for the API. module Tracing # Public: Trace a given block of code. Detect any exceptions thrown by # the block and report errors. # # layer - The layer the block of code belongs to. # opts - A hash containing key/value pairs that will be reported along # with the first event of this layer (optional). # protect_op - specify the operation being traced. Used to avoid # double tracing between operations that call each other # # Example # # def computation(n) # fib(n) # raise Exception.new # end # # def computation_with_oboe(n) # trace('fib', { :number => n }) do # computation(n) # end # end # # result = computation_with_oboe(1000) # # Returns the result of the block. def trace(layer, opts = {}, protect_op = nil) log_entry(layer, opts, protect_op) begin yield rescue Exception => e log_exception(layer, e) raise ensure log_exit(layer, {}, protect_op) end end # Public: Trace a given block of code which can start a trace depending # on configuration and probability. Detect any exceptions thrown by the # block and report errors. # # When start_trace returns control to the calling context, the oboe # context will be cleared. # # layer - The layer the block of code belongs to. # opts - A hash containing key/value pairs that will be reported along # with the first event of this layer (optional). # # Example # # def handle_request(request, response) # # ... code that modifies request and response ... # end # # def handle_request_with_oboe(request, response) # result, xtrace = start_trace('rails', request['X-Trace']) do # handle_request(request, response) # end # result # rescue Exception => e # xtrace = e.xtrace # ensure # response['X-trace'] = xtrace # end # # Returns a list of length two, the first element of which is the result # of the block, and the second element of which is the oboe context that # was set when the block completed execution. def start_trace(layer, xtrace = nil, opts = {}) log_start(layer, xtrace, opts) begin result = yield rescue Exception => e log_exception(layer, e) e.instance_variable_set(:@xtrace, log_end(layer)) raise end xtrace = log_end(layer) [result, xtrace] end # Public: Trace a given block of code which can start a trace depending # on configuration and probability. Detect any exceptions thrown by the # block and report errors. Insert the oboe metadata into the provided for # later user. # # The motivating use case for this is HTTP streaming in rails3. We need # access to the exit event's trace id so we can set the header before any # work is done, and before any headers are sent back to the client. # # layer - The layer the block of code belongs to. # target - The target object in which to place the oboe metadata. # opts - A hash containing key/value pairs that will be reported along # with the first event of this layer (optional). # # Example: # # def handle_request(request, response) # # ... code that does something with request and response ... # end # # def handle_request_with_oboe(request, response) # start_trace_with_target('rails', request['X-Trace'], response) do # handle_request(request, response) # end # end # # Returns the result of the block. def start_trace_with_target(layer, xtrace, target, opts = {}) log_start(layer, xtrace, opts) exit_evt = Oboe::Context.createEvent begin target['X-Trace'] = Oboe::Event.metadataString(exit_evt) if Oboe.tracing? yield rescue Exception => e log_exception(layer, e) raise ensure exit_evt.addEdge(Oboe::Context.get) log_event(layer, 'exit', exit_evt) Oboe::Context.clear end end end end end