def test_setup_no_service_name(stdout):
    # GIVEN no service is explicitly defined
    # WHEN logger is setup
    # THEN service field should be "service_undefined"
    logger = Logger(stream=stdout)
    logger.info("Hello")
    log = json.loads(stdout.getvalue())

    assert "service_undefined" == log["service"]
def test_setup_service_name(root_logger, stdout):
    # GIVEN service is explicitly defined
    # WHEN logger is setup
    # THEN service field should be equals service given
    service_name = "payment"
    logger = Logger(service=service_name, stream=stdout)

    logger.info("Hello")
    log = json.loads(stdout.getvalue())

    assert service_name == log["service"]
def test_setup_service_env_var(monkeypatch, stdout):
    # GIVEN service is explicitly defined via POWERTOOLS_SERVICE_NAME env
    # WHEN logger is setup
    # THEN service field should be equals POWERTOOLS_SERVICE_NAME value
    service_name = "payment"
    monkeypatch.setenv("POWERTOOLS_SERVICE_NAME", service_name)

    logger = Logger(stream=stdout)
    logger.info("Hello")
    log = json.loads(stdout.getvalue())

    assert service_name == log["service"]
def log_eventbridge_errors(response: dict, function_logger: Logger):
    """
    Args:
          response: Response from putting events onto eventBridge
          function_logger: logger to write out errors to (if any exists)
    return:
        null
    """

    if response["FailedEntryCount"] > 0:
        for entry in response["Entries"]:
            if entry.get("ErrorCode", False):
                function_logger.error(entry)

    return response["FailedEntryCount"]
