-
Notifications
You must be signed in to change notification settings - Fork 426
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into chore/trigger-probe
- Loading branch information
Showing
62 changed files
with
2,605 additions
and
584 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import logging | ||
from typing import Dict | ||
from typing import Union | ||
|
||
from ddtrace import config | ||
from ddtrace._trace.span import Span | ||
from ddtrace.constants import SPAN_KIND | ||
from ddtrace.ext import SpanKind | ||
from ddtrace.ext import SpanTypes | ||
from ddtrace.ext import http | ||
from ddtrace.internal.constants import COMPONENT | ||
from ddtrace.propagation.http import _extract_header_value | ||
from ddtrace.propagation.http import _possible_header | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
# Checking lower case and upper case versions per WSGI spec following ddtrace/propagation/http.py's | ||
# logic to extract http headers | ||
POSSIBLE_PROXY_HEADER_SYSTEM = _possible_header("x-dd-proxy") | ||
POSSIBLE_PROXY_HEADER_START_TIME_MS = _possible_header("x-dd-proxy-request-time-ms") | ||
POSSIBLE_PROXY_HEADER_PATH = _possible_header("x-dd-proxy-path") | ||
POSSIBLE_PROXY_HEADER_HTTPMETHOD = _possible_header("x-dd-proxy-httpmethod") | ||
POSSIBLE_PROXY_HEADER_DOMAIN = _possible_header("x-dd-proxy-domain-name") | ||
POSSIBLE_PROXY_HEADER_STAGE = _possible_header("x-dd-proxy-stage") | ||
|
||
supported_proxies: Dict[str, Dict[str, str]] = { | ||
"aws-apigateway": {"span_name": "aws.apigateway", "component": "aws-apigateway"} | ||
} | ||
|
||
|
||
def create_inferred_proxy_span_if_headers_exist(ctx, headers, child_of, tracer) -> None: | ||
if not headers: | ||
return None | ||
|
||
normalized_headers = normalize_headers(headers) | ||
|
||
proxy_context = extract_inferred_proxy_context(normalized_headers) | ||
|
||
if not proxy_context: | ||
return None | ||
|
||
proxy_span_info = supported_proxies[proxy_context["proxy_system_name"]] | ||
|
||
span = tracer.start_span( | ||
proxy_span_info["span_name"], | ||
service=proxy_context.get("domain_name", config._get_service()), | ||
resource=proxy_context["method"] + " " + proxy_context["path"], | ||
span_type=SpanTypes.WEB, | ||
activate=True, | ||
child_of=child_of, | ||
) | ||
span.start_ns = int(proxy_context["request_time"]) * 1000000 | ||
|
||
set_inferred_proxy_span_tags(span, proxy_context) | ||
|
||
# we need a callback to finish the api gateway span, this callback will be added to the child spans finish callbacks | ||
def finish_callback(_): | ||
span.finish() | ||
|
||
if span: | ||
ctx.set_item("inferred_proxy_span", span) | ||
ctx.set_item("inferred_proxy_finish_callback", finish_callback) | ||
ctx.set_item("headers", headers) | ||
|
||
|
||
def set_inferred_proxy_span_tags(span, proxy_context) -> Span: | ||
span.set_tag_str(COMPONENT, supported_proxies[proxy_context["proxy_system_name"]]["component"]) | ||
span.set_tag_str(SPAN_KIND, SpanKind.INTERNAL) | ||
|
||
span.set_tag_str(http.METHOD, proxy_context["method"]) | ||
span.set_tag_str(http.URL, f"{proxy_context['domain_name']}{proxy_context['path']}") | ||
span.set_tag_str(http.ROUTE, proxy_context["path"]) | ||
span.set_tag_str("stage", proxy_context["stage"]) | ||
|
||
span.set_tag_str("_dd.inferred_span", "1") | ||
return span | ||
|
||
|
||
def extract_inferred_proxy_context(headers) -> Union[None, Dict[str, str]]: | ||
proxy_header_system = str(_extract_header_value(POSSIBLE_PROXY_HEADER_SYSTEM, headers)) | ||
proxy_header_start_time_ms = str(_extract_header_value(POSSIBLE_PROXY_HEADER_START_TIME_MS, headers)) | ||
proxy_header_path = str(_extract_header_value(POSSIBLE_PROXY_HEADER_PATH, headers)) | ||
proxy_header_httpmethod = str(_extract_header_value(POSSIBLE_PROXY_HEADER_HTTPMETHOD, headers)) | ||
proxy_header_domain = str(_extract_header_value(POSSIBLE_PROXY_HEADER_DOMAIN, headers)) | ||
proxy_header_stage = str(_extract_header_value(POSSIBLE_PROXY_HEADER_STAGE, headers)) | ||
|
||
# Exit if any of the required headers are not present | ||
if ( | ||
not proxy_header_system | ||
or not proxy_header_start_time_ms | ||
or not proxy_header_path | ||
or not proxy_header_httpmethod | ||
or not proxy_header_domain | ||
or not proxy_header_stage | ||
): | ||
return None | ||
|
||
if not (proxy_header_system and proxy_header_system in supported_proxies): | ||
log.debug( | ||
"Received headers to create inferred proxy span but headers include an unsupported proxy type", headers | ||
) | ||
return None | ||
|
||
return { | ||
"request_time": proxy_header_start_time_ms, | ||
"method": proxy_header_httpmethod, | ||
"path": proxy_header_path, | ||
"stage": proxy_header_stage, | ||
"domain_name": proxy_header_domain, | ||
"proxy_system_name": proxy_header_system, | ||
} | ||
|
||
|
||
def normalize_headers(headers) -> Dict[str, str]: | ||
return {key.lower(): value for key, value in headers.items()} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.