def _collect_runtime_snapshot(self, plugin_data): """ Gathers Python specific Snapshot information for this process """ snapshot_payload = {} try: snapshot_payload['name'] = determine_service_name() snapshot_payload['version'] = sys.version snapshot_payload['f'] = platform.python_implementation() # flavor snapshot_payload['a'] = platform.architecture()[0] # architecture snapshot_payload['versions'] = self.gather_python_packages() snapshot_payload['iv'] = VERSION if 'AUTOWRAPT_BOOTSTRAP' in os.environ: snapshot_payload['m'] = 'Autowrapt' elif 'INSTANA_MAGIC' in os.environ: snapshot_payload['m'] = 'AutoTrace' else: snapshot_payload['m'] = 'Manual' try: from django.conf import settings # pylint: disable=import-outside-toplevel if hasattr(settings, 'MIDDLEWARE') and settings.MIDDLEWARE is not None: snapshot_payload['djmw'] = settings.MIDDLEWARE elif hasattr(settings, 'MIDDLEWARE_CLASSES' ) and settings.MIDDLEWARE_CLASSES is not None: snapshot_payload['djmw'] = settings.MIDDLEWARE_CLASSES except Exception: pass except Exception: logger.debug("collect_snapshot: ", exc_info=True) plugin_data['data']['snapshot'] = snapshot_payload
def _collect_gc_metrics(self, plugin_data, with_snapshot): try: gc_count = gc.get_count() gc_threshold = gc.get_threshold() self.apply_delta(gc_count[0], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "collect0", with_snapshot) self.apply_delta(gc_count[1], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "collect1", with_snapshot) self.apply_delta(gc_count[2], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "collect2", with_snapshot) self.apply_delta(gc_threshold[0], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "threshold0", with_snapshot) self.apply_delta(gc_threshold[1], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "threshold1", with_snapshot) self.apply_delta(gc_threshold[2], self.previous['data']['metrics']['gc'], plugin_data['data']['metrics']['gc'], "threshold2", with_snapshot) except Exception: logger.debug("_collect_gc_metrics", exc_info=True)
def collect(instance, args, kwargs): """ Build and return a fully qualified URL for this request """ try: kvs = {} kvs['host'] = instance.host kvs['port'] = instance.port if args is not None and len(args) is 2: kvs['method'] = args[0] kvs['path'] = args[1] else: kvs['method'] = kwargs['method'] kvs['path'] = kwargs['url'] if type(instance) is urllib3.connectionpool.HTTPSConnectionPool: kvs['url'] = 'https://%s:%d%s' % (kvs['host'], kvs['port'], kvs['path']) else: kvs['url'] = 'http://%s:%d%s' % (kvs['host'], kvs['port'], kvs['path']) except Exception as e: logger.debug(e) return kvs else: return kvs
def jsonable(self, value): try: if callable(value): try: result = value() except Exception: result = 'Unknown' elif isinstance(value, ModuleType): result = value else: result = value return str(result) except Exception: logger.debug("jsonable: ", exc_info=True)
def collect_metrics(self, with_snapshot=False): plugin_data = dict() try: plugin_data["name"] = "com.instana.plugin.python" plugin_data["entityId"] = str(os.getpid()) plugin_data["data"] = DictionaryOfStan() plugin_data["data"]["pid"] = str(os.getpid()) self._collect_runtime_metrics(plugin_data, with_snapshot) if with_snapshot is True: self._collect_runtime_snapshot(plugin_data) except Exception: logger.debug("_collect_metrics: ", exc_info=True) return [plugin_data]
def collect_metrics(self, with_snapshot=False): plugin_data = dict() try: plugin_data["name"] = "com.instana.plugin.process" plugin_data["entityId"] = str(os.getpid()) plugin_data["data"] = DictionaryOfStan() plugin_data["data"]["pid"] = int(os.getpid()) plugin_data["data"]["containerType"] = "docker" if self.collector.root_metadata is not None: plugin_data["data"]["container"] = self.collector.root_metadata.get("DockerId") if with_snapshot: self._collect_process_snapshot(plugin_data) except Exception: logger.debug("ProcessHelper.collect_metrics: ", exc_info=True) return [plugin_data]
def process_request(self, request): try: env = request.environ if 'HTTP_X_INSTANA_T' in env and 'HTTP_X_INSTANA_S' in env: ctx = internal_tracer.extract(ot.Format.HTTP_HEADERS, env) span = internal_tracer.start_span("django", child_of=ctx) else: span = internal_tracer.start_span("django") span.set_tag(ext.HTTP_URL, env['PATH_INFO']) span.set_tag("http.params", env['QUERY_STRING']) span.set_tag(ext.HTTP_METHOD, request.method) span.set_tag("http.host", env['HTTP_HOST']) self.span = span except Exception as e: logger.debug("Instana middleware @ process_response: ", e)
def eum_test_snippet(trace_id=None, eum_api_key=None, meta=None): """ Return an EUM snippet for use in views, templates and layouts that reports client side metrics to Instana that will automagically be linked to the current trace. @param trace_id [optional] the trace ID to insert into the EUM string @param eum_api_key [optional] the EUM API key from your Instana dashboard @param meta [optional] optional additional KVs you want reported with the EUM metrics @return string """ try: eum_file = open(os.path.dirname(__file__) + '/eum_test.js') eum_src = Template(eum_file.read()) # Prepare the standard required IDs ids = {} ids['meta_kvs'] = '' parent_span = tracer.active_span if trace_id or parent_span: ids['trace_id'] = trace_id or parent_span.trace_id else: # No trace_id passed in and tracer doesn't show an active span so # return nothing, nada & zip. return '' if eum_api_key: ids['eum_api_key'] = eum_api_key else: ids['eum_api_key'] = global_eum_api_key # Process passed in EUM 'meta' key/values if meta is not None: for key, value in meta.items(): ids['meta_kvs'] += ("'ineum('meta', '%s', '%s');'" % (key, value)) return eum_src.substitute(ids) except Exception: logger.debug("eum_snippet: ", exc_info=True) return ''
def process_response(self, request, response): try: if self.span: if 500 <= response.status_code <= 511: self.span.set_tag("error", True) ec = self.span.tags.get('ec', 0) if ec is 0: self.span.set_tag("ec", ec + 1) self.span.set_tag(ext.HTTP_STATUS_CODE, response.status_code) internal_tracer.inject(self.span.context, ot.Format.HTTP_HEADERS, response) self.span.finish() self.span = None except Exception as e: logger.debug("Instana middleware @ process_response: ", e) finally: return response
def gather_python_packages(self): """ Collect up the list of modules in use """ versions = dict() try: sys_packages = sys.modules.copy() for pkg_name in sys_packages: # Don't report submodules (e.g. django.x, django.y, django.z) # Skip modules that begin with underscore if ('.' in pkg_name) or pkg_name[0] == '_': continue # Skip builtins if pkg_name in ["sys", "curses"]: continue if sys_packages[pkg_name]: try: pkg_info = sys_packages[pkg_name].__dict__ if "__version__" in pkg_info: if isinstance(pkg_info["__version__"], str): versions[pkg_name] = pkg_info["__version__"] else: versions[pkg_name] = self.jsonable( pkg_info["__version__"]) elif "version" in pkg_info: versions[pkg_name] = self.jsonable( pkg_info["version"]) else: versions[pkg_name] = get_distribution( pkg_name).version except DistributionNotFound: pass except Exception: logger.debug( "gather_python_packages: could not process module: %s", pkg_name) # Manually set our package version versions['instana'] = VERSION except Exception: logger.debug("gather_python_packages", exc_info=True) return versions
def _collect_process_snapshot(self, plugin_data): try: env = dict() for key in os.environ: if contains_secret(key, self.collector.agent.options.secrets_matcher, self.collector.agent.options.secrets_list): env[key] = "<ignored>" else: env[key] = os.environ[key] plugin_data["data"]["env"] = env if os.path.isfile("/proc/self/exe"): plugin_data["data"]["exec"] = os.readlink("/proc/self/exe") else: logger.debug("Can't access /proc/self/exe...") cmdline = get_proc_cmdline() if len(cmdline) > 1: # drop the exe cmdline.pop(0) plugin_data["data"]["args"] = cmdline try: euid = os.geteuid() egid = os.getegid() plugin_data["data"]["user"] = pwd.getpwuid(euid) plugin_data["data"]["group"] = grp.getgrgid(egid).gr_name except Exception: logger.debug("euid/egid detection: ", exc_info=True) plugin_data["data"]["start"] = 1 # FIXME: process start time reporting if self.collector.task_metadata is not None: plugin_data["data"]["com.instana.plugin.host.name"] = self.collector.task_metadata.get("TaskArn") except Exception: logger.debug("ProcessHelper._collect_process_snapshot: ", exc_info=True)
def _collect_thread_metrics(self, plugin_data, with_snapshot): try: threads = threading.enumerate() daemon_threads = [thread.daemon is True for thread in threads].count(True) self.apply_delta(daemon_threads, self.previous['data']['metrics'], plugin_data['data']['metrics'], "daemon_threads", with_snapshot) alive_threads = [thread.daemon is False for thread in threads].count(True) self.apply_delta(alive_threads, self.previous['data']['metrics'], plugin_data['data']['metrics'], "alive_threads", with_snapshot) dummy_threads = [ isinstance(thread, threading._DummyThread) for thread in threads ].count(True) # pylint: disable=protected-access self.apply_delta(dummy_threads, self.previous['data']['metrics'], plugin_data['data']['metrics'], "dummy_threads", with_snapshot) except Exception: logger.debug("_collect_thread_metrics", exc_info=True)
def _collect_runtime_metrics(self, plugin_data, with_snapshot): """ Collect up and return the runtime metrics """ try: rusage = resource.getrusage(resource.RUSAGE_SELF) if gc.isenabled(): self._collect_gc_metrics(plugin_data, with_snapshot) self._collect_thread_metrics(plugin_data, with_snapshot) value_diff = rusage.ru_utime - self.previous_rusage.ru_utime self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_utime", with_snapshot) value_diff = rusage.ru_stime - self.previous_rusage.ru_stime self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_stime", with_snapshot) self.apply_delta(rusage.ru_maxrss, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_maxrss", with_snapshot) self.apply_delta(rusage.ru_ixrss, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_ixrss", with_snapshot) self.apply_delta(rusage.ru_idrss, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_idrss", with_snapshot) self.apply_delta(rusage.ru_isrss, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_isrss", with_snapshot) value_diff = rusage.ru_minflt - self.previous_rusage.ru_minflt self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_minflt", with_snapshot) value_diff = rusage.ru_majflt - self.previous_rusage.ru_majflt self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_majflt", with_snapshot) value_diff = rusage.ru_nswap - self.previous_rusage.ru_nswap self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_nswap", with_snapshot) value_diff = rusage.ru_inblock - self.previous_rusage.ru_inblock self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_inblock", with_snapshot) value_diff = rusage.ru_oublock - self.previous_rusage.ru_oublock self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_oublock", with_snapshot) value_diff = rusage.ru_msgsnd - self.previous_rusage.ru_msgsnd self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_msgsnd", with_snapshot) value_diff = rusage.ru_msgrcv - self.previous_rusage.ru_msgrcv self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_msgrcv", with_snapshot) value_diff = rusage.ru_nsignals - self.previous_rusage.ru_nsignals self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_nsignals", with_snapshot) value_diff = rusage.ru_nvcsw - self.previous_rusage.ru_nvcsw self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_nvcsw", with_snapshot) value_diff = rusage.ru_nivcsw - self.previous_rusage.ru_nivcsw self.apply_delta(value_diff, self.previous['data']['metrics'], plugin_data['data']['metrics'], "ru_nivcsw", with_snapshot) except Exception: logger.debug("_collect_runtime_metrics", exc_info=True) finally: self.previous_rusage = rusage