HADOOP-14475 Metrics of S3A don't print out when enabled. Contributed by Younger and Sean Mackrory.

This commit is contained in:
Aaron Fabbri 2017-12-05 11:06:32 -08:00
parent a957f1c60e
commit 6555af81a2
No known key found for this signature in database
GPG Key ID: B2EEFA9E78118A29
4 changed files with 186 additions and 13 deletions

View File

@ -78,6 +78,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
@ -2423,6 +2424,8 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities {
metadataStore.close(); metadataStore.close();
metadataStore = null; metadataStore = null;
} }
IOUtils.closeQuietly(instrumentation);
instrumentation = null;
} }
} }

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.fs.s3a; package org.apache.hadoop.fs.s3a;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -29,8 +30,10 @@ import org.apache.hadoop.metrics2.MetricStringBuilder;
import org.apache.hadoop.metrics2.MetricsCollector; import org.apache.hadoop.metrics2.MetricsCollector;
import org.apache.hadoop.metrics2.MetricsInfo; import org.apache.hadoop.metrics2.MetricsInfo;
import org.apache.hadoop.metrics2.MetricsRecordBuilder; import org.apache.hadoop.metrics2.MetricsRecordBuilder;
import org.apache.hadoop.metrics2.MetricsSource;
import org.apache.hadoop.metrics2.MetricsSystem;
import org.apache.hadoop.metrics2.MetricsTag; import org.apache.hadoop.metrics2.MetricsTag;
import org.apache.hadoop.metrics2.annotation.Metrics; import org.apache.hadoop.metrics2.impl.MetricsSystemImpl;
import org.apache.hadoop.metrics2.lib.Interns; import org.apache.hadoop.metrics2.lib.Interns;
import org.apache.hadoop.metrics2.lib.MetricsRegistry; import org.apache.hadoop.metrics2.lib.MetricsRegistry;
import org.apache.hadoop.metrics2.lib.MutableCounterLong; import org.apache.hadoop.metrics2.lib.MutableCounterLong;
@ -58,16 +61,49 @@ import static org.apache.hadoop.fs.s3a.Statistic.*;
* the operations to increment/query metric values are designed to handle * the operations to increment/query metric values are designed to handle
* lookup failures. * lookup failures.
*/ */
@Metrics(about = "Metrics for S3a", context = "S3AFileSystem")
@InterfaceAudience.Private @InterfaceAudience.Private
@InterfaceStability.Evolving @InterfaceStability.Evolving
public class S3AInstrumentation { public class S3AInstrumentation implements Closeable, MetricsSource {
private static final Logger LOG = LoggerFactory.getLogger( private static final Logger LOG = LoggerFactory.getLogger(
S3AInstrumentation.class); S3AInstrumentation.class);
public static final String CONTEXT = "S3AFileSystem"; private static final String METRICS_SOURCE_BASENAME = "S3AMetrics";
/**
* {@value #METRICS_SYSTEM_NAME} The name of the s3a-specific metrics
* system instance used for s3a metrics.
*/
public static final String METRICS_SYSTEM_NAME = "s3a-file-system";
/**
* {@value #CONTEXT} Currently all s3a metrics are placed in a single
* "context". Distinct contexts may be used in the future.
*/
public static final String CONTEXT = "s3aFileSystem";
/**
* {@value #METRIC_TAG_FILESYSTEM_ID} The name of a field added to metrics
* records that uniquely identifies a specific FileSystem instance.
*/
public static final String METRIC_TAG_FILESYSTEM_ID = "s3aFileSystemId";
/**
* {@value #METRIC_TAG_BUCKET} The name of a field added to metrics records
* that indicates the hostname portion of the FS URL.
*/
public static final String METRIC_TAG_BUCKET = "bucket";
// metricsSystemLock must be used to synchronize modifications to
// metricsSystem and the following counters.
private static Object metricsSystemLock = new Object();
private static MetricsSystem metricsSystem = null;
private static int metricsSourceNameCounter = 0;
private static int metricsSourceActiveCounter = 0;
private String metricsSourceName;
private final MetricsRegistry registry = private final MetricsRegistry registry =
new MetricsRegistry("S3AFileSystem").setContext(CONTEXT); new MetricsRegistry("s3aFileSystem").setContext(CONTEXT);
private final MutableCounterLong streamOpenOperations; private final MutableCounterLong streamOpenOperations;
private final MutableCounterLong streamCloseOperations; private final MutableCounterLong streamCloseOperations;
private final MutableCounterLong streamClosed; private final MutableCounterLong streamClosed;
@ -146,7 +182,6 @@ public class S3AInstrumentation {
STORE_IO_THROTTLED STORE_IO_THROTTLED
}; };
private static final Statistic[] GAUGES_TO_CREATE = { private static final Statistic[] GAUGES_TO_CREATE = {
OBJECT_PUT_REQUESTS_ACTIVE, OBJECT_PUT_REQUESTS_ACTIVE,
OBJECT_PUT_BYTES_PENDING, OBJECT_PUT_BYTES_PENDING,
@ -157,12 +192,10 @@ public class S3AInstrumentation {
public S3AInstrumentation(URI name) { public S3AInstrumentation(URI name) {
UUID fileSystemInstanceId = UUID.randomUUID(); UUID fileSystemInstanceId = UUID.randomUUID();
registry.tag("FileSystemId", registry.tag(METRIC_TAG_FILESYSTEM_ID,
"A unique identifier for the FS ", "A unique identifier for the instance",
fileSystemInstanceId.toString() + "-" + name.getHost()); fileSystemInstanceId.toString());
registry.tag("fsURI", registry.tag(METRIC_TAG_BUCKET, "Hostname from the FS URL", name.getHost());
"URI of this filesystem",
name.toString());
streamOpenOperations = streamCounter(STREAM_OPENED); streamOpenOperations = streamCounter(STREAM_OPENED);
streamCloseOperations = streamCounter(STREAM_CLOSE_OPERATIONS); streamCloseOperations = streamCounter(STREAM_CLOSE_OPERATIONS);
streamClosed = streamCounter(STREAM_CLOSED); streamClosed = streamCounter(STREAM_CLOSED);
@ -204,6 +237,39 @@ public class S3AInstrumentation {
"ops", "latency", interval); "ops", "latency", interval);
quantiles(S3GUARD_METADATASTORE_THROTTLE_RATE, quantiles(S3GUARD_METADATASTORE_THROTTLE_RATE,
"events", "frequency (Hz)", interval); "events", "frequency (Hz)", interval);
registerAsMetricsSource(name);
}
@VisibleForTesting
public MetricsSystem getMetricsSystem() {
synchronized (metricsSystemLock) {
if (metricsSystem == null) {
metricsSystem = new MetricsSystemImpl();
metricsSystem.init(METRICS_SYSTEM_NAME);
}
}
return metricsSystem;
}
/**
* Register this instance as a metrics source.
* @param name s3a:// URI for the associated FileSystem instance
*/
private void registerAsMetricsSource(URI name) {
int number;
synchronized(metricsSystemLock) {
getMetricsSystem();
metricsSourceActiveCounter++;
number = ++metricsSourceNameCounter;
}
String msName = METRICS_SOURCE_BASENAME + number;
if (number > 1) {
msName = msName + number;
}
metricsSourceName = msName + "-" + name.getHost();
metricsSystem.register(metricsSourceName, "", this);
} }
/** /**
@ -560,6 +626,23 @@ public class S3AInstrumentation {
streamBytesDiscardedInAbort.incr(statistics.bytesDiscardedInAbort); streamBytesDiscardedInAbort.incr(statistics.bytesDiscardedInAbort);
} }
@Override
public void getMetrics(MetricsCollector collector, boolean all) {
registry.snapshot(collector.addRecord(registry.info().name()), true);
}
public void close() {
synchronized (metricsSystemLock) {
metricsSystem.unregisterSource(metricsSourceName);
int activeSources = --metricsSourceActiveCounter;
if (activeSources == 0) {
metricsSystem.publishMetricsNow();
metricsSystem.shutdown();
metricsSystem = null;
}
}
}
/** /**
* Statistics updated by an input stream during its actual operation. * Statistics updated by an input stream during its actual operation.
* These counters not thread-safe and are for use in a single instance * These counters not thread-safe and are for use in a single instance

View File

@ -1,4 +1,3 @@
<!--- <!---
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -1599,6 +1598,43 @@ basis.
to set fadvise policies on input streams. Once implemented, to set fadvise policies on input streams. Once implemented,
this will become the supported mechanism used for configuring the input IO policy. this will become the supported mechanism used for configuring the input IO policy.
##<a name="metrics"></a>Metrics
S3A metrics can be monitored through Hadoop's metrics2 framework. S3A creates
its own metrics system called s3a-file-system, and each instance of the client
will create its own metrics source, named with a JVM-unique numerical ID.
As a simple example, the following can be added to `hadoop-metrics2.properties`
to write all S3A metrics to a log file every 10 seconds:
s3a-file-system.sink.my-metrics-config.class=org.apache.hadoop.metrics2.sink.FileSink
s3a-file-system.sink.my-metrics-config.filename=/var/log/hadoop-yarn/s3a-metrics.out
*.period=10
Lines in that file will be structured like the following:
1511208770680 s3aFileSystem.s3aFileSystem: Context=s3aFileSystem, s3aFileSystemId=892b02bb-7b30-4ffe-80ca-3a9935e1d96e, bucket=bucket,
Hostname=hostname-1.hadoop.apache.com, files_created=1, files_copied=2, files_copied_bytes=10000, files_deleted=5, fake_directories_deleted=3,
directories_created=3, directories_deleted=0, ignored_errors=0, op_copy_from_local_file=0, op_exists=0, op_get_file_status=15, op_glob_status=0,
op_is_directory=0, op_is_file=0, op_list_files=0, op_list_located_status=0, op_list_status=3, op_mkdirs=1, op_rename=2, object_copy_requests=0,
object_delete_requests=6, object_list_requests=23, object_continue_list_requests=0, object_metadata_requests=46, object_multipart_aborted=0,
object_put_bytes=0, object_put_requests=4, object_put_requests_completed=4, stream_write_failures=0, stream_write_block_uploads=0,
stream_write_block_uploads_committed=0, stream_write_block_uploads_aborted=0, stream_write_total_time=0, stream_write_total_data=0,
s3guard_metadatastore_put_path_request=10, s3guard_metadatastore_initialization=0, object_put_requests_active=0, object_put_bytes_pending=0,
stream_write_block_uploads_active=0, stream_write_block_uploads_pending=0, stream_write_block_uploads_data_pending=0,
S3guard_metadatastore_put_path_latencyNumOps=0, S3guard_metadatastore_put_path_latency50thPercentileLatency=0,
S3guard_metadatastore_put_path_latency75thPercentileLatency=0, S3guard_metadatastore_put_path_latency90thPercentileLatency=0,
S3guard_metadatastore_put_path_latency95thPercentileLatency=0, S3guard_metadatastore_put_path_latency99thPercentileLatency=0
Depending on other configuration, metrics from other systems, contexts, etc. may
also get recorded, for example the following:
1511208770680 metricssystem.MetricsSystem: Context=metricssystem, Hostname=s3a-metrics-4.gce.cloudera.com, NumActiveSources=1, NumAllSources=1,
NumActiveSinks=1, NumAllSinks=0, Sink_fileNumOps=2, Sink_fileAvgTime=1.0, Sink_fileDropped=0, Sink_fileQsize=0, SnapshotNumOps=5,
SnapshotAvgTime=0.0, PublishNumOps=2, PublishAvgTime=0.0, DroppedPubAll=0
Note that low-level metrics from the AWS SDK itself are not currently included
in these metrics.
##<a name="further_reading"></a> Other Topics ##<a name="further_reading"></a> Other Topics

View File

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.fs.s3a;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.contract.ContractTestUtils;
import org.apache.hadoop.metrics2.lib.MutableCounterLong;
import org.junit.Test;
import java.io.IOException;
/**
* Test s3a performance metrics register and output.
*/
public class ITestS3AMetrics extends AbstractS3ATestBase {
@Test
public void testMetricsRegister()
throws IOException, InterruptedException {
S3AFileSystem fs = getFileSystem();
Path dest = new Path("newfile1");
ContractTestUtils.touch(fs, dest);
String targetMetricSource = "S3AMetrics1" + "-" + fs.getBucket();
assertNotNull("No metrics under test fs for " + targetMetricSource,
fs.getInstrumentation().getMetricsSystem()
.getSource(targetMetricSource));
MutableCounterLong fileCreated =
(MutableCounterLong) fs.getInstrumentation().getRegistry()
.get(Statistic.FILES_CREATED.getSymbol());
assertEquals("Metrics system should report single file created event",
1, fileCreated.value());
}
}