<s> from __future__ import absolute_import <EOL> from collections import defaultdict <EOL> from . base import BaseModule , RequestTrace <EOL> from . monkey_patching import monkeypatch_method , CallableProxy <EOL> import time <EOL> class StackEntry ( object ) : <EOL> def __init__ ( self , id_generator , entry_map , entry_type , label , extra = None ) : <EOL> self . id_generator = id_generator <EOL> self . entry_map = entry_map <EOL> self . entry_id = id_generator ( ) <EOL> self . entry_type = entry_type <EOL> self . label = label <EOL> self . extra = extra <EOL> self . start = time . time ( ) <EOL> self . children = [ ] <EOL> self . entry_map [ entry_type ] . append ( self ) <EOL> def mark_end ( self ) : <EOL> self . end = time . time ( ) <EOL> def add_child ( self , entry_type , label , extra = None ) : <EOL> child = StackEntry ( self . id_generator , self . entry_map , entry_type , label , extra ) <EOL> self . children . append ( child ) <EOL> return child <EOL> @ property <EOL> def duration ( self ) : <EOL> if self . end : <EOL> return self . end - self . start <EOL> return <NUM_LIT:0> <EOL> def to_dict ( self ) : <EOL> return { <EOL> '<STR_LIT:id>' : str ( self . entry_id ) , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:start>' : round ( self . start * <NUM_LIT:1000> , <NUM_LIT:1> ) , <EOL> '<STR_LIT:end>' : round ( self . end * <NUM_LIT:1000> , <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : round ( self . duration * <NUM_LIT:1000> , <NUM_LIT:1> ) , <EOL> } , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:type>' : self . entry_type , <EOL> '<STR_LIT:label>' : self . label , <EOL> } , <EOL> '<STR_LIT>' : [ child . to_dict ( ) for child in self . children ] , <EOL> } <EOL> class StackTracer ( BaseModule ) : <EOL> """<STR_LIT>""" <EOL> key = '<STR_LIT>' <EOL> def __init__ ( self ) : <EOL> super ( StackTracer , self ) . __init__ ( ) <EOL> self . root = None <EOL> self . stack = [ ] <EOL> self . stack_id = <NUM_LIT:0> <EOL> self . entry_map = defaultdict ( list ) <EOL> def push_stack ( self , entry_type , label , extra = None ) : <EOL> if len ( self . stack ) : <EOL> entry = self . stack [ - <NUM_LIT:1> ] . add_child ( entry_type , label , extra ) <EOL> else : <EOL> entry = self . root = StackEntry ( self . _get_next_id , self . entry_map , entry_type , label , extra ) <EOL> self . stack . append ( entry ) <EOL> return entry <EOL> def pop_stack ( self ) : <EOL> self . stack [ - <NUM_LIT:1> ] . mark_end ( ) <EOL> self . stack . pop ( ) <EOL> def get_metrics ( self ) : <EOL> return { } <EOL> def get_node_metrics ( self , node_type ) : <EOL> nodes = self . get_nodes ( node_type ) <EOL> return { <EOL> '<STR_LIT:time>' : int ( sum ( x . duration for x in nodes ) * <NUM_LIT:1000> ) , <EOL> '<STR_LIT:count>' : len ( nodes ) , <EOL> } <EOL> def get_nodes ( self , node_type ) : <EOL> return self . entry_map [ node_type ] <EOL> def speedtracer_log ( self ) : <EOL> entries_as_dict = self . root . to_dict ( ) <EOL> return { <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:id>' : str ( self . stack_id ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:date>' : time . time ( ) , <EOL> '<STR_LIT>' : entries_as_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : entries_as_dict , <EOL> } <EOL> } <EOL> def _get_next_id ( self ) : <EOL> self . stack_id += <NUM_LIT:1> <EOL> return self . stack_id <EOL> def trace_method ( cls , method_name = None ) : <EOL> def decorator ( info_func ) : <EOL> method_to_patch = method_name or info_func . __name__ <EOL> @ monkeypatch_method ( cls , method_to_patch ) <EOL> def tracing_method ( original , self , * args , ** kwargs ) : <EOL> request_trace = RequestTrace . instance ( ) <EOL> if request_trace : <EOL> entry_type , label , extra = info_func ( self , * args , ** kwargs ) <EOL> request_trace . stacktracer . push_stack ( entry_type , label , extra = extra ) <EOL> try : <EOL> return original ( * args , ** kwargs ) <EOL> finally : <EOL> if request_trace : <EOL> request_trace . stacktracer . pop_stack ( ) <EOL> return tracing_method <EOL> return decorator <EOL> def trace_function ( func , info ) : <EOL> try : <EOL> def tracing_function ( original , * args , ** kwargs ) : <EOL> request_trace = RequestTrace . instance ( ) <EOL> if request_trace : <EOL> if callable ( info ) : <EOL> entry_type , label , extra = info ( * args , ** kwargs ) <EOL> else : <EOL> entry_type , label , extra = info <EOL> request_trace . stacktracer . push_stack ( entry_type , label , extra ) <EOL> try : <EOL> return original ( * args , ** kwargs ) <EOL> finally : <EOL> if request_trace : <EOL> request_trace . stacktracer . pop_stack ( ) <EOL> return CallableProxy ( func , tracing_function ) <EOL> except Exception : <EOL> return func <EOL> def init ( ) : <EOL> return StackTracer </s>