def test_setup_sampling_rate(monkeypatch, 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(stream=stdout)
    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_log_no_request_by_default(
        monkeypatch, lambda_context, stdout):
    # GIVEN a lambda function is decorated with logger
    # WHEN logger is setup
    # THEN logger should not log event received by lambda handler
    lambda_event = {"greeting": "hello"}

    logger = Logger(stream=stdout)

    @logger.inject_lambda_context
    def handler(event, context):
        logger.info("Hello")

    handler(lambda_event, lambda_context)

    # Given that our string buffer has many log statements separated by newline \n
    # We need to clean it before we can assert on
    logs = [
        json.loads(line.strip()) for line in stdout.getvalue().split("\n")
        if line
    ]

    event = {}
    for log in logs:
        if "greeting" in log["message"]:
            event = log["message"]

    assert event != lambda_event
def test_inject_lambda_context_log_event_request_env_var(
        monkeypatch, lambda_context, stdout):
    # GIVEN a lambda function is decorated with logger instructed to log event
    # via POWERTOOLS_LOGGER_LOG_EVENT env
    # WHEN logger is setup
    # THEN logger should log event received from Lambda
    lambda_event = {"greeting": "hello"}
    monkeypatch.setenv("POWERTOOLS_LOGGER_LOG_EVENT", "true")

    logger = Logger(stream=stdout)

    @logger.inject_lambda_context
    def handler(event, context):
        logger.info("Hello")

    handler(lambda_event, lambda_context)

    # Given that our string buffer has many log statements separated by newline \n
    # We need to clean it before we can assert on
    logs = [
        json.loads(line.strip()) for line in stdout.getvalue().split("\n")
        if line
    ]

    event = {}
    for log in logs:
        if "greeting" in log["message"]:
            event = log["message"]

    assert event == lambda_event
def test_inject_lambda_cold_start(lambda_context, stdout):
    # GIVEN a lambda function is decorated with logger, and called twice
    # WHEN logger is setup
    # THEN cold_start key should only be true in the first call

    from aws_lambda_powertools.logging import logger

    # # As we run tests in parallel global cold_start value can be false
    # # here we reset to simulate the correct behaviour
    # # since Lambda will only import our logger lib once per concurrent execution
    logger.is_cold_start = True

    logger = Logger(stream=stdout)

    def custom_method():
        logger.info("Hello from method")

    @logger.inject_lambda_context
    def handler(event, context):
        custom_method()
        logger.info("Hello")

    handler({}, lambda_context)
    handler({}, lambda_context)

    # Given that our string buffer has many log statements separated by newline \n
    # We need to clean it before we can assert on
    logs = [
        json.loads(line.strip()) for line in stdout.getvalue().split("\n")
        if line
    ]
    first_log, second_log, third_log, fourth_log = logs

    # First execution
    assert "true" == first_log["cold_start"]
    assert "true" == second_log["cold_start"]

    # Second execution
    assert "false" == third_log["cold_start"]
    assert "false" == fourth_log["cold_start"]
def test_inject_lambda_context(lambda_context, stdout):
    # GIVEN a lambda function is decorated with logger
    # WHEN logger is setup
    # THEN lambda contextual info should always be in the logs
    logger_context_keys = (
        "function_name",
        "function_memory_size",
        "function_arn",
        "function_request_id",
    )

    logger = Logger(stream=stdout)

    @logger.inject_lambda_context
    def handler(event, context):
        logger.info("Hello")

    handler({}, lambda_context)

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

    for key in logger_context_keys:
        assert key in log
def test_inject_lambda_context_log_event_request(lambda_context, stdout):
    # GIVEN a lambda function is decorated with logger instructed to log event
    # WHEN logger is setup
    # THEN logger should log event received from Lambda
    lambda_event = {"greeting": "hello"}

    logger = Logger(stream=stdout)

    @logger.inject_lambda_context(log_event=True)
    # @logger.inject_lambda_context(log_event=True)
    def handler(event, context):
        logger.info("Hello")

    handler(lambda_event, lambda_context)

    # Given that our string buffer has many log statements separated by newline \n
    # We need to clean it before we can assert on
    logs = [
        json.loads(line.strip()) for line in stdout.getvalue().split("\n")
        if line
    ]
    logged_event, _ = logs
    assert "greeting" in logged_event["message"]
Beispiel #11
0
import os
import json

import boto3
from boto3.dynamodb.conditions import Key

from aws_lambda_powertools.logging import Logger

logger = Logger()

from common.dynamodb import DecimalEncoder, map_keys, query_till_end


def query_table(region, table, pk):
    """
    Args:
      table: DynamoDB table object to query
      region: region to query on
    returns:
      items: items returned from the query
    """

    kwargs = {
        "KeyConditionExpression": Key("pk").eq(pk),
        "ProjectionExpression": "arn, pckgVrsn, dplySts, rqrmntsTxt, exDt",
        "FilterExpression":
        "attribute_exists(dplySts)",  # don't get latest version
    }
    items = query_till_end(table=table, kwargs=kwargs)

    return map_keys(items)
Beispiel #12
0
from zipfile import ZipFile, is_zipfile
from typing import Dict, List, Optional

import hermes.backend.dict
from ask_sdk_core.exceptions import ApiClientException
from ask_sdk_model.services import ApiClient, ApiClientRequest
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer
from marshmallow import ValidationError

from .cache.bmemcached import Backend as BmemcachedBackend
from .exceptions import GTFSDataError, NetworkDescriptionError, OperationMonitoringError
from .model.line_stops import LineDetails
from .model.passing_times import PassingTime, PointPassingTimes

logger = Logger(service="STIB service")
tracer = Tracer(service="STIB service")

ENVIRONMENT = environ["env"]
MEMCACHED_ENDPOINT = environ["cache_endpoint"]
MEMCACHED_USERNAME = environ["cache_username"]
MEMCACHED_PASSWORD = environ["cache_password"]


@tracer.capture_method
def initialize_cache() -> hermes.Hermes:
    if ENVIRONMENT == "Sandbox":
        logger.info(
            {
                "operation": "Setting Hermes caching backend",
                "environment": ENVIRONMENT.upper(),
Beispiel #13
0
#  or in the "license" file accompanying this file. This file is
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

import gettext

from ask_sdk_core.dispatch_components import AbstractRequestInterceptor
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import get_locale
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

# Logging/tracing configuration
logger = Logger(service="i18n interceptor")
tracer = Tracer(service="i18n interceptor")


class LocalizationInterceptor(AbstractRequestInterceptor):
    """Request interceptor to handle multiple locales."""

    def process(self, handler_input):
        """Parse locale information and add i18n manager to the request attributes."""

        # type: (HandlerInput) -> None
        logger.debug("In LocalizationInterceptor")
        locale = get_locale(handler_input)
        logger.debug({"Locale": locale})
        i18n = gettext.translation(
            "base", localedir="core/locales/", languages=[locale], fallback=True
import os
import re

import requests

from aws_lambda_powertools.logging import Logger

logger = Logger(service="Console Sign-in")

class SlackMessage:
    def __init__(self, user_arn):
        self.user_arn = user_arn

    def _user_name(self):
        """
        Extracts the username from an AWS User ARN

        Parameters:
            self.user_arn (string): AWS User ARN, e.g. arn:aws:iam::123456789012:user/[email protected]

        Returns:
            username (string): Username in email format, e.g. [email protected]
        """
        arn = re.search(r'arn:aws:iam::\d{12}:user/([a-z]+@\w+\.com)', self.user_arn)
        return arn.group(1)

    def _payload(self) -> dict:
        p = {'username': self._user_name()}
        return p
        
    def post(self, slack_url: str) -> requests.Response:
Beispiel #15
0
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer
from requests import Response

from ...data import data

# Logging/tracing configuration
logger = Logger(service="Fallback Amazon handler")
tracer = Tracer(service="Fallback Amazon handler")


class FallBackHandler(AbstractRequestHandler):
    """Handler for Fallback Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return is_intent_name("AMAZON.FallbackIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        logger.debug("In FallbackIntentHandler")
        _ = handler_input.attributes_manager.request_attributes["_"]
#  specific language governing permissions and limitations under the
#  License.

import json
from calendar import timegm
from os import environ
from datetime import datetime, timedelta, timezone

import requests
from boto3.session import Session
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer
from botocore.exceptions import ClientError

# Logging/tracing configuration
logger = Logger(service="Token helper")
tracer = Tracer(service="Token helper")


class TokenException(Exception):
    """Exception for token generation errors"""
    def __init__(self, msg, original_exception):
        super(TokenException,
              self).__init__(msg + (": %s" % original_exception))
        self.original_exception = original_exception


class SecurityToken:
    """Authentication token and expiration date access/management."""
    def __init__(self, token, token_validity_time: int = None):
        if token_validity_time:
def test_logger_append_duplicated(stdout):
    logger = Logger(stream=stdout, request_id="value")
    logger.structure_logs(append=True, request_id="new_value")
    logger.info("log")
    log = json.loads(stdout.getvalue())
    assert "new_value" == log["request_id"]
Beispiel #18
0
#  License.

from typing import List, Optional

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from ask_sdk_model import Response
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ...data import data
from ...service.model.passing_times import PassingTime

# Logging/tracing configuration
logger = Logger(service="Get arrival time intent handler")
tracer = Tracer(service="Get arrival time intent handler")


class GetArrivalTimesNoPrefsIntentHandler(AbstractRequestHandler):
    """Handler for get arrival time Intent: no available preferences scenario."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        # Extract persistent attributes and check if they are all present
        attr = handler_input.attributes_manager.persistent_attributes
        attributes_are_present = ("favorite_stop_id" in attr
                                  and "favorite_line_id" in attr)
        return not attributes_are_present and is_intent_name(
            "GetArrivalTimesIntent")(handler_input)
Beispiel #19
0
#
#  or in the "license" file accompanying this file. This file is
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer
from requests import Response

# Logging/tracing configuration
logger = Logger(service="Repeat Amazon handler")
tracer = Tracer(service="Repeat Amazon handler")


class RepeatHandler(AbstractRequestHandler):
    """Handler for Repeat Intent."""

    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return is_intent_name("AMAZON.RepeatIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        logger.debug("In RepeatIntentHandler")
from ask_sdk_model.dialog.dynamic_entities_directive import *
from ask_sdk_model.dialog_state import DialogState
from ask_sdk_model.er.dynamic import (
    Entity,
    EntityListItem,
    EntityValueAndSynonyms,
    UpdateBehavior,
)
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ...data import data
from ...service.model.line_stops import LineDetails

# Logging/tracing configuration
logger = Logger(service="Favorite line intent handler")
tracer = Tracer(service="Favorite line intent handler")


class StartedInProgressFavoriteLineHandler(AbstractRequestHandler):
    """
    Handler to delegate the favorite line intent dialog to alexa
    """

    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return (
            is_intent_name("SetFavoriteLineIntent")(handler_input)
            and get_dialog_state(handler_input) != DialogState.COMPLETED
        )
Beispiel #21
0
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name, is_request_type
from ask_sdk_model import Response
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ...data import data

# Logging/tracing configuration
logger = Logger(service="Common Amazon handlers")
tracer = Tracer(service="Common Amazon handlers")


class YesIntentHandler(AbstractRequestHandler):
    """Single handler for Yes Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        _ = handler_input.attributes_manager.request_attributes["_"]
        session_attributes = handler_input.attributes_manager.session_attributes

        return session_attributes["repeat_prompt"] == _(
            data.ASK_FOR_PREFERENCES_REPROMPT) and is_intent_name(
                "AMAZON.YesIntent")(handler_input)

    def handle(self, handler_input):
Beispiel #22
0
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name, is_request_type
from ask_sdk_model import Response
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ...data import data

# Logging/tracing configuration
logger = Logger(service="Save trip preferences intent handler")
tracer = Tracer(service="Save trip preferences intent handler")


class SaveTripPreferencesHandler(AbstractRequestHandler):
    """Single handler for save trip preferences Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return is_intent_name("SaveTripPreferencesIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        logger.debug("In SaveTripPreferencesHandler")
Beispiel #23
0
import json
from os import environ
from typing import Optional

import requests
import six
from ask_sdk_core.exceptions import ApiClientException
from ask_sdk_model.services import ApiClient, ApiClientRequest, ApiClientResponse
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer
from urllib3.util import parse_url

from .token_helper import TokenHelper

logger = Logger(service="STIB API client")
tracer = Tracer(service="STIB API client")
OPEN_DATA_API_ENDPOINT = environ["open_data_api_endpoint"]

tracer.put_metadata(key="open_data_api_endpoint", value=OPEN_DATA_API_ENDPOINT)


class OpenDataAPIClient(ApiClient):
    """OpenData API client implementation wrapping HTTP requests"""

    def __init__(self):
        self.token_helper = TokenHelper()

    def invoke(self, request):
        # type: (ApiClientRequest) -> ApiClientResponse
        """Dispatches a request to an API endpoint described in the
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_request_type
from ask_sdk_model import Response
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ..data import data

# Logging/tracing configuration
logger = Logger(service="Launch handler")
tracer = Tracer(service="Launch handler")


class LaunchRequestHandler(AbstractRequestHandler):
    """Handler for Skill Launch."""

    # Todo: Make this two different launch handlers ?

    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
def test_logger_invalid_sampling_rate():
    with pytest.raises(InvalidLoggerSamplingRateError):
        Logger(sampling_rate="TEST")
Beispiel #26
0
from typing import Any, Dict, IO

import boto3
import imageio
import rawpy

from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.utilities.typing import LambdaContext
from mypy_boto3_s3 import S3Client
from mypy_boto3_s3.type_defs import PutObjectOutputTypeDef
from mypy_boto3_sts import STSClient

from common.models import JpegData, JpegDataItem, PutDdbItemAction
from common.util.dataclasses import lambda_dataclass_response

LOGGER = Logger(utc=True)

S3_CLIENT: S3Client = boto3.client("s3")
S3_EXPIRATION_DELTA_DAYS = 15

CROSS_ACCOUNT_IAM_ROLE_ARN = os.environ.get('CROSS_ACCOUNT_IAM_ROLE_ARN', '')

PHOTOOPS_S3_BUCKET = os.environ['PHOTOOPS_S3_BUCKET']
PHOTOOPS_IMAGE_CACHE_PREFIX = 'cache'


@dataclass
class Response(PutDdbItemAction):
    '''Function response'''
    Item: JpegDataItem
 def __init__(self):
     self.logger = Logger()
     self.tracer = Tracer()
Beispiel #28
0
#
#  or in the "license" file accompanying this file. This file is
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import (AbstractRequestInterceptor,
                                              AbstractResponseInterceptor)
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

# Logging/tracing configuration
logger = Logger(service="Logger interceptor")
tracer = Tracer(service="Logger interceptor")


class RequestLoggerInterceptor(AbstractRequestInterceptor):
    """Request Interceptor for logging purposes."""
    def process(self, handler_input):
        """Log the request envelope."""

        # type: (HandlerInput) -> None
        logger.debug({"Request Envelope": handler_input.request_envelope})


class ResponseLoggerInterceptor(AbstractResponseInterceptor):
    """Response Interceptor for logging purposes."""
    def process(self, handler_input, response):
class Utils:
    def __init__(self):
        self.logger = Logger()
        self.tracer = Tracer()

    def set_trace_id(self, lambda_handler):
        def get_trace_id(raw_trace_id):
            for t in raw_trace_id.split(';'):
                if t.startswith('Root'):
                    return t.split('=')[1]
            return None

        def decorate(event, context):
            if '_X_AMZN_TRACE_ID' in os.environ:
                if get_trace_id(os.environ['_X_AMZN_TRACE_ID']) is not None:
                    os.environ['trace_id'] = get_trace_id(
                        os.environ['_X_AMZN_TRACE_ID'])
            if 'trace_id' not in os.environ:
                START_TIME = time.time()
                HEX = hex(int(START_TIME))[2:]
                os.environ['trace_id'] = "0-{}-{}".format(
                    HEX, str(binascii.hexlify(urandom(12)), 'utf-8'))
            self.logger.structure_logs(append=True,
                                       trace_id=os.environ['trace_id'])
            self.logger.info(os.environ.get('trace_id'))
            response = lambda_handler(event, context)
            return response

        return decorate

    def api_gateway_response(self, lambda_handler):
        def decorate(event, context):
            response = lambda_handler(event, context)
            if isinstance(response, tuple):
                body = response[0]
                status = response[1]
            else:
                body = response
                status = 200

            if isinstance(body, Exception):
                if status == 200:
                    status = 400
                self.logger.exception(body)
                self.tracer.put_annotation("ErrorCode",
                                           body.__class__.__name__)
                self.tracer.put_annotation("ErrorMessage", "{}".format(body))
                res = {
                    "isBase64Encoded":
                    False,
                    "statusCode":
                    status,
                    'headers': {
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json"
                    },
                    'body':
                    json.dumps({
                        "Code": body.__class__.__name__,
                        "Message": "{}".format(body),
                        "TraceId": os.environ.get('trace_id')
                    })
                }

            else:
                if body is not None and isinstance(body, str) is False:
                    body = json.dumps(body)

                res = {
                    'isBase64Encoded': False,
                    'statusCode': status,
                    'headers': {
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json"
                    }
                }
                if body is not None:
                    res['body'] = body
            return res

        return decorate
#  or in the "license" file accompanying this file. This file is
#  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
#  OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the
#  License.

from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput
from aws_lambda_powertools.logging import Logger
from aws_lambda_powertools.tracing import Tracer

from ...data import data
from ...service.exceptions import OpenDataServiceException

# Logging/tracing configuration
logger = Logger(service="Exception handler")
tracer = Tracer(service="Exception handler")


class GenericExceptionHandler(AbstractExceptionHandler):
    """
    Catch All Exception handler.
    This handler catches all kinds of exceptions and prints
    the stack trace on AWS Cloudwatch with the request envelope.
    """
    def can_handle(self, handler_input, exception):
        # type: (HandlerInput, Exception) -> bool

        return True

    def handle(self, handler_input, exception):