def collect_stack_traces(include_nr_threads=False, include_xrays=False): """Generator that yields the (thread category, stack trace) of all the python threads. """ for (txn, thread_id, thread_category, frame) in \ transaction_cache().active_threads(): # Skip NR Threads unless explicitly requested. if (thread_category == 'AGENT') and (not include_nr_threads): continue stack_trace = format_stack_trace(frame, thread_category) # Skip over empty stack traces. This is merely for optimization. # # It saves us from adding an empty deque to the txn obj, which will be # discarded later on during call tree merge. if not stack_trace: continue if include_xrays and txn: txn.add_profile_sample(stack_trace) yield thread_category, stack_trace
def current_transaction(): current = transaction_cache().current_transaction() if current and (current.ignore_transaction or current.stopped): return None return current
def __init__(self, application, enabled=None): self._application = application self.thread_id = transaction_cache().current_thread_id() self._transaction_id = id(self) self._transaction_lock = threading.Lock() self._dead = False self._state = STATE_PENDING self._settings = None self._priority = 0 self._group = None self._name = None self._frameworks = set() self._frozen_path = None self._node_stack = [] self._request_uri = None self.queue_start = 0.0 self.start_time = 0.0 self.end_time = 0.0 self.stopped = False self._errors = [] self._slow_sql = [] self._stack_trace_count = 0 self._explain_plan_count = 0 self._string_cache = {} self._custom_params = {} self._request_params = {} self._utilization_tracker = None self._thread_utilization_start = None self._thread_utilization_end = None self._thread_utilization_value = None self._cpu_user_time_start = None self._cpu_user_time_end = None self._cpu_user_time_value = 0.0 self._read_length = None self._read_start = None self._read_end = None self._sent_start = None self._sent_end = None self._bytes_read = 0 self._bytes_sent = 0 self._calls_read = 0 self._calls_readline = 0 self._calls_readlines = 0 self._calls_write = 0 self._calls_yield = 0 self._request_environment = {} self._response_properties = {} self._transaction_metrics = {} self.background_task = False self.enabled = False self.autorum_disabled = False self.ignore_transaction = False self.suppress_apdex = False self.suppress_transaction_trace = False self.capture_params = False self.ignored_params = [] self.response_code = 0 self.apdex = 0 self.rum_token = None self.rum_trace = False # 16-digit random hex. Padded with zeros in the front. self.guid = '%016x' % random.getrandbits(64) self.client_cross_process_id = None self.client_account_id = None self.client_application_id = None self.referring_transaction_guid = None self.record_tt = False self._custom_metrics = CustomMetrics() self._profile_samples = deque() self._profile_frames = {} self._profile_skip = 1 self._profile_count = 0 global_settings = application.global_settings if global_settings.enabled: if enabled or (enabled is None and application.enabled): self._settings = application.settings if not self._settings: application.activate() # We see again if the settings is now valid # in case startup timeout had been specified # and registration had been started and # completed within the timeout. self._settings = application.settings if self._settings: self.enabled = True
def drop_transaction(self): transaction_cache().drop_transaction(self)
def save_transaction(self): transaction_cache().save_transaction(self)
def current_thread_id(): return transaction_cache().current_thread_id()
def __init__(self, application, enabled=None): self._application = application self.thread_id = transaction_cache().current_thread_id() self._transaction_id = id(self) self._transaction_lock = threading.Lock() self._dead = False self._state = self.STATE_PENDING self._settings = None self._priority = 0 self._group = None self._name = None self._frameworks = set() self._frozen_path = None self._node_stack = [] self._request_uri = None self.queue_start = 0.0 self.start_time = 0.0 self.end_time = 0.0 self.stopped = False self._trace_node_count = 0 self._errors = [] self._slow_sql = [] self._stack_trace_count = 0 self._explain_plan_count = 0 self._string_cache = {} self._custom_params = {} self._request_params = {} self._utilization_tracker = None self._thread_utilization_start = None self._thread_utilization_end = None self._thread_utilization_value = None self._cpu_user_time_start = None self._cpu_user_time_end = None self._cpu_user_time_value = 0.0 self._read_length = None self._read_start = None self._read_end = None self._sent_start = None self._sent_end = None self._bytes_read = 0 self._bytes_sent = 0 self._calls_read = 0 self._calls_readline = 0 self._calls_readlines = 0 self._calls_write = 0 self._calls_yield = 0 self._request_environment = {} self._response_properties = {} self._transaction_metrics = {} self.background_task = False self.enabled = False self.autorum_disabled = False self.ignore_transaction = False self.suppress_apdex = False self.suppress_transaction_trace = False self.capture_params = False self.ignored_params = [] self.response_code = 0 self.apdex = 0 self.rum_token = None self.rum_trace = False # 16-digit random hex. Padded with zeros in the front. self.guid = '%016x' % random.getrandbits(64) self.client_cross_process_id = None self.client_account_id = None self.client_application_id = None self.referring_transaction_guid = None self.record_tt = False self._trip_id = None self._referring_path_hash = None self._alternate_path_hashes = {} self.is_part_of_cat = False self.synthetics_resource_id = None self.synthetics_job_id = None self.synthetics_monitor_id = None self.synthetics_header = None self._custom_metrics = CustomMetrics() self._profile_samples = deque() self._profile_frames = {} self._profile_skip = 1 self._profile_count = 0 global_settings = application.global_settings if global_settings.enabled: if enabled or (enabled is None and application.enabled): self._settings = application.settings if not self._settings: application.activate() # We see again if the settings is now valid # in case startup timeout had been specified # and registration had been started and # completed within the timeout. self._settings = application.settings if self._settings: self.enabled = True
def current_transaction(active_only=True): current = transaction_cache().current_transaction() if active_only: if current and (current.ignore_transaction or current.stopped): return None return current
def _argspec_py3(func): a = inspect.getfullargspec(func) return (a.args, a.varargs, a.varkw, a.defaults) if hasattr(inspect, 'getfullargspec'): _argspec = _argspec_py3 else: _argspec = _argspec_py2 from newrelic.core.agent import agent_instance from newrelic.core.config import global_settings, flatten_settings from newrelic.api.transaction import Transaction from newrelic.api.object_wrapper import ObjectWrapper from newrelic.core.transaction_cache import transaction_cache _transaction_cache = transaction_cache() def shell_command(wrapped): args, varargs, keywords, defaults = _argspec(wrapped) parser = optparse.OptionParser() for name in args[1:]: parser.add_option('--%s' % name, dest=name) @functools.wraps(wrapped) def wrapper(self, line): result = shlex.split(line) (options, args) = parser.parse_args(result) kwargs = {}
def collect_stack_traces(): """Collects representaions for the stack of each active thread within the process. A item is yielded for each thread which consists of a tuple with the category of thread and then the stack trace. """ for txn, thread_id, thread_category, frame in \ transaction_cache().active_threads(): stack_trace = [] # The initial stack frame is the lowest frame or leaf node and # we will track back up the stack. For that lowest stack frame # we optionally want to introduce a fake node which captures the # actual execution line so will be displayed as a separate item # in the UI. This makes it easier to identify where in the # actual code it was executing. leaf_node = ADD_REAL_LINE_LEAF_NODE while frame: # The value frame.f_code.co_firstlineno is the first line of # code in the file for the specified function. The value # frame.f_lineno is the actual line which is being executed # at the time the stack frame was being viewed. filename = frame.f_code.co_filename func_name = frame.f_code.co_name first_line = frame.f_code.co_firstlineno real_line = frame.f_lineno # As we experiment with representation of the stack trace in # UI, allow line number for each stack frame to either be # the actual execution line or start of function. It would # appear at this point it should always be execution line. line_no = real_line if USE_REAL_LINE_NUMBERS else first_line # Set ourselves up to process next frame back up the stack. frame = frame.f_back # So as to make it more obvious to the user as to what their # code is doing, we drop out stack frames related to the # agent instrumentation. Don't do this for the agent threads # though as we still need to seem them in that case so can # debug what the agent itself is doing. if IGNORE_AGENT_FRAMES and thread_category != 'AGENT': if filename.startswith(AGENT_PACKAGE_DIRECTORY): continue if leaf_node: # Add the fake leaf node with line number of where the # code was executing at the point of the sample. This # could be actual Python code within the function, or # more likely showing the point where a call is being # made into a C function wrapped as Python object. The # latter can occur because we will not see stack frames # when calling into C functions. name = '@%s#%s' % (func_name, real_line) method_data = _MethodData(filename, name, line_no) stack_trace.append(method_data) leaf_node = False # Add the actual node for the function being called at this # level in the stack frames. if ADD_LINE_TO_FUNC_NAME: name = '%s#%s' % (func_name, first_line) else: name = func_name method_data = _MethodData(filename, name, line_no) stack_trace.append(method_data) # Collect the stack trace samples in a list attached to the transaction # obj. This will be merged together to create a call tree if the # transaction is an xray txn. if txn: txn.add_profile_sample(stack_trace) yield thread_category, stack_trace
def collect_stack_traces(): """Collects representaions for the stack of each active thread within the process. A item is yielded for each thread which consists of a tuple with the category of thread and then the stack trace. """ for thread_id, thread_category, frame in \ transaction_cache().active_threads(): stack_trace = [] # The initial stack frame is the lowest frame or leaf node and # we will track back up the stack. For that lowest stack frame # we optionally want to introduce a fake node which captures the # actual execution line so will be displayed as a separate item # in the UI. This makes it easier to identify where in the # actual code it was executing. leaf_node = ADD_REAL_LINE_LEAF_NODE while frame: # The value frame.f_code.co_firstlineno is the first line of # code in the file for the specified function. The value # frame.f_lineno is the actual line which is being executed # at the time the stack frame was being viewed. filename = frame.f_code.co_filename func_name = frame.f_code.co_name first_line = frame.f_code.co_firstlineno real_line = frame.f_lineno # As we experiment with representation of the stack trace in # UI, allow line number for each stack frame to either be # the actual execution line or start of function. It would # appear at this point it should always be execution line. line_no = real_line if USE_REAL_LINE_NUMBERS else first_line # Set ourselves up to process next frame back up the stack. frame = frame.f_back # So as to make it more obvious to the user as to what their # code is doing, we drop out stack frames related to the # agent instrumentation. Don't do this for the agent threads # though as we still need to seem them in that case so can # debug what the agent itself is doing. if IGNORE_AGENT_FRAMES and thread_category != 'AGENT': if filename.startswith(AGENT_PACKAGE_DIRECTORY): continue if leaf_node: # Add the fake leaf node with line number of where the # code was executing at the point of the sample. This # could be actual Python code within the function, or # more likely showing the point where a call is being # made into a C function wrapped as Python object. The # latter can occur because we will not see stack frames # when calling into C functions. name = '@%s#%s' % (func_name, real_line) method_data = _MethodData(filename, name, line_no) stack_trace.append(method_data) leaf_node = False # Add the actual node for the function being called at this # level in the stack frames. if ADD_LINE_TO_FUNC_NAME: name = '%s#%s' % (func_name, first_line) else: name = func_name method_data = _MethodData(filename, name, line_no) stack_trace.append(method_data) yield thread_category, stack_trace