Skip to content

Commit 1714589

Browse files
Mehakmeet Singhsteveloughran
authored andcommitted
HADOOP-17016. Adding Common Counters in ABFS (#1991).
Contributed by: Mehakmeet Singh. Change-Id: Ib84e7a42f28e064df4c6204fcce33e573360bf42
1 parent 8a642ca commit 1714589

File tree

7 files changed

+838
-8
lines changed

7 files changed

+838
-8
lines changed
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs.azurebfs;
20+
21+
import java.net.URI;
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.UUID;
25+
26+
import com.google.common.annotations.VisibleForTesting;
27+
28+
import org.apache.hadoop.fs.azurebfs.services.AbfsCounters;
29+
import org.apache.hadoop.metrics2.AbstractMetric;
30+
import org.apache.hadoop.metrics2.MetricStringBuilder;
31+
import org.apache.hadoop.metrics2.MetricsCollector;
32+
import org.apache.hadoop.metrics2.MetricsInfo;
33+
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
34+
import org.apache.hadoop.metrics2.MetricsTag;
35+
import org.apache.hadoop.metrics2.lib.MetricsRegistry;
36+
import org.apache.hadoop.metrics2.lib.MutableCounterLong;
37+
import org.apache.hadoop.metrics2.lib.MutableMetric;
38+
39+
import static org.apache.hadoop.fs.azurebfs.AbfsStatistic.*;
40+
41+
/**
42+
* Instrumentation of Abfs counters.
43+
*/
44+
public class AbfsInstrumentation implements AbfsCounters {
45+
46+
/**
47+
* Single context for all the Abfs counters to separate them from other
48+
* counters.
49+
*/
50+
private static final String CONTEXT = "AbfsContext";
51+
/**
52+
* The name of a field added to metrics records that uniquely identifies a
53+
* specific FileSystem instance.
54+
*/
55+
private static final String REGISTRY_ID = "AbfsID";
56+
/**
57+
* The name of a field added to metrics records that indicates the hostname
58+
* portion of the FS URL.
59+
*/
60+
private static final String METRIC_BUCKET = "AbfsBucket";
61+
62+
private final MetricsRegistry registry =
63+
new MetricsRegistry("abfsMetrics").setContext(CONTEXT);
64+
65+
private static final AbfsStatistic[] STATISTIC_LIST = {
66+
CALL_CREATE,
67+
CALL_OPEN,
68+
CALL_GET_FILE_STATUS,
69+
CALL_APPEND,
70+
CALL_CREATE_NON_RECURSIVE,
71+
CALL_DELETE,
72+
CALL_EXIST,
73+
CALL_GET_DELEGATION_TOKEN,
74+
CALL_LIST_STATUS,
75+
CALL_MKDIRS,
76+
CALL_RENAME,
77+
DIRECTORIES_CREATED,
78+
DIRECTORIES_DELETED,
79+
FILES_CREATED,
80+
FILES_DELETED,
81+
ERROR_IGNORED
82+
};
83+
84+
public AbfsInstrumentation(URI uri) {
85+
UUID fileSystemInstanceId = UUID.randomUUID();
86+
registry.tag(REGISTRY_ID,
87+
"A unique identifier for the instance",
88+
fileSystemInstanceId.toString());
89+
registry.tag(METRIC_BUCKET, "Hostname from the FS URL", uri.getHost());
90+
91+
for (AbfsStatistic stats : STATISTIC_LIST) {
92+
createCounter(stats);
93+
}
94+
}
95+
96+
/**
97+
* Look up a Metric from registered set.
98+
*
99+
* @param name name of metric.
100+
* @return the metric or null.
101+
*/
102+
private MutableMetric lookupMetric(String name) {
103+
return getRegistry().get(name);
104+
}
105+
106+
/**
107+
* Look up counter by name.
108+
*
109+
* @param name name of counter.
110+
* @return counter if found, else null.
111+
*/
112+
private MutableCounterLong lookupCounter(String name) {
113+
MutableMetric metric = lookupMetric(name);
114+
if (metric == null) {
115+
return null;
116+
}
117+
if (!(metric instanceof MutableCounterLong)) {
118+
throw new IllegalStateException("Metric " + name
119+
+ " is not a MutableCounterLong: " + metric);
120+
}
121+
return (MutableCounterLong) metric;
122+
}
123+
124+
/**
125+
* Create a counter in the registry.
126+
*
127+
* @param stats AbfsStatistic whose counter needs to be made.
128+
* @return counter or null.
129+
*/
130+
private MutableCounterLong createCounter(AbfsStatistic stats) {
131+
return registry.newCounter(stats.getStatName(),
132+
stats.getStatDescription(), 0L);
133+
}
134+
135+
/**
136+
* {@inheritDoc}
137+
*
138+
* Increment a statistic with some value.
139+
*
140+
* @param statistic AbfsStatistic need to be incremented.
141+
* @param value long value to be incremented by.
142+
*/
143+
@Override
144+
public void incrementCounter(AbfsStatistic statistic, long value) {
145+
MutableCounterLong counter = lookupCounter(statistic.getStatName());
146+
if (counter != null) {
147+
counter.incr(value);
148+
}
149+
}
150+
151+
/**
152+
* Getter for MetricRegistry.
153+
*
154+
* @return MetricRegistry or null.
155+
*/
156+
private MetricsRegistry getRegistry() {
157+
return registry;
158+
}
159+
160+
/**
161+
* {@inheritDoc}
162+
*
163+
* Method to aggregate all the counters in the MetricRegistry and form a
164+
* string with prefix, separator and suffix.
165+
*
166+
* @param prefix string that would be before metric.
167+
* @param separator string that would be between metric name and value.
168+
* @param suffix string that would be after metric value.
169+
* @param all gets all the values even if unchanged.
170+
* @return a String with all the metrics and their values.
171+
*/
172+
@Override
173+
public String formString(String prefix, String separator, String suffix,
174+
boolean all) {
175+
176+
MetricStringBuilder metricStringBuilder = new MetricStringBuilder(null,
177+
prefix, separator, suffix);
178+
registry.snapshot(metricStringBuilder, all);
179+
return metricStringBuilder.toString();
180+
}
181+
182+
/**
183+
* {@inheritDoc}
184+
*
185+
* Creating a map of all the counters for testing.
186+
*
187+
* @return a map of the metrics.
188+
*/
189+
@VisibleForTesting
190+
@Override
191+
public Map<String, Long> toMap() {
192+
MetricsToMap metricBuilder = new MetricsToMap(null);
193+
registry.snapshot(metricBuilder, true);
194+
return metricBuilder.getMap();
195+
}
196+
197+
protected static class MetricsToMap extends MetricsRecordBuilder {
198+
private final MetricsCollector parent;
199+
private final Map<String, Long> map =
200+
new HashMap<>();
201+
202+
MetricsToMap(MetricsCollector parent) {
203+
this.parent = parent;
204+
}
205+
206+
@Override
207+
public MetricsRecordBuilder tag(MetricsInfo info, String value) {
208+
return this;
209+
}
210+
211+
@Override
212+
public MetricsRecordBuilder add(MetricsTag tag) {
213+
return this;
214+
}
215+
216+
@Override
217+
public MetricsRecordBuilder add(AbstractMetric metric) {
218+
return this;
219+
}
220+
221+
@Override
222+
public MetricsRecordBuilder setContext(String value) {
223+
return this;
224+
}
225+
226+
@Override
227+
public MetricsRecordBuilder addCounter(MetricsInfo info, int value) {
228+
return tuple(info, value);
229+
}
230+
231+
@Override
232+
public MetricsRecordBuilder addCounter(MetricsInfo info, long value) {
233+
return tuple(info, value);
234+
}
235+
236+
@Override
237+
public MetricsRecordBuilder addGauge(MetricsInfo info, int value) {
238+
return tuple(info, value);
239+
}
240+
241+
@Override
242+
public MetricsRecordBuilder addGauge(MetricsInfo info, long value) {
243+
return tuple(info, value);
244+
}
245+
246+
public MetricsToMap tuple(MetricsInfo info, long value) {
247+
return tuple(info.name(), value);
248+
}
249+
250+
public MetricsToMap tuple(String name, long value) {
251+
map.put(name, value);
252+
return this;
253+
}
254+
255+
@Override
256+
public MetricsRecordBuilder addGauge(MetricsInfo info, float value) {
257+
return tuple(info, (long) value);
258+
}
259+
260+
@Override
261+
public MetricsRecordBuilder addGauge(MetricsInfo info, double value) {
262+
return tuple(info, (long) value);
263+
}
264+
265+
@Override
266+
public MetricsCollector parent() {
267+
return parent;
268+
}
269+
270+
/**
271+
* Get the map.
272+
*
273+
* @return the map of metrics.
274+
*/
275+
public Map<String, Long> getMap() {
276+
return map;
277+
}
278+
}
279+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs.azurebfs;
20+
21+
import org.apache.hadoop.fs.StorageStatistics.CommonStatisticNames;
22+
23+
/**
24+
* Statistic which are collected in Abfs.
25+
* Available as metrics in {@link AbfsInstrumentation}.
26+
*/
27+
public enum AbfsStatistic {
28+
29+
CALL_CREATE(CommonStatisticNames.OP_CREATE,
30+
"Calls of create()."),
31+
CALL_OPEN(CommonStatisticNames.OP_OPEN,
32+
"Calls of open()."),
33+
CALL_GET_FILE_STATUS(CommonStatisticNames.OP_GET_FILE_STATUS,
34+
"Calls of getFileStatus()."),
35+
CALL_APPEND(CommonStatisticNames.OP_APPEND,
36+
"Calls of append()."),
37+
CALL_CREATE_NON_RECURSIVE(CommonStatisticNames.OP_CREATE_NON_RECURSIVE,
38+
"Calls of createNonRecursive()."),
39+
CALL_DELETE(CommonStatisticNames.OP_DELETE,
40+
"Calls of delete()."),
41+
CALL_EXIST(CommonStatisticNames.OP_EXISTS,
42+
"Calls of exist()."),
43+
CALL_GET_DELEGATION_TOKEN(CommonStatisticNames.OP_GET_DELEGATION_TOKEN,
44+
"Calls of getDelegationToken()."),
45+
CALL_LIST_STATUS(CommonStatisticNames.OP_LIST_STATUS,
46+
"Calls of listStatus()."),
47+
CALL_MKDIRS(CommonStatisticNames.OP_MKDIRS,
48+
"Calls of mkdirs()."),
49+
CALL_RENAME(CommonStatisticNames.OP_RENAME,
50+
"Calls of rename()."),
51+
DIRECTORIES_CREATED("directories_created",
52+
"Total number of directories created through the object store."),
53+
DIRECTORIES_DELETED("directories_deleted",
54+
"Total number of directories deleted through the object store."),
55+
FILES_CREATED("files_created",
56+
"Total number of files created through the object store."),
57+
FILES_DELETED("files_deleted",
58+
"Total number of files deleted from the object store."),
59+
ERROR_IGNORED("error_ignored",
60+
"Errors caught and ignored.");
61+
62+
private String statName;
63+
private String statDescription;
64+
65+
/**
66+
* Constructor of AbfsStatistic to set statistic name and description.
67+
*
68+
* @param statName Name of the statistic.
69+
* @param statDescription Description of the statistic.
70+
*/
71+
AbfsStatistic(String statName, String statDescription) {
72+
this.statName = statName;
73+
this.statDescription = statDescription;
74+
}
75+
76+
/**
77+
* Getter for statistic name.
78+
*
79+
* @return Name of statistic.
80+
*/
81+
public String getStatName() {
82+
return statName;
83+
}
84+
85+
/**
86+
* Getter for statistic description.
87+
*
88+
* @return Description of statistic.
89+
*/
90+
public String getStatDescription() {
91+
return statDescription;
92+
}
93+
}

0 commit comments

Comments
 (0)