async def middlewareOpencensus( request: Request, call_next ): # The middleware function recieves: The request, A function call_next that will recieve the request as a parameter tracer = Tracer(exporter=AzureExporter( connection_string=f'InstrumentationKey={APPINSIGHTS_INSTRUMENTATIONKEY}' ), sampler=ProbabilitySampler(1.0)) # https://opencensus.io/tracing/span/kind/#2 # SpanKind details the relationships between spans in addition to the parent/child relationship. # Spand kind: 0 = UNSEPCIFIED, 1 = SERVER, 2 = CLIENT # Detail explaination of Span : https://opencensus.io/tracing/span/ with tracer.span("main") as span: span.span_kind = SpanKind.SERVER response = await call_next( request ) # call next will pass the request to the corresponding path operation, then returns the response genrated by the corresponding path operation tracer.add_attribute_to_current_span( # current span is a SERVER attribute_key=HTTP_STATUS_CODE, # E.g. 202, 201, 404, 405, 505 attribute_value=response.status_code) tracer.add_attribute_to_current_span(attribute_key=HTTP_URL, attribute_value=str(request.url)) return response
def main(): sampler = always_on.AlwaysOnSampler() exporter = print_exporter.PrintExporter() #tracer = Tracer(sampler=sampler, exporter=exporter) je = JaegerExporter(service_name="pitoncito", host_name='jaeger-server', port=9411, endpoint='/api/traces') tracer = Tracer(exporter=je, sampler=always_on.AlwaysOnSampler()) with tracer.span(name='root'): tracer.add_attribute_to_current_span(attribute_key='miclave', attribute_value='mivalor') function_to_trace() with tracer.span(name='child'): function_to_trace() # Get the current tracer tracer = execution_context.get_opencensus_tracer() # Explicitly create spans tracer.start_span() # Get current span execution_context.get_current_span() # Explicitly end span tracer.end_span()
def main(): sampler = always_on.AlwaysOnSampler() exporter = print_exporter.PrintExporter() tracer = Tracer(sampler=sampler, exporter=exporter) with tracer.span(name='root'): tracer.add_attribute_to_current_span(attribute_key='example key', attribute_value='example value') function_to_trace() with tracer.span(name='child'): function_to_trace() # Get the current tracer tracer = execution_context.get_opencensus_tracer() # Explicitly create spans tracer.start_span() # Get current span execution_context.get_current_span() # Explicitly end span tracer.end_span()
exporter=EXPORTER, sampler=SAMPLER, ) # Add tracing for PostgreSQL config_integration.trace_integrations(['postgresql']) # Configure logging from settings.py logging.config.dictConfig(getattr(django.conf.settings, 'LOGGING', {})) # Add logging integration config_integration.trace_integrations(['logging']) logger = logging.getLogger(__name__) if getattr(django.conf.settings, 'DEBUG'): try: from logging_tree import printout printout() except: pass # optional logging_tree not in venv. # Run with tracing # TODO: Currently the manage.py command is showing as a dependency. Can I turn it into the node itself? # TODO: tracemanage.py node is showing with 0 calls and 0ms with TRACER.span(name='manage.py/{0}'.format(sys.argv[1])) as span: span.span_kind = span_module.SpanKind.CLIENT TRACER.add_attribute_to_current_span("http.method", "CLI") TRACER.add_attribute_to_current_span( "http.route", 'manage.py/{0}'.format(sys.argv[1])) execute_from_command_line(sys.argv)
class AppInsightsLogger(LoggerInterface, ObservabilityAbstract): def __init__(self, run): print('Initializing the AppInsightsLogger') self.env = Env() self.run_id = self.get_run_id_and_set_context(run) # Prepare integrations and initialize tracer config_integration.trace_integrations(['httplib', 'logging']) texporter = AzureExporter( connection_string=self.env.app_insights_connection_string) texporter.add_telemetry_processor(self.callback_function) self.tracer = Tracer(exporter=texporter, sampler=ProbabilitySampler( self.env.trace_sampling_rate)) # Create AppInsights Handler and set log format self.logger = logging.getLogger(__name__) self.logger.setLevel( getattr(logging, self.env.log_level.upper(), "WARNING")) handler = AzureLogHandler( connection_string=self.env.app_insights_connection_string, logging_sampling_rate=self.env.log_sampling_rate, ) handler.add_telemetry_processor(self.callback_function) self.logger.addHandler(handler) # initializes metric exporter mexporter = metrics_exporter.new_metrics_exporter( enable_standard_metrics=self.env.enable_standard_metrics, export_interval=self.env.metrics_export_interval, connection_string=self.env.app_insights_connection_string, ) mexporter.add_telemetry_processor(self.callback_function) stats_module.stats.view_manager.register_exporter(mexporter) def log_metric( self, name="", value="", description="", log_parent=False, ): """ Sends a custom metric to appInsights :param name: name of the metric :param value: value of the metric :param description: description of the metric :param log_parent: not being used for this logger :return: """ measurement_map = \ stats_module.stats.stats_recorder.new_measurement_map() tag_map = tag_map_module.TagMap() measure = measure_module.MeasureFloat(name, description) self.set_view(name, description, measure) measurement_map.measure_float_put(measure, value) measurement_map.record(tag_map) def log(self, description="", severity=Severity.INFO): """ Sends the logs to App Insights :param description: log description :param severity: log severity :return: """ # Overwrite custom dimensions with caller data modulename, filename, lineno = self.get_callee_details(2) self.custom_dimensions[self.CUSTOM_DIMENSIONS][self.FILENAME] =\ filename self.custom_dimensions[self.CUSTOM_DIMENSIONS][self.LINENO] =\ lineno self.custom_dimensions[self.CUSTOM_DIMENSIONS][self.MODULE] =\ modulename if self.current_span() is not None: self.custom_dimensions[self.CUSTOM_DIMENSIONS][self.PROCESS] =\ self.current_span().name if severity == self.severity.DEBUG: self.logger.debug(description, extra=self.custom_dimensions) elif severity == self.severity.INFO: self.logger.info(description, extra=self.custom_dimensions) elif severity == self.severity.WARNING: self.logger.warning(description, extra=self.custom_dimensions) elif severity == self.severity.ERROR: self.logger.error(description, extra=self.custom_dimensions) elif severity == self.severity.CRITICAL: self.logger.critical(description, extra=self.custom_dimensions) def exception(self, exception: Exception): """ Sends the exception to App Insights :param exception: Actual exception to be sent :return: """ self.logger.exception(exception, extra=self.custom_dimensions) # Mark current span/operation with internal error if self.current_span() is not None: self.current_span().status = Status(2, exception) self.current_span().attributes['http.status_code'] = 500 @staticmethod def set_view(metric, description, measure): """ Sets the view for the custom metric """ prompt_view = view_module.View( metric, description, [], measure, aggregation_module.LastValueAggregation()) stats_module.stats.view_manager.register_view(prompt_view) def callback_function(self, envelope): """ Attaches a correlation_id as a custom dimension to the exporter just before sending the logs/metrics :param envelope: :return: Always return True (if False, it does not export metrics/logs) """ envelope.data.baseData.properties[self.CORRELATION_ID] = self.run_id return True def span(self, name='span'): """Create a new span with the trace using the context information. :type name: str :param name: The name of the span. :rtype: :class:`~opencensus.trace.span.Span` :returns: The Span object. """ return self.start_span(name) def start_span(self, name='span'): """Start a span. :type name: str :param name: The name of the span. :rtype: :class:`~opencensus.trace.span.Span` :returns: The Span object. """ span = self.tracer.start_span(name) span.span_kind = SpanKind.SERVER span.attributes['http.method'] = 'START' span.attributes['http.route'] = name return span def end_span(self): """End a span. Remove the span from the span stack, and update the span_id in TraceContext as the current span_id which is the peek element in the span stack. """ self.tracer.end_span() def current_span(self): """Return the current span.""" return self.tracer.current_span() def add_attribute_to_current_span(self, attribute_key, attribute_value): self.tracer.add_attribute_to_current_span(attribute_key, attribute_value) def list_collected_spans(self): """List collected spans.""" self.tracer.list_collected_spans()