def handle_error(self, context): beeline.add_context_field( "db.error", beeline.internal.stringify_exception(context.original_exception)) if self.state.span: beeline.finish_span(self.state.span) self.state.span = None
def lambda_handler(event, context): trace_context = None input = None parent_trace = None output = {} logging.debug(f"event: {json.dumps(event)}") init_beeline() # Attempt to get trace_context(s) from the input input = event.get("Input", None) if input: trace_context = input.get("trace_context", None) # Start trace if it isn't already, otherwise resume if trace_context: trace_id, parent_id, context = beeline.trace.unmarshal_trace_context( trace_context) logging.info(f"Resuming trace: {trace_id}") trace = beeline.start_trace(trace_id=trace_id, parent_span_id=parent_id, context=context) # add a field to test context propogation beeline.add_trace_field( event.get("Path", "UnknownPath").lower(), uuid.uuid4()) beeline.add_context( {"name": event.get("Path", "Missing Path Information")}) beeline.add_context( {"function_name": event.get("Path", "Missing Path Information")}) random_sleep() beeline.finish_span(trace) else: trace = start_trace() beeline.add_trace_field("c3po", "r2d2") logging.info(f"Starting Trace") with beeline.tracer( name=event.get("Path", "Missing Path Information")): random_sleep() trace_context = beeline.get_beeline( ).tracer_impl.marshal_trace_context() # If final step close the parent trace if event.get("Path") == "Step4": # 2019-03-26T20:14:13.192Z parent_trace_id, parent_parent_id, parent_context_data = beeline.trace.unmarshal_trace_context( trace_context) start_time = datetime.strptime(event.get("start_time"), "%Y-%m-%dT%H:%M:%S.%fZ") close_final_trace(parent_trace_id, parent_parent_id, parent_context_data, start_time) # Close only (send pending) beeline.close() # Return the trace_context to the SFN output["trace_context"] = trace_context return output
def _render_template(fn, instance, args, kwargs): span = beeline.start_span(context={ "name": "jinja2_render_template", "template.name": instance.name or "[string]", }) try: return fn(*args, **kwargs) finally: beeline.finish_span(span)
def request(_request, instance, args, kwargs): span = beeline.start_span(context={"meta.type": "http_client"}) b = beeline.get_beeline() if b and b.http_trace_propagation_hook is not None: new_headers = beeline.http_trace_propagation_hook() if new_headers: b.log( "requests lib - adding trace context to outbound request: %s", new_headers) instance.headers.update(new_headers) else: b.log("requests lib - no trace context found") try: resp = None # Required as Python treats the `or` keyword differently in string # interpolation vs. when assigning a variable. method = kwargs.get('method') or args[0] beeline.add_context({ "name": "requests_%s" % method, "request.method": method, "request.url": kwargs.get('url') or args[1], }) resp = _request(*args, **kwargs) return resp except Exception as e: beeline.add_context({ "request.error_type": str(type(e)), "request.error": beeline.internal.stringify_exception(e), }) raise finally: if resp is not None: content_type = resp.headers.get('content-type') if content_type: beeline.add_context_field("response.content_type", content_type) content_length = resp.headers.get('content-length') if content_length: beeline.add_context_field("response.content_length", content_length) if hasattr(resp, 'status_code'): beeline.add_context_field("response.status_code", resp.status_code) beeline.finish_span(span)
def after_cursor_execute(self, conn, cursor, statement, parameters, context, executemany): if not current_app: return query_duration = datetime.datetime.now() - self.query_start_time beeline.add_context({ "db.duration": query_duration.total_seconds() * 1000, "db.last_insert_id": getattr(cursor, 'lastrowid', None), "db.rows_affected": cursor.rowcount, }) if self.state.span: beeline.finish_span(self.state.span) self.state.span = None
def request(_request, instance, args, kwargs): span = beeline.start_span(context={"meta.type": "http_client"}) b = beeline.get_beeline() if b: context = b.tracer_impl.marshal_trace_context() if context: b.log( "requests lib - adding trace context to outbound request: %s", context) instance.headers['X-Honeycomb-Trace'] = context else: b.log("requests lib - no trace context found") try: resp = None beeline.add_context({ "name": "requests_%s" % kwargs.get('method') or args[0], "request.method": kwargs.get('method') or args[0], "request.url": kwargs.get('url') or args[1], }) resp = _request(*args, **kwargs) return resp except Exception as e: beeline.add_context({ "request.error_type": str(type(e)), "request.error": beeline.internal.stringify_exception(e), }) raise finally: if resp: content_type = resp.headers.get('content-type') if content_type: beeline.add_context_field("response.content_type", content_type) content_length = resp.headers.get('content-length') if content_length: beeline.add_context_field("response.content_length", content_length) if hasattr(resp, 'status_code'): beeline.add_context_field("response.status_code", resp.status_code) beeline.finish_span(span)
def _urllibopen(_urlopen, instance, args, kwargs): # urlopen accepts either a string URL or a Request object as its first arg # It's easier to process the info contained in the request and modify it # by converting the URL string into a Request if type(args[0]) != urllib.request.Request: args = (urllib.request.Request(args[0]), ) + tuple(args[1:]) span = beeline.start_span(context={"meta.type": "http_client"}) b = beeline.get_beeline() if b and b.http_trace_propagation_hook is not None: new_headers = beeline.http_trace_propagation_hook() if new_headers: # Merge the new headers into the existing headers for the outbound request b.log("urllib lib - adding trace context to outbound request: %s", new_headers) args[0].headers.update(new_headers) try: resp = None beeline.add_context({ "name": "urllib_%s" % args[0].get_method(), "request.method": args[0].get_method(), "request.uri": args[0].full_url }) resp = _urlopen(*args, **kwargs) return resp except Exception as e: beeline.add_context({ "request.error_type": str(type(e)), "request.error": beeline.internal.stringify_exception(e), }) raise finally: if resp: beeline.add_context_field("response.status_code", resp.status) content_type = resp.getheader('content-type') if content_type: beeline.add_context_field("response.content_type", content_type) content_length = resp.getheader('content-length') if content_length: beeline.add_context_field("response.content_length", content_length) beeline.finish_span(span)
def _urllibopen(_urlopen, instance, args, kwargs): if type(args[0]) != urllib.request.Request: args[0] = urllib.request.Request(args[0]) span = beeline.start_span(context={"meta.type": "http_client"}) b = beeline.get_beeline() if b: context = b.tracer_impl.marshal_trace_context() if context: b.log("urllib lib - adding trace context to outbound request: %s", context) args[0].headers['X-Honeycomb-Trace'] = context else: b.log("urllib lib - no trace context found") try: resp = None beeline.add_context({ "name": "urllib_%s" % args[0].get_method(), "request.method": args[0].get_method(), "request.uri": args[0].full_url }) resp = _urlopen(*args, **kwargs) return resp except Exception as e: beeline.add_context({ "request.error_type": str(type(e)), "request.error": beeline.internal.stringify_exception(e), }) raise finally: if resp: beeline.add_context_field("response.status_code", resp.status) content_type = resp.getheader('content-type') if content_type: beeline.add_context_field("response.content_type", content_type) content_length = resp.getheader('content-length') if content_length: beeline.add_context_field("response.content_length", content_length) beeline.finish_span(span)
def random_sleep(): logging.info("Generating a span") span = beeline.start_span(context={"name": "do_assorted_data_processing"}) time.sleep(random.randint(1, 10)) beeline.finish_span(span)
def hello_world(): span = beeline.start_span(context={"name": "Preparing to greet the world"}) message = "Hello World" beeline.add_trace_field('message', message) beeline.finish_span(span) return message