Ejemplo n.º 1
0
    def serialize(context: MetricsContext) -> List[str]:
        config = get_config()

        dimension_keys = []
        dimensions_properties: Dict[str, str] = {}

        for dimension_set in context.get_dimensions():
            keys = list(dimension_set.keys())
            dimension_keys.append(keys[0:MAX_DIMENSIONS])
            dimensions_properties = {**dimensions_properties, **dimension_set}

        def create_body() -> Dict[str, Any]:
            body: Dict[str, Any] = {
                **dimensions_properties,
                **context.properties,
            }
            if not config.disable_metric_extraction:
                body["_aws"] = {
                    **context.meta,
                    "CloudWatchMetrics": [
                        {
                            "Dimensions": dimension_keys,
                            "Metrics": [],
                            "Namespace": context.namespace,
                        },
                    ],
                }
            return body

        current_body: Dict[str, Any] = create_body()
        event_batches: List[str] = []
        num_metrics_in_current_body = 0

        for metric_name, metric in context.metrics.items():

            if len(metric.values) == 1:
                current_body[metric_name] = metric.values[0]
            else:
                current_body[metric_name] = metric.values

            if not config.disable_metric_extraction:
                current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"].append(
                    {
                        "Name": metric_name,
                        "Unit": metric.unit
                    })

            num_metrics_in_current_body += 1

            should_serialize: bool = num_metrics_in_current_body == MAX_METRICS_PER_EVENT
            if should_serialize:
                event_batches.append(json.dumps(current_body))
                current_body = create_body()
                num_metrics_in_current_body = 0

        if not event_batches or num_metrics_in_current_body > 0:
            event_batches.append(json.dumps(current_body))

        return event_batches
    def __init__(
        self,
        namespace: str = None,
        properties: Dict[str, Any] = None,
        dimensions: List[Dict[str, str]] = None,
        default_dimensions: Dict[str, str] = None,
    ):

        self.namespace: str = namespace or get_config(
        ).namespace or constants.DEFAULT_NAMESPACE
        self.properties: Dict[str, Any] = properties or {}
        self.dimensions: List[Dict[str, str]] = dimensions or []
        self.default_dimensions: Dict[str, str] = default_dimensions or {}
        self.metrics: Dict[str, Metric] = {}
        self.should_use_default_dimensions = True
        self.meta: Dict[str, Any] = {"Timestamp": utils.now()}
def test_serialize_metrics_with_aggregation_disabled():
    """Test log records don't contain metadata when aggregation is disabled."""
    # arrange
    config = get_config()
    config.disable_metric_extraction = True

    expected_key = fake.word()
    expected_value = fake.random.randrange(0, 100)

    expected = {expected_key: expected_value}

    context = get_context()
    context.put_metric(expected_key, expected_value)

    # act
    result_json = serializer.serialize(context)[0]

    # assert
    assert_json_equality(result_json, expected)
Ejemplo n.º 4
0
#
#     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.config import get_config

from typing import Any, Awaitable, Callable, Dict

Config = get_config()


class MetricsLogger:
    def __init__(
        self,
        resolve_environment: Callable[..., Awaitable[Environment]],
        context: MetricsContext = None,
    ):
        self.resolve_environment = resolve_environment
        self.context: MetricsContext = context or MetricsContext.empty()

    async def flush(self) -> None:
        # resolve the environment and get the sink
        # MOST of the time this will run synchonrously
        # This only runs asynchronously if executing for the
Ejemplo n.º 5
0
def get_config():
    # reload the configuration module since it is loaded on
    # startup and cached
    reload(config)
    return config.get_config()
Ejemplo n.º 6
0
import logging
from aws_embedded_metrics import config
from aws_embedded_metrics.environment import Environment
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 typing import Optional

log = logging.getLogger(__name__)

lambda_environment = LambdaEnvironment()
ec2_environment = EC2Environment()
default_environment = DefaultEnvironment()
environments = [lambda_environment, ec2_environment]
Config = config.get_config()


class EnvironmentCache:
    environment: Optional[Environment] = None


async def resolve_environment() -> Environment:
    if EnvironmentCache.environment is not None:
        log.debug("Environment resolved from cache.")
        return EnvironmentCache.environment

    if Config.environment:
        lower_configured_enviroment = Config.environment.lower()
        if lower_configured_enviroment == "lambda":
            EnvironmentCache.environment = lambda_environment
    def serialize(context: MetricsContext) -> List[str]:
        config = get_config()

        dimension_keys = []
        dimensions_properties: Dict[str, str] = {}

        for dimension_set in context.get_dimensions():
            keys = list(dimension_set.keys())
            dimension_keys.append(keys[0:MAX_DIMENSIONS])
            dimensions_properties = {**dimensions_properties, **dimension_set}

        def create_body() -> Dict[str, Any]:
            body: Dict[str, Any] = {
                **dimensions_properties,
                **context.properties,
            }
            if not config.disable_metric_extraction:
                body["_aws"] = {
                    **context.meta,
                    "CloudWatchMetrics": [
                        {
                            "Dimensions": dimension_keys,
                            "Metrics": [],
                            "Namespace": context.namespace,
                        },
                    ],
                }
            return body

        current_body: Dict[str, Any] = {}
        event_batches: List[str] = []
        num_metrics_in_current_body = 0

        # Track if any given metric has data remaining to be serialized
        remaining_data = True

        # Track batch number to know where to slice metric data
        i = 0

        while remaining_data:
            remaining_data = False
            current_body = create_body()

            for metric_name, metric in context.metrics.items():

                if len(metric.values) == 1:
                    current_body[metric_name] = metric.values[0]
                else:
                    # Slice metric data as each batch cannot contain more than
                    # MAX_DATAPOINTS_PER_METRIC entries for a given metric
                    start_index = i * MAX_DATAPOINTS_PER_METRIC
                    end_index = (i + 1) * MAX_DATAPOINTS_PER_METRIC
                    current_body[metric_name] = metric.values[
                        start_index:end_index]

                    # Make sure to consume remaining values if we sliced before the end
                    # of the metric value list
                    if len(metric.values) > end_index:
                        remaining_data = True

                if not config.disable_metric_extraction:
                    current_body["_aws"]["CloudWatchMetrics"][0][
                        "Metrics"].append({
                            "Name": metric_name,
                            "Unit": metric.unit
                        })
                num_metrics_in_current_body += 1

                if (num_metrics_in_current_body == MAX_METRICS_PER_EVENT):
                    event_batches.append(json.dumps(current_body))
                    current_body = create_body()
                    num_metrics_in_current_body = 0

            # iter over missing datapoints
            i += 1
            if not event_batches or num_metrics_in_current_body > 0:
                event_batches.append(json.dumps(current_body))

        return event_batches