import logging
import os
from app.lib.pymorri.util.application_dependencies import ApplicationDependencies
from app.lib.pymorri.util.aws_utils import get_event_from_sns
from app.lib.pymorri.util.serverless_utils import get_or_exception
from app.lib.pymorri.util.datadog_utils import send_check_event_to_datadog, send_metric_event_to_datadog
from datadog.api.constants import CheckStatus
metric_type_list = ['gauge', 'rate', 'count', 'check']
valid_check_status_list = [CheckStatus.OK, CheckStatus.WARNING, CheckStatus.UNKNOWN, CheckStatus.CRITICAL]
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
deps = None
def _prepare_deps(config, ssm):
global deps
if not deps:
deps = ApplicationDependencies(
config_file=config,
ssm_param_store_name=ssm
)
[docs]@get_event_from_sns
def lambda_handler(event, context):
"""
This Lambda is trigerred by env specific digital-storepick-events topic. Any application that wants to post a metric to
Datadog would post the metric payload onto the digital-storepick-events topic thus allowing asynchronous way of posting
metric to Datadog.
The following information needs to be in the event which is important for the Datadog dashboard:
- Metric Name - Name of metric to be posted
- Metric Type - Type of metric e.g. count, sum
- Metric Value - Actual value of the metric
- Application Name - Metric relates to which application e.g. nhs_discount
Args:
event (dict) - required: event['Records'][0]['Sns'].get("Message")
Example:
.. code-block:: python
event = {
"Records": [
{
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
"EventSource": "aws:sns",
"Sns": {
"SignatureVersion": "1",
"Timestamp": "2019-01-02T12:45:07.000Z",
"Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
"SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "{\"eventType\": \"writeMetricForMonitoring\", \"eventData\": { \"name\": \"storepick_state_mc2\",\"type\": \"check\",\"metric_value\": \"2\", \"application\": \"nhs-discount\" } }",
"MessageAttributes": {
"eventType": {
"Type": "String",
"Value": "logRowToBq"
}
},
"Type": "Notification",
"UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
"TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda",
"Subject": "TestInvoke"
}
}
]
}
Returns:
event (dict): response from datadog api call
Example:
.. code-block:: python
event = {'status': 'ok'}
Raises:
Exception: Exception containing details about exception
"""
################################################################################
# need to populate the global deps (which is cached deliberately outside this
# main handler
################################################################################
_prepare_deps(None, "storepick_datadog_apikey")
global deps
logger.info(f"input event: {event}")
if "ENV" not in os.environ:
raise KeyError("Env is not set")
env = os.environ['ENV']
logger.info(f"ENV is {env}")
event_data = get_or_exception(event, "eventData")
metric_value = get_or_exception(event_data, "metric_value")
metric_name = get_or_exception(event_data, "name")
metric_type = get_or_exception(event_data, "type")
application_name = get_or_exception(event_data, "application")
logger.info(f"metric_name...{metric_name} metric_type... {metric_type} metric_value... {metric_value}")
ssm = deps.get_ssm_params()
datadog_api_key = get_or_exception(ssm, "DD_KMS_API_KEY")
datadog_app_key = get_or_exception(ssm, "DD_KMS_APPLICATION_KEY")
datadog_host = "https://api.datadoghq.com/"
options = {
'api_key': datadog_api_key,
'app_key': datadog_app_key,
'api_host': datadog_host
}
if metric_type not in metric_type_list:
raise ValueError("Invalid datadog event value")
if metric_type == 'count':
response = send_metric_event_to_datadog(options, env, application_name, metric_name, metric_type, metric_value)
else:
if int(metric_value) not in valid_check_status_list:
raise ValueError("Invalid check event value")
response = send_check_event_to_datadog(options, env, application_name, metric_name, metric_value)
return response
if __name__ == "__main__":
# count event
# event = {
# "Records": [
# {
# "EventVersion": "1.0",
# "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
# "EventSource": "aws:sns",
# "Sns": {
# "SignatureVersion": "1",
# "Timestamp": "2019-01-02T12:45:07.000Z",
# "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
# "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
# "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
# "Message": "{ \"eventType\": \"writeMetricForMonitoring\", \"eventData\": { \"name\": \"storepick_state_mc\", \"type\": \"count\", \"metric_value\": \"1000\", \"application\": \"edit-order-notification\" }",
# "MessageAttributes": {
# "eventType": {
# "Type": "String",
# "Value": "logRowToBq"
# }
# },
# "Type": "Notification",
# "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
# "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda",
# "Subject": "TestInvoke"
# }
# }
# ]
# }
#check event
event = {
"Records": [
{
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
"EventSource": "aws:sns",
"Sns": {
"SignatureVersion": "1",
"Timestamp": "2019-01-02T12:45:07.000Z",
"Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
"SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "{\"eventType\": \"writeMetricForMonitoring\", \"eventData\": { \"name\": \"storepick_state_mc2\",\"type\": \"check\",\"metric_value\": \"0\", \"application\": \"nhs-discount\" } }",
"MessageAttributes": {
"eventType": {
"Type": "String",
"Value": "logRowToBq"
}
},
"Type": "Notification",
"UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
"TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda",
"Subject": "TestInvoke"
}
}
]
}
response = lambda_handler(event, '')