Skip to content

environment overrides #26

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

Closed
wants to merge 3 commits into from
Closed
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Generate CloudWatch Metrics embedded within structured log events. The embedded
- [Installation](#installation)
- [Usage](#usage)
- [API](#api)
- [Configuration](#configuration)
- [Examples](#examples)
- [Development](#development)

Expand Down Expand Up @@ -151,7 +152,7 @@ set_namespace("MyApplication");

Flushes the current MetricsContext to the configured sink and resets all properties, dimensions and metric values. The namespace and default dimensions will be preserved across flushes.

### Configuration
## Configuration

All configuration values can be set using environment variables with the prefix (`AWS_EMF_`). Configuration should be performed as close to application start up as possible.

Expand Down
4 changes: 4 additions & 0 deletions aws_embedded_metrics/config/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from aws_embedded_metrics.environment.environments import Environments


class Configuration:
def __init__(
Expand All @@ -22,6 +24,7 @@ def __init__(
log_stream_name: str,
agent_endpoint: str,
ec2_metadata_endpoint: str = None,
environment: Environments = Environments.Unknown
):
self.debug_logging_enabled = debug_logging_enabled
self.service_name = service_name
Expand All @@ -30,3 +33,4 @@ def __init__(
self.log_stream_name = log_stream_name
self.agent_endpoint = agent_endpoint
self.ec2_metadata_endpoint = ec2_metadata_endpoint
self.environment = environment
13 changes: 13 additions & 0 deletions aws_embedded_metrics/config/environment_configuration_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import os
from aws_embedded_metrics.config.configuration import Configuration
from aws_embedded_metrics.environment.environments import Environments

ENV_VAR_PREFIX = "AWS_EMF"

Expand All @@ -23,6 +24,7 @@
LOG_STREAM_NAME = "LOG_STREAM_NAME"
AGENT_ENDPOINT = "AGENT_ENDPOINT"
EC2_METADATA_ENDPOINT = "EC2_METADATA_ENDPOINT"
ENVIRONMENT_OVERRIDE = "ENVIRONMENT"


class EnvironmentConfigurationProvider:
Expand All @@ -39,6 +41,7 @@ def get_configuration(self) -> Configuration:
self.__get_env_var(LOG_STREAM_NAME),
self.__get_env_var(AGENT_ENDPOINT),
self.__get_env_var(EC2_METADATA_ENDPOINT),
self.__get_environment_override(),
)

@staticmethod
Expand All @@ -54,3 +57,13 @@ def __get_bool_env_var(key: str) -> bool:
if value is None:
return False
return value.lower() == "true"

@staticmethod
def __get_environment_override() -> Environments:
value = os.environ.get(f"{ENV_VAR_PREFIX}_{ENVIRONMENT_OVERRIDE}")
if value is not None and len(value) > 0:
try:
return Environments[value]
except Exception:
pass
return Environments.Unknown
32 changes: 30 additions & 2 deletions aws_embedded_metrics/environment/environment_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,36 @@

import logging
from aws_embedded_metrics.environment import Environment
from aws_embedded_metrics.environment.environments import Environments
from aws_embedded_metrics.environment.default_environment import DefaultEnvironment
from aws_embedded_metrics.environment.lambda_environment import LambdaEnvironment
from aws_embedded_metrics.environment.ec2_environment import EC2Environment
from aws_embedded_metrics.environment.local_environment import LocalEnvironment
from aws_embedded_metrics import config
from typing import Optional

log = logging.getLogger(__name__)

environments = [LambdaEnvironment(), EC2Environment()]
lambda_environment = LambdaEnvironment()
ec2_environment = EC2Environment()
default_environment = DefaultEnvironment()
local_environment = LocalEnvironment()

environments = [lambda_environment, ec2_environment]
Config = config.get_config()


def get_environment_from_override() -> Environment:
if Config.environment == Environments.Agent:
return default_environment
if Config.environment == Environments.EC2:
return ec2_environment
if Config.environment == Environments.Lambda:
return lambda_environment
if Config.environment == Environments.Local:
return local_environment

return default_environment


class EnvironmentCache:
Expand All @@ -32,6 +54,12 @@ async def resolve_environment() -> Environment:
log.debug("Environment resolved from cache.")
return EnvironmentCache.environment

if Config.environment is not Environments.Unknown and Config.environment is not None:
log.info("Environment override provided: %s", Config.environment)
environment_override = get_environment_from_override()
if environment_override is not None:
return environment_override

for env_under_test in environments:
is_environment = False
try:
Expand All @@ -49,5 +77,5 @@ async def resolve_environment() -> Environment:
return env_under_test

log.info("No environment was detected. Using default.")
EnvironmentCache.environment = DefaultEnvironment()
EnvironmentCache.environment = default_environment
return EnvironmentCache.environment
9 changes: 9 additions & 0 deletions aws_embedded_metrics/environment/environments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from enum import Enum


class Environments(Enum):
Local = 1
Lambda = 2
Agent = 3
EC2 = 4
Unknown = -1
4 changes: 2 additions & 2 deletions aws_embedded_metrics/environment/lambda_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from aws_embedded_metrics.environment import Environment
from aws_embedded_metrics.logger.metrics_context import MetricsContext
from aws_embedded_metrics.sinks import Sink
from aws_embedded_metrics.sinks.lambda_sink import LambdaSink
from aws_embedded_metrics.sinks.console_sink import ConsoleSink
import os


Expand All @@ -24,7 +24,7 @@ def get_env(key: str) -> str:
return ""


sink = LambdaSink()
sink = ConsoleSink()


class LambdaEnvironment(Environment):
Expand Down
54 changes: 54 additions & 0 deletions aws_embedded_metrics/environment/local_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright 2019 Amazon.com, Inc. or its affiliates.
# Licensed under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License 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 aws_embedded_metrics.environment import Environment
from aws_embedded_metrics.logger.metrics_context import MetricsContext
from aws_embedded_metrics.sinks import Sink
from aws_embedded_metrics.sinks.console_sink import ConsoleSink
from aws_embedded_metrics import config
import os

Config = config.get_config()


def get_env(key: str) -> str:
if key in os.environ:
return os.environ[key]
return ""


sink = ConsoleSink()


class LocalEnvironment(Environment):
async def probe(self) -> bool:
# probe is not intended to be used in the LocalEnvironment
# To use the local environment you should set the environment
# override
return False

def get_name(self) -> str:
return Config.service_name or "Unknown"

def get_type(self) -> str:
return Config.service_type or "Local"

def get_log_group_name(self) -> str:
return Config.log_group_name or f"{self.get_name()}-metrics"

def configure_context(self, context: MetricsContext) -> None:
pass

def get_sink(self) -> Sink:
"""Create the appropriate sink for this environment."""
return sink
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from aws_embedded_metrics.serializers.log_serializer import LogSerializer


class LambdaSink(Sink):
class ConsoleSink(Sink):
def __init__(self, serializer: Serializer = LogSerializer()):
self.serializer = serializer

Expand All @@ -26,4 +26,4 @@ def accept(self, context: MetricsContext) -> None:

@staticmethod
def name() -> str:
return "LambdaSink"
return "ConsoleSink"
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="aws-embedded-metrics",
version="1.0.1b3",
version="1.0.1b4",
author="Amazon Web Services",
author_email="jarnance@amazon.com",
description="AWS Embedded Metrics Package",
Expand Down
6 changes: 3 additions & 3 deletions tests/environment/test_lambda_environment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from aws_embedded_metrics.environment.lambda_environment import LambdaEnvironment
from aws_embedded_metrics.sinks.lambda_sink import LambdaSink
from aws_embedded_metrics.sinks.console_sink import ConsoleSink
import pytest
from faker import Faker

Expand Down Expand Up @@ -57,12 +57,12 @@ def test_get_log_group_name_returns_function_name():
assert result == expected_name


def test_create_sink_creates_LambdaSink():
def test_create_sink_creates_ConsoleSink():
# arrange
env = LambdaEnvironment()

# act
result = env.get_sink()

# assert
assert isinstance(result, LambdaSink)
assert isinstance(result, ConsoleSink)
4 changes: 2 additions & 2 deletions tests/sinks/test_lambda_sink.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from aws_embedded_metrics.sinks.lambda_sink import LambdaSink
from aws_embedded_metrics.sinks.console_sink import ConsoleSink
from aws_embedded_metrics.logger.metrics_context import MetricsContext


def test_accept_writes_to_stdout(capfd):
# arrange
sink = LambdaSink()
sink = ConsoleSink()
context = MetricsContext.empty()
context.meta["Timestamp"] = 1

Expand Down