Skip to content

Added Statistic Set Aggregation Methods #2

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

Draft
wants to merge 2 commits into
base: MetricsRefactor
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import software.amazon.cloudwatchlogs.emf.exception.InvalidMetricException;
import software.amazon.cloudwatchlogs.emf.exception.InvalidNamespaceException;
import software.amazon.cloudwatchlogs.emf.exception.InvalidTimestampException;
import software.amazon.cloudwatchlogs.emf.model.AggregationType;
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.cloudwatchlogs.emf.model.Metric;
import software.amazon.cloudwatchlogs.emf.model.MetricsContext;
import software.amazon.cloudwatchlogs.emf.model.StorageResolution;
import software.amazon.cloudwatchlogs.emf.model.Unit;
Expand All @@ -45,6 +47,7 @@ public class MetricsLogger {
private MetricsContext context;
private CompletableFuture<Environment> environmentFuture;
private EnvironmentProvider environmentProvider;
@Getter @Setter private volatile AggregationType defaultAggregationType = AggregationType.LIST;
/**
* This lock is used to create an internal sync context for flush() method in multi-threaded
* situations. Flush() acquires write lock, other methods (accessing mutable shared data with
Expand Down Expand Up @@ -191,74 +194,177 @@ public MetricsLogger resetDimensions(boolean useDefault) {
* @param value is the value of the metric
* @param unit is the unit of the metric value
* @param storageResolution is the resolution of the metric
* @param aggregationType is the aggregation type of the metric
* @see <a
* href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics">CloudWatch
* High Resolution Metrics</a>
* @return the current logger
* @throws InvalidMetricException if the metric is invalid
*/
public MetricsLogger putMetric(
String key, double value, Unit unit, StorageResolution storageResolution)
String key,
double value,
Unit unit,
StorageResolution storageResolution,
AggregationType aggregationType)
throws InvalidMetricException {
rwl.readLock().lock();
try {
this.context.putMetric(key, value, unit, storageResolution);
this.context.putMetric(key, value, unit, storageResolution, aggregationType);
return this;
} finally {
rwl.readLock().unlock();
}
}

/**
* Put a metric value. This value will be emitted to CloudWatch Metrics asynchronously and does
* not contribute to your account TPS limits. The value will also be available in your
* CloudWatch Logs
*
* @param key is the name of the metric
* @param value is the value of the metric
* @param storageResolution is the resolution of the metric
* @see <a
* href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics">CloudWatch
* High Resolution Metrics</a>
* @return the current logger
* @throws InvalidMetricException if the metric is invalid
*
* <ul>
* <li>Unit defaults to NONE
* <li>AggregationType defaults to the default AggregationType of this logger
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(String key, double value, StorageResolution storageResolution)
throws InvalidMetricException {
this.putMetric(key, value, Unit.NONE, storageResolution);
this.putMetric(key, value, Unit.NONE, storageResolution, this.defaultAggregationType);
return this;
}

/**
* Put a metric value. This value will be emitted to CloudWatch Metrics asynchronously and does
* not contribute to your account TPS limits. The value will also be available in your
* CloudWatch Logs
*
* @param key is the name of the metric
* @param value is the value of the metric
* @param unit is the unit of the metric value
* @return the current logger
* @throws InvalidMetricException if the metric is invalid
*
* <ul>
* <li>StorageResolution defaults to STANDARD
* <li>AggregationType defaults to the default AggregationType of this logger
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(String key, double value, Unit unit)
throws InvalidMetricException {
this.putMetric(key, value, unit, StorageResolution.STANDARD);
this.putMetric(key, value, unit, StorageResolution.STANDARD, this.defaultAggregationType);
return this;
}

/**
* Put a metric value. This value will be emitted to CloudWatch Metrics asynchronously and does
* not contribute to your account TPS limits. The value will also be available in your
* CloudWatch Logs
*
*
* <ul>
* <li>StorageResolution defaults to STANDARD
* <li>Unit defaults to NONE
* <li>AggregationType defaults to the default AggregationType of this logger
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(String key, double value) throws InvalidMetricException {
this.putMetric(
key, value, Unit.NONE, StorageResolution.STANDARD, this.defaultAggregationType);
return this;
}

/**
*
*
* <ul>
* <li>AggregationType defaults to the default AggregationType of this logger
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(
String key, double value, Unit unit, StorageResolution storageResolution)
throws InvalidMetricException {
this.putMetric(key, value, Unit.NONE, storageResolution, this.defaultAggregationType);
return this;
}

/**
*
*
* <ul>
* <li>StorageResolution defaults to STANDARD
* <li>AggregationType defaults to the default AggregationType of this logger
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(
String key,
double value,
StorageResolution storageResolution,
AggregationType aggregationType)
throws InvalidMetricException {
this.putMetric(key, value, Unit.NONE, storageResolution, aggregationType);
return this;
}

/**
*
*
* <ul>
* <li>StorageResolution defaults to STANDARD
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(
String key, double value, Unit unit, AggregationType aggregationType)
throws InvalidMetricException {
this.putMetric(key, value, unit, StorageResolution.STANDARD, aggregationType);
return this;
}

/**
*
*
* <ul>
* <li>StorageResolution defaults to STANDARD
* <li>Unit defaults to NONE
* </ul>
*
* @see MetricsLogger#putMetric(String key, double value, Unit unit, StorageResolution
* storageResolution, AggregationType aggregationType) putMetric(String key, double value,
* Unit unit, StorageResolution storageResolution, AggregationType aggregationType)
*/
public MetricsLogger putMetric(String key, double value, AggregationType aggregationType)
throws InvalidMetricException {
this.putMetric(key, value, Unit.NONE, StorageResolution.STANDARD, aggregationType);
return this;
}

