-
Notifications
You must be signed in to change notification settings - Fork 45
Statsd integration #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
c43b5b5
1e346ab
8942e67
041bb51
866a75e
7883a6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import logging | ||
import requests | ||
|
||
AGENT_URL = "http://127.0.0.1:8124" | ||
HELLO_PATH = "/lambda/hello" | ||
FLUSH_PATH = "/lambda/flush" | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def is_extension_running(): | ||
try: | ||
requests.get(AGENT_URL + HELLO_PATH) | ||
except Exception as e: | ||
logger.debug("Extension is not running, returned with error %s", e) | ||
return False | ||
return True | ||
|
||
|
||
def flush_extension(): | ||
try: | ||
requests.post(AGENT_URL + FLUSH_PATH, data={}) | ||
except Exception as e: | ||
logger.debug("Failed to flush extension, returned with error %s", e) | ||
return False | ||
return True | ||
|
||
|
||
use_extension = is_extension_running() | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,20 +10,42 @@ | |
import logging | ||
|
||
import boto3 | ||
from datadog import api | ||
from datadog import api, initialize, statsd | ||
from datadog.threadstats import ThreadStats | ||
from datadog_lambda.extension import use_extension | ||
from datadog_lambda.tags import get_enhanced_metrics_tags, tag_dd_lambda_layer | ||
|
||
|
||
ENHANCED_METRICS_NAMESPACE_PREFIX = "aws.lambda.enhanced" | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
lambda_stats = ThreadStats() | ||
lambda_stats.start() | ||
|
||
class StatsDWrapper: | ||
""" | ||
Wraps StatsD calls, to give an identical to ThreadStats | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to give an identical what? |
||
""" | ||
|
||
def __init__(self): | ||
options = {"statsd_host": "127.0.0.1", "statsd_port": 8125} | ||
initialize(**options) | ||
|
||
def distribution(self, metric_name, value, tags=[], timestamp=None): | ||
statsd.distribution(metric_name, value, tags=tags) | ||
|
||
def flush(self, value): | ||
pass | ||
|
||
|
||
def lambda_metric(metric_name, value, timestamp=None, tags=None): | ||
lambda_stats = None | ||
if use_extension: | ||
lambda_stats = StatsDWrapper() | ||
else: | ||
lambda_stats = ThreadStats() | ||
lambda_stats.start() | ||
|
||
|
||
def lambda_metric(metric_name, value, timestamp=None, tags=None, force_async=False): | ||
""" | ||
Submit a data point to Datadog distribution metrics. | ||
https://docs.datadoghq.com/graphing/metrics/distributions/ | ||
|
@@ -36,12 +58,14 @@ def lambda_metric(metric_name, value, timestamp=None, tags=None): | |
periodically and at the end of the function execution in a | ||
background thread. | ||
""" | ||
flush_to_logs = os.environ.get("DD_FLUSH_TO_LOG", "").lower() == "true" | ||
tags = tag_dd_lambda_layer(tags) | ||
if os.environ.get("DD_FLUSH_TO_LOG", "").lower() == "true": | ||
write_metric_point_to_stdout(metric_name, value, timestamp, tags) | ||
|
||
if flush_to_logs or (force_async and not use_extension): | ||
write_metric_point_to_stdout(metric_name, value, timestamp=timestamp, tags=tags) | ||
else: | ||
logger.debug("Sending metric %s to Datadog via lambda layer", metric_name) | ||
lambda_stats.distribution(metric_name, value, timestamp=timestamp, tags=tags) | ||
lambda_stats.distribution(metric_name, value, tags=tags, timestamp=timestamp) | ||
|
||
|
||
def write_metric_point_to_stdout(metric_name, value, timestamp=None, tags=[]): | ||
|
@@ -85,13 +109,10 @@ def submit_enhanced_metric(metric_name, lambda_context): | |
metric_name, | ||
) | ||
return | ||
|
||
# Enhanced metrics are always written to logs | ||
write_metric_point_to_stdout( | ||
"{}.{}".format(ENHANCED_METRICS_NAMESPACE_PREFIX, metric_name), | ||
1, | ||
tags=get_enhanced_metrics_tags(lambda_context), | ||
) | ||
tags = get_enhanced_metrics_tags(lambda_context) | ||
metric_name = "aws.lambda.enhanced." + metric_name | ||
# Enhanced metrics always use an async submission method, (eg logs or extension). | ||
lambda_metric(metric_name, 1, timestamp=None, tags=tags, force_async=True) | ||
|
||
|
||
def submit_invocations_metric(lambda_context): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
./scripts/list_layers.sh | ||
./scripts/build_layers.sh | ||
./scripts/publish_layers.sh us-east-1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,9 +38,9 @@ def setUp(self): | |
self.mock_wrapper_lambda_stats = patcher.start() | ||
self.addCleanup(patcher.stop) | ||
|
||
patcher = patch("datadog_lambda.metric.lambda_metric") | ||
self.mock_lambda_metric = patcher.start() | ||
self.addCleanup(patcher.stop) | ||
# patcher = patch("datadog_lambda.metric.lambda_metric") | ||
# self.mock_lambda_metric = patcher.start() | ||
# self.addCleanup(patcher.stop) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We were patching the datadog_lambda.metric.lambda_metric out for testing, but the new code uses it internally, so I unpatched it. I'll remove this snippet. |
||
|
||
patcher = patch("datadog_lambda.wrapper.extract_dd_trace_context") | ||
self.mock_extract_dd_trace_context = patcher.start() | ||
|
@@ -152,6 +152,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
) | ||
] | ||
) | ||
|
@@ -181,6 +182,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
), | ||
call( | ||
"aws.lambda.enhanced.errors", | ||
|
@@ -195,6 +197,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
), | ||
] | ||
) | ||
|
@@ -229,6 +232,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
), | ||
call( | ||
"aws.lambda.enhanced.invocations", | ||
|
@@ -243,6 +247,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
), | ||
] | ||
) | ||
|
@@ -275,6 +280,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
) | ||
] | ||
) | ||
|
@@ -307,6 +313,7 @@ def lambda_handler(event, context): | |
"runtime:python2.7", | ||
"dd_lambda_layer:datadog-python27_0.1.0", | ||
], | ||
timestamp=None, | ||
) | ||
] | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me,
use_extension
sounds like a verb, i.e. if I call it, then the extension will be used. But it seems like it represents whether the extension should be used. Maybe rename this tois_using_extension
orshould_use_extension
or something along those lines?