Skip to content

feat: sampling feature for logger #7

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

Merged
merged 4 commits into from
Feb 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -291,5 +291,5 @@ $RECYCLE.BIN/
# End of https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode

# Misc

test_report
test_report
/.idea/*
26 changes: 23 additions & 3 deletions python/aws_lambda_powertools/logging/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
import itertools
import logging
import os
import random
from distutils.util import strtobool
from typing import Any, Callable, Dict

from . import aws_lambda_logging
from ..helper.models import MetricUnit, build_lambda_context_model, build_metric_unit_from_str
from . import aws_lambda_logging

logger = logging.getLogger(__name__)
logger.setLevel(os.getenv("LOG_LEVEL", "INFO"))

is_cold_start = True


def logger_setup(service: str = "service_undefined", level: str = "INFO", **kwargs):
def logger_setup(
service: str = "service_undefined", level: str = "INFO", sampling_rate: float = 0.0, **kwargs
):
"""Setups root logger to format statements in JSON.

Includes service name and any additional key=value into logs
Expand All @@ -26,13 +29,17 @@ def logger_setup(service: str = "service_undefined", level: str = "INFO", **kwar
service name
LOG_LEVEL: str
logging level (e.g. INFO, DEBUG)
POWERTOOLS_LOGGER_SAMPLE_RATE: float
samping rate ranging from 0 to 1, 1 being 100% sampling

Parameters
----------
service : str, optional
service name to be appended in logs, by default "service_undefined"
level : str, optional
logging.level, by default "INFO"
sample_rate: float, optional
sample rate for debug calls within execution context defaults to 0

Example
-------
Expand All @@ -47,6 +54,7 @@ def logger_setup(service: str = "service_undefined", level: str = "INFO", **kwar
Setups structured logging in JSON for Lambda functions using env vars

$ export POWERTOOLS_SERVICE_NAME="payment"
$ export POWERTOOLS_LOGGER_SAMPLE_RATE=0.01 # 1% debug sampling
>>> from aws_lambda_powertools.logging import logger_setup
>>> logger = logger_setup()
>>>
Expand All @@ -55,12 +63,24 @@ def logger_setup(service: str = "service_undefined", level: str = "INFO", **kwar

"""
service = os.getenv("POWERTOOLS_SERVICE_NAME") or service
sampling_rate = os.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE") or sampling_rate
log_level = os.getenv("LOG_LEVEL") or level
logger = logging.getLogger(name=service)

try:
if sampling_rate and random.random() <= float(sampling_rate):
log_level = logging.DEBUG
except ValueError:
raise ValueError(
f"Expected a float value ranging 0 to 1, but received {sampling_rate} instead. Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable."
)

logger.setLevel(log_level)

# Patch logger by structuring its outputs as JSON
aws_lambda_logging.setup(level=log_level, service=service, **kwargs)
aws_lambda_logging.setup(
level=log_level, service=service, sampling_rate=sampling_rate, **kwargs
)

return logger

Expand Down
2 changes: 1 addition & 1 deletion python/tests/functional/test_aws_lambda_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@ class X:

log_dict = json.loads(stdout.getvalue())

assert log_dict["message"]["x"].startswith("<")
assert log_dict["message"]["x"].startswith("<")
19 changes: 18 additions & 1 deletion python/tests/functional/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ def test_setup_service_env_var(monkeypatch, root_logger, stdout):
assert service_name == log["service"]


def test_setup_sampling_rate(monkeypatch, root_logger, stdout):
# GIVEN samping rate is explicitly defined via POWERTOOLS_LOGGER_SAMPLE_RATE env
# WHEN logger is setup
# THEN sampling rate should be equals POWERTOOLS_LOGGER_SAMPLE_RATE value and should sample debug logs

sampling_rate = "1"
monkeypatch.setenv("POWERTOOLS_LOGGER_SAMPLE_RATE", sampling_rate)
monkeypatch.setenv("LOG_LEVEL", "INFO")

logger = logger_setup()
logger.debug("I am being sampled")
log = json.loads(stdout.getvalue())

assert sampling_rate == log["sampling_rate"]
assert "DEBUG" == log["level"]
assert "I am being sampled" == log["message"]


def test_inject_lambda_context(root_logger, stdout, lambda_context):
# GIVEN a lambda function is decorated with logger
# WHEN logger is setup
Expand Down Expand Up @@ -130,7 +148,6 @@ def handler(event, context):
def test_inject_lambda_context_log_event_request_env_var(
monkeypatch, root_logger, stdout, lambda_context
):

# GIVEN a lambda function is decorated with logger instructed to log event
# via POWERTOOLS_LOGGER_LOG_EVENT env
# WHEN logger is setup
Expand Down