/**
* Set a metric value, if a metric already has the same key it will be overwitten. This value
* will be emitted to CloudWatch Metrics asynchronously and does not contribute to your account
* TPS limits. The value will also be available in your CloudWatch Logs
*
* @param key the name of the metric
* @param value the value of the metric
* @return the current logger
* @throws InvalidMetricException if the metric is invalid
*/
public MetricsLogger putMetric(String key, double value) throws InvalidMetricException {
this.putMetric(key, value, Unit.NONE, StorageResolution.STANDARD);
return this;
public MetricsLogger setMetric(String key, Metric value) throws InvalidMetricException {
try {
this.context.setMetric(key, value);
return this;
} finally {
rwl.readLock().unlock();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*/

package software.amazon.cloudwatchlogs.emf.model;

public enum AggregationType {
LIST(0),
STATISTIC_SET(1),
UNKNOWN_TO_SDK_VERSION(-1);

private final int value;

AggregationType(final int newValue) {
value = newValue;
}

public int getValue() {
return this.value;
}
}
130 changes: 130 additions & 0 deletions src/main/java/software/amazon/cloudwatchlogs/emf/model/Metric.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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.
*/

package software.amazon.cloudwatchlogs.emf.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.LinkedList;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionFilter;
import software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionSerializer;
import software.amazon.cloudwatchlogs.emf.serializers.UnitDeserializer;
import software.amazon.cloudwatchlogs.emf.serializers.UnitSerializer;

/** Abstract immutable (except for name) class that all Metrics are based on. */
@Getter
public abstract class Metric<V> {
@JsonProperty("Name")
@Setter(AccessLevel.PROTECTED)
@NonNull
protected String name;

@JsonProperty("Unit")
@JsonSerialize(using = UnitSerializer.class)
@JsonDeserialize(using = UnitDeserializer.class)
protected Unit unit = Unit.NONE;

@JsonProperty("StorageResolution")
@JsonInclude(
value = JsonInclude.Include.CUSTOM,
valueFilter =
StorageResolutionFilter.class) // Do not serialize when valueFilter is true
@JsonSerialize(using = StorageResolutionSerializer.class)
protected StorageResolution storageResolution = StorageResolution.STANDARD;

@JsonIgnore @Getter protected V values;

/** @return the values of this metric formatted to be flushed */
protected Object getFormattedValues() {
return this.getValues();
}

/** @return true if the values of this metric are valid, false otherwise. */
public abstract boolean hasValidValues();

/** @return true if the values of this metric are oversized for CloudWatch Logs */
protected abstract boolean isOversized();

/**
* Creates a list of new Metrics based off the values in this metric split in so that they are
* small enough that CWL will not drop the message values
*
* @return a list of metrics based off of the values of this metric that aren't too large for
* CWL
*/
protected abstract LinkedList<Metric> serialize();

public abstract static class MetricBuilder<V, T extends MetricBuilder<V, T>> extends Metric<V> {

protected abstract T getThis();

/**
* Adds a value to the metric.
*
* @param value the value to be added to this metric
*/
abstract T addValue(double value);

/**
* Builds the metric.
*
* @return the built metric
*/
abstract Metric<V> build();

protected T name(@NonNull String name) {
this.name = name;
return getThis();
}

public T unit(Unit unit) {
this.unit = unit;
return getThis();
}

public T storageResolution(StorageResolution storageResolution) {
this.storageResolution = storageResolution;
return getThis();
}

@Override
public boolean hasValidValues() {
return build().hasValidValues();
}

@Override
protected LinkedList<Metric> serialize() {
return build().serialize();
}

@Override
protected Object getFormattedValues() {
return build().getFormattedValues();
}

@Override
protected boolean isOversized() {
return build().isOversized();
}
}
}
Loading