/* * Copyright 2010-2019 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. * A copy of the License is located at * * http://aws.amazon.com/apache2.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. */ package com.amazonaws.metrics; import static com.amazonaws.SDKGlobalConfiguration.DEFAULT_METRICS_SYSTEM_PROPERTY; import com.amazonaws.SDKGlobalConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.auth.PropertiesCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.util.AWSRequestMetrics.Field; import com.amazonaws.util.AWSServiceMetrics; import com.amazonaws.logging.LogFactory; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * Used to control the default AWS SDK metric collection system. *
* The default metric collection of the Java AWS SDK is disabled by default. To * enable it, simply specify the system property * "com.amazonaws.sdk.enableDefaultMetrics" when starting up the JVM. * When the system property is specified, a default metric collector will be * started at the AWS SDK level. The default implementation uploads the * request/response metrics captured to Amazon CloudWatch using AWS credentials * obtained via the {@link DefaultAWSCredentialsProviderChain}. *
* For additional optional attributes that can be specified for the system * property, please read the javadoc of the individual fields of this class for * more details. *
* Instead of via system properties, the default AWS SDK metric collection can * also be enabled programmatically via {@link #enableDefaultMetrics()}. * Similarly, metric collection at the AWS SDK level can be disabled via * {@link #disableMetrics()}. *
* Clients who needs to fully customize the metric collection can implement the * SPI {@link MetricCollector}, and then replace the default AWS SDK * implementation of the collector via * {@link #setMetricCollector(MetricCollector)}. *
* Alternatively, for limited customization of the internal collector * implementation provided by the AWS SDK, one can extend the internal Amazon * CloudWatch metric collector. See the javadoc at * com.amazonaws.metrics.internal.cloudwatch.CloudWatchMetricConfig for more * details. */ @SuppressWarnings("checkstyle:nowhitespacebefore") public enum AwsSdkMetrics { ; /** Constant for default metric namespace. */ public static final String DEFAULT_METRIC_NAMESPACE = "AWSSDK/Java"; private static final int QUEUE_POLL_TIMEOUT_MILLI_MINUMUM = 1000; private static final String MBEAN_OBJECT_NAME = "com.amazonaws.management:type=" + AwsSdkMetrics.class.getSimpleName(); /** * Used to enable the use of a single metric namespace for all levels of SDK * generated CloudWatch metrics such as JVM level, host level, etc. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=useSingleMetricNamespace **/ public static final String USE_SINGLE_METRIC_NAMESPACE = "useSingleMetricNamespace"; /** * Used to exclude the generation of JVM metrics when the AWS SDK default * metrics is enabled. By default, jvm metrics is included. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=excludeJvmMetrics **/ public static final String EXCLUDE_MACHINE_METRICS = "excludeMachineMetrics"; /** * Used to generate per host level metrics when the AWS SDK default metrics * is enabled. By default, per-host level metrics is excluded. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=includePerHostMetrics **/ public static final String INCLUDE_PER_HOST_METRICS = "includePerHostMetrics"; /** * Used to specify an AWS credential property file. By default, the * {@link DefaultAWSCredentialsProviderChain} is used. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties **/ public static final String AWS_CREDENTAIL_PROPERTIES_FILE = "credentialFile"; /** * Used to specify the Amazon CloudWatch region for metrics uploading * purposes. By default, metrics are uploaded to us-east-1. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=cloudwatchRegion=us-west-2 **/ public static final String CLOUDWATCH_REGION = "cloudwatchRegion"; /** * Used to specify the internal in-memory queue size for queuing metrics * data points. The default size is 1,000. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=metricQueueSize=1000 **/ public static final String METRIC_QUEUE_SIZE = "metricQueueSize"; /** * Used to specify the internal queue polling timeout in millisecond. The * default timeout is 1 minute, which is optimal for the default CloudWatch * implementation. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=getQueuePollTimeoutMilli=60000 **/ public static final String QUEUE_POLL_TIMEOUT_MILLI = "getQueuePollTimeoutMilli"; /** * Used to specify a custom metric name space. The default name space is * {@link #DEFAULT_METRIC_NAMESPACE}. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyNameSpace **/ public static final String METRIC_NAME_SPACE = "metricNameSpace"; /** * Used to generate per JVM level metrics when the AWS SDK default metrics * is enabled. By default, JVM level metrics are not generated. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=jvmMetricName=Tomcat1 **/ public static final String JVM_METRIC_NAME = "jvmMetricName"; /** * Used to explicitly specify the host name for metric purposes, instead of * detecting the host name via {@link InetAddress} when the AWS SDK default * metrics is enabled. Specifying the host name also has the side effecting * of enabling per host level metrics. * *
* Example: * -Dcom.amazonaws.sdk.enableDefaultMetrics=hostMetricName=MyHost **/ public static final String HOST_METRIC_NAME = "hostMetricName"; private static final String DEFAULT_METRIC_COLLECTOR_FACTORY = "com.amazonaws.metrics.internal.cloudwatch.DefaultMetricCollectorFactory"; /** * True iff the system property {@link #DEFAULT_METRICS_SYSTEM_PROPERTY} has * been set; false otherwise. */ private static final boolean DEFAULT_METRICS_ENABLED; private static volatile AWSCredentialsProvider credentialProvider; /** * True if machine metrics is to be excluded; false otherwise. */ private static volatile boolean machineMetricsExcluded; /** * True if per-host metrics is to be included; false if per-host metrics is * to be excluded when {@link #hostMetricName} is not specified. In the * absence of {@link #hostMetricName}, the host name will be automatically * detected via {@link InetAddress}. */ private static volatile boolean perHostMetricsIncluded; private static volatile Regions region; private static volatile Integer metricQueueSize; private static volatile Long queuePollTimeoutMilli; private static volatile String metricNameSpace = DEFAULT_METRIC_NAMESPACE; private static volatile String credentialFile; /** * No JVM level metrics is generated if this field is set to null or blank. * Otherwise, the value in this field is used to compose the metric name * space. Example: *
* Caller of this method is responsible for starting the new metric
* collector specified as the input parameter.
*
* @param mc the metric collector to be used by the AWS SDK; or null if no
* metric collection is to be performed at the AWS SDK level.
* @see RequestMetricCollector
* @see RequestMetricCollector#NONE
*/
@SuppressWarnings("checkstyle:hiddenfield")
public static synchronized void setMetricCollector(MetricCollector mc) {
MetricCollector old = AwsSdkMetrics.mc;
AwsSdkMetrics.mc = mc;
if (old != null) {
old.stop();
}
}
/**
* Used to set whether the machine metrics is to be excluded.
*
* @param excludeMachineMetrics true if machine metrics is to be excluded;
* false otherwise.
*/
public static void setMachineMetricsExcluded(boolean excludeMachineMetrics) {
AwsSdkMetrics.machineMetricsExcluded = excludeMachineMetrics;
}
/**
* Used to set whether the per-host metrics is to be included.
*
* @param includePerHostMetrics true if per-host metrics is to be included;
* false otherwise.
*/
public static void setPerHostMetricsIncluded(boolean includePerHostMetrics) {
AwsSdkMetrics.perHostMetricsIncluded = includePerHostMetrics;
}
/**
* @return true if the system property
* {@link SDKGlobalConfiguration#DEFAULT_METRICS_SYSTEM_PROPERTY} has been
* set; false otherwise.
*/
public static boolean isDefaultMetricsEnabled() {
return DEFAULT_METRICS_ENABLED;
}
/**
* @return true if a single metric name space is to be used for all levels
* of SDK generated CloudWatch metrics, including JVM level, host level,
* etc.; false otherwise.
*/
public static boolean isSingleMetricNamespace() {
return singleMetricNamespace;
}
/**
* Used to set whether a single metric name space is to be used for all
* levels of SDK generated CloudWatch metrics, including JVM level, host
* level, etc.
*
* @param singleMetricNamespace true if single metric name is to be used;
* false otherwise.
*/
public static void setSingleMetricNamespace(boolean singleMetricNamespace) {
AwsSdkMetrics.singleMetricNamespace = singleMetricNamespace;
}
/**
* @return true if metrics at the AWS SDK level is enabled; false if
* disabled.
*/
@SuppressWarnings("checkstyle:hiddenfield")
public static boolean isMetricsEnabled() {
MetricCollector mc = AwsSdkMetrics.mc;
return mc != null && mc.isEnabled();
}
/**
* @return true if machine metrics is to be excluded.
*/
public static boolean isMachineMetricExcluded() {
return machineMetricsExcluded;
}
/**
* @return true if the per-host metrics flag has been set; false otherwise.
*/
public static boolean isPerHostMetricIncluded() {
return perHostMetricsIncluded;
}
/**
* @return true if per-host metrics is enabled; false otherwise.
*/
public static boolean isPerHostMetricEnabled() {
if (perHostMetricsIncluded)
return true;
String host = hostMetricName;
host = host == null ? "" : host.trim();
return host.length() > 0;
}
/**
* Starts the default AWS SDK metric collector, but only if no metric
* collector is currently in use at the AWS SDK level.
*
* @return true if the default AWS SDK metric collector has been
* successfully started by this call; false otherwise.
*/
public static synchronized boolean enableDefaultMetrics() {
if (mc == null || !mc.isEnabled()) {
if (dirtyEnabling) {
throw new IllegalStateException("Reentrancy is not allowed");
}
dirtyEnabling = true;
try {
Class> c = Class.forName(DEFAULT_METRIC_COLLECTOR_FACTORY);
MetricCollector.Factory f = (MetricCollector.Factory) c.newInstance();
MetricCollector instance = f.getInstance();
if (instance != null) {
setMetricCollector(instance);
return true;
}
} catch (Exception e) {
LogFactory.getLog(AwsSdkMetrics.class)
.warn("Failed to enable the default metrics", e);
} finally {
dirtyEnabling = false;
}
}
return false;
}
/**
* Convenient method to disable the metric collector at the AWS SDK level.
*/
public static void disableMetrics() {
setMetricCollector(MetricCollector.NONE);
}
/**
* Adds the given metric type to the REGISTRY of predefined metrics to be
* captured at the AWS SDK level.
* @param type the metric type.
* @return true if the set of predefined metric types gets changed as a
* result of the call
*/
public static boolean add(MetricType type) {
return type == null ? false : REGISTRY.addMetricType(type);
}
/**
* Adds the given metric types to the REGISTRY of predefined metrics to be
* captured at the AWS SDK level.
* @param types the collection of metric types.
* @param