Skip to content

Commit 231819c

Browse files
committed
HADOOP-16830 + HADOOP-17271: S3A instrumentation
* delete duration now tracked * and split into single/bulk delete calls * delete/rename cost tests updated to match * ...and to work correctly if bulk deletes are disabled. * +moved most of the Statistic names into the hadoop-common constant files, for reuse. * New method IOStatisticsLogging.ioStatisticsToSortedString(); sorts the metrics before printing. Adds cost of creation of and insertion into treemaps, so should be used with care. Used for test reporting. Change-Id: I2c7378e504aa364a39ea7feb50c4c6b538bb1d8f
1 parent 71e8280 commit 231819c

34 files changed

+458
-183
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/impl/FunctionsRaisingIOE.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
/**
2727
* Support for functional programming/lambda-expressions.
28-
* @deprecated use {@code org.apache.hadoop.util.functional} classes
28+
* @deprecated use {@code org.apache.hadoop.util.functional}
2929
*/
3030
@InterfaceAudience.Private
3131
@InterfaceStability.Unstable

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/IOStatisticsLogging.java

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import javax.annotation.Nullable;
2222
import java.util.Map;
23+
import java.util.TreeMap;
2324

2425
import org.slf4j.Logger;
2526
import org.slf4j.LoggerFactory;
@@ -72,11 +73,35 @@ public static String ioStatisticsToString(
7273
@Nullable final IOStatistics statistics) {
7374
if (statistics != null) {
7475
StringBuilder sb = new StringBuilder();
75-
mapToString(sb, "counters", statistics.counters());
76-
mapToString(sb, "gauges", statistics.gauges());
77-
mapToString(sb, "minimums", statistics.minimums());
78-
mapToString(sb, "maximums", statistics.maximums());
79-
mapToString(sb, "means", statistics.meanStatistics());
76+
mapToString(sb, "counters", statistics.counters(), " ");
77+
mapToString(sb, "gauges", statistics.gauges(), " ");
78+
mapToString(sb, "minimums", statistics.minimums(), " ");
79+
mapToString(sb, "maximums", statistics.maximums(), " ");
80+
mapToString(sb, "means", statistics.meanStatistics(), " ");
81+
82+
return sb.toString();
83+
} else {
84+
return "";
85+
}
86+
}
87+
88+
/**
89+
* Convert IOStatistics to a string form, with all the metrics sorted.
90+
* This is more expensive than the simple conversion, so should only
91+
* be used for logging/output where it's known/highly likely that the
92+
* caller wants to see the values. Not for debug logging.
93+
* @param statistics A statistics instance.
94+
* @return string value or the empty string if null
95+
*/
96+
public static String ioStatisticsToSortedString(
97+
@Nullable final IOStatistics statistics) {
98+
if (statistics != null) {
99+
StringBuilder sb = new StringBuilder();
100+
mapToSortedString(sb, "counters", statistics.counters());
101+
mapToSortedString(sb, "\ngauges", statistics.gauges());
102+
mapToSortedString(sb, "\nminimums", statistics.minimums());
103+
mapToSortedString(sb, "\nmaximums", statistics.maximums());
104+
mapToSortedString(sb, "\nmeans", statistics.meanStatistics());
80105

81106
return sb.toString();
82107
} else {
@@ -86,26 +111,59 @@ public static String ioStatisticsToString(
86111

87112
/**
88113
* Given a map, add its entryset to the string.
114+
* The entries are only sorted if the source entryset
115+
* iterator is sorted, such as from a TreeMap.
89116
* @param sb string buffer to append to
90117
* @param type type (for output)
91118
* @param map map to evaluate
119+
* @param separator separator
92120
* @param <E> type of values of the map
93121
*/
94122
private static <E> void mapToString(StringBuilder sb,
95123
final String type,
96-
final Map<String, E> map) {
124+
final Map<String, E> map,
125+
final String separator) {
97126
int count = 0;
98127
sb.append(type);
99128
sb.append("=(");
100129
for (Map.Entry<String, E> entry : map.entrySet()) {
101130
if (count > 0) {
102-
sb.append(' ');
131+
sb.append(separator);
103132
}
104133
count++;
105134
sb.append(IOStatisticsBinding.entryToString(
106135
entry.getKey(), entry.getValue()));
107136
}
108-
sb.append("); ");
137+
sb.append(");\n");
138+
}
139+
140+
/**
141+
* Given a map, produce a string with all the values, sorted.
142+
* Needs to create a treemap and insert all the entries.
143+
* @param sb string buffer to append to
144+
* @param type type (for output)
145+
* @param map map to evaluate
146+
* @param <E> type of values of the map
147+
*/
148+
private static <E> void mapToSortedString(StringBuilder sb,
149+
final String type,
150+
final Map<String, E> map) {
151+
mapToString(sb, type, sortedMap(map), "\n");
152+
}
153+
154+
/**
155+
* Create a sorted (tree) map from an unsorted map.
156+
* This incurs the cost of creating a map and that
157+
* of inserting every object into the tree.
158+
* @param source source map
159+
* @param <E> value type
160+
* @return a treemap with all the entries.
161+
*/
162+
private static <E> Map<String, E> sortedMap(
163+
final Map<String, E> source) {
164+
Map<String, E> tm = new TreeMap<>();
165+
tm.putAll(source);
166+
return tm;
109167
}
110168

111169
/**

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/MeanStatistic.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ public MeanStatistic copy() {
278278

279279
@Override
280280
public String toString() {
281-
return String.format("(sum=%d, samples=%d, mean=%.4f)",
282-
sum, samples, mean());
281+
return String.format("(samples=%d, sum=%d, mean=%.4f)",
282+
samples, sum, mean());
283283
}
284284

285285
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/StoreStatisticNames.java

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222
import org.apache.hadoop.classification.InterfaceStability;
2323

2424
/**
25-
* These are common statistic names.
25+
* Common statistic names for object store operations..
2626
* <p>
2727
* When adding new common statistic name constants, please make them unique.
28-
* By convention, they are implicitly unique:
28+
* By convention:
29+
* </p>
2930
* <ul>
3031
* <li>the name of the constants are uppercase, words separated by
3132
* underscores.</li>
@@ -160,13 +161,28 @@ public final class StoreStatisticNames {
160161
public static final String OBJECT_CONTINUE_LIST_REQUEST =
161162
"object_continue_list_request";
162163

164+
/**
165+
* A bulk DELETE request was made: {@value}.
166+
* A separate statistic from {@link #OBJECT_DELETE_REQUEST}
167+
* so that metrics on duration of the operations can
168+
* be distinguished.
169+
*/
170+
public static final String OBJECT_BULK_DELETE_REQUEST
171+
= "object_bulk_delete_request";
172+
163173
/**
164174
* A store's equivalent of a DELETE request was made: {@value}.
165175
* This may be an HTTP DELETE verb, or it may be some custom
166176
* operation which takes a list of objects to delete.
167177
*/
168-
public static final String OP_HTTP_DELETE_REQUEST
169-
= "op_http_delete_request";
178+
public static final String OBJECT_DELETE_REQUEST
179+
= "object_delete_request";
180+
181+
/**
182+
* The count of objects deleted in delete requests
183+
*/
184+
public static final String OBJECT_DELETE_OBJECTS
185+
= "object_delete_objects";
170186

171187
/**
172188
* Object multipart upload initiated.
@@ -285,6 +301,36 @@ public final class StoreStatisticNames {
285301
public static final String OBJECT_METADATA_REQUESTS
286302
= "object_metadata_request";
287303

304+
public static final String OBJECT_COPY_REQUESTS
305+
= "object_copy_requests";
306+
307+
public static final String STORE_IO_THROTTLE_RATE
308+
= "store_io_throttle_rate";
309+
310+
public static final String DELEGATION_TOKEN_ISSUED
311+
= "delegation_token_issued";
312+
313+
public static final String MULTIPART_UPLOAD_INSTANTIATED
314+
= "multipart_instantiated";
315+
316+
public static final String MULTIPART_UPLOAD_PART_PUT
317+
= "multipart_upload_part_put";
318+
319+
public static final String MULTIPART_UPLOAD_PART_PUT_BYTES
320+
= "multipart_upload_part_put_bytes";
321+
322+
public static final String MULTIPART_UPLOAD_ABORTED
323+
= "multipart_upload_aborted";
324+
325+
public static final String MULTIPART_UPLOAD_ABORT_UNDER_PATH_INVOKED
326+
= "multipart_upload_abort_under_path_invoked";
327+
328+
public static final String MULTIPART_UPLOAD_COMPLETED
329+
= "multipart_upload_completed";
330+
331+
public static final String MULTIPART_UPLOAD_STARTED
332+
= "multipart_upload_started";
333+
288334
private StoreStatisticNames() {
289335
}
290336

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/StreamStatisticNames.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ public final class StreamStatisticNames {
283283
public static final String STREAM_WRITE_QUEUE_DURATION
284284
= "stream_write_queue_duration";
285285

286+
public static final String STREAM_WRITE_TOTAL_DATA
287+
= "stream_write_total_data";
288+
286289
private StreamStatisticNames() {
287290
}
288291

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/impl/IOStatisticsStoreImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,16 @@ private void setAtomicLong(final AtomicLong aLong, final long value) {
154154
* increment an atomic long and return its value;
155155
* null long is no-op returning 0.
156156
* @param aLong atomic long; may be null
157-
* @param increment amount to increment; -ve for a decrement
157+
* param increment amount to increment; negative for a decrement
158158
* @return final value or 0 if the long is null
159159
*/
160160
private long incAtomicLong(final AtomicLong aLong,
161161
final long increment) {
162162
if (aLong != null) {
163-
return aLong.addAndGet(increment);
163+
// optimization: zero is a get rather than addAndGet()
164+
return increment != 0
165+
? aLong.addAndGet(increment)
166+
: aLong.get();
164167
} else {
165168
return 0;
166169
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/statistics/impl/StatisticDurationTracker.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public StatisticDurationTracker(
6767
* of the key name is updated.
6868
* @param iostats statistics to update
6969
* @param key Key to use as prefix of values.
70-
* @param count #of times to increment the matching counter.
70+
* @param count #of times to increment the matching counter.
7171
*/
7272
public StatisticDurationTracker(
7373
final IOStatisticsStore iostats,
@@ -87,6 +87,10 @@ public void failed() {
8787

8888
/**
8989
* Set the finished time and then update the statistics.
90+
* If the operation failed then the key + .failures counter will be
91+
* incremented by one.
92+
* The operation min/mean/max values will be updated with the duration;
93+
* on a failure these will all be the .failures metrics.
9094
*/
9195
@Override
9296
public void close() {

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/InconsistentS3ClientFactory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public class InconsistentS3ClientFactory extends DefaultS3ClientFactory {
4141
* Logs a warning that this is being done.
4242
* @param credentials credentials to use
4343
* @param awsConf AWS configuration
44-
* @param metrics
45-
* @param endpoint
46-
* @param pathStyleAccess
44+
* @param metrics metric collector
45+
* @param endpoint AWS endpoint
46+
* @param pathStyleAccess should path style access be supported?
4747
* @return an inconsistent client.
4848
*/
4949
@Override

0 commit comments

Comments
 (0)