1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.coprocessor;
20
21 import com.google.common.collect.ImmutableMap;
22 import java.io.IOException;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.Cell;
28 import org.apache.hadoop.hbase.CoprocessorEnvironment;
29 import org.apache.hadoop.hbase.TableName;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.hbase.client.Delete;
32 import org.apache.hadoop.hbase.client.Durability;
33 import org.apache.hadoop.hbase.client.Get;
34 import org.apache.hadoop.hbase.client.Put;
35 import org.apache.hadoop.hbase.client.Row;
36 import org.apache.hadoop.hbase.ipc.RpcServer;
37 import org.apache.hadoop.hbase.metrics.MetricRegistry;
38 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
39 import org.apache.hadoop.hbase.util.Bytes;
40 import org.apache.hadoop.hbase.util.LossyCounting;
41
42
43
44
45
46
47
48
49
50
51 @InterfaceAudience.Private
52 public class MetaTableMetrics extends BaseRegionObserver {
53
54 private MetricRegistry registry;
55 private LossyCounting<String> clientMetricsLossyCounting, regionMetricsLossyCounting;
56 private boolean active = false;
57 private Set<String> metrics = new HashSet<>();
58
59 enum MetaTableOps {
60 GET, PUT, DELETE,
61 }
62
63 private ImmutableMap<Class<? extends Row>, MetaTableOps> opsNameMap =
64 ImmutableMap.<Class<? extends Row>, MetaTableOps>builder()
65 .put(Put.class, MetaTableOps.PUT)
66 .put(Get.class, MetaTableOps.GET)
67 .put(Delete.class, MetaTableOps.DELETE)
68 .build();
69
70 @Override
71 public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results)
72 throws IOException {
73 registerAndMarkMetrics(e, get);
74 }
75
76 @Override
77 public void prePut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit,
78 Durability durability) throws IOException {
79 registerAndMarkMetrics(e, put);
80 }
81
82 @Override
83 public void preDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete,
84 WALEdit edit, Durability durability) throws IOException {
85 registerAndMarkMetrics(e, delete);
86 }
87
88 private void registerAndMarkMetrics(ObserverContext<RegionCoprocessorEnvironment> e, Row row) {
89 if (!active || !isMetaTableOp(e)) {
90 return;
91 }
92 tableMetricRegisterAndMark(row);
93 clientMetricRegisterAndMark();
94 regionMetricRegisterAndMark(row);
95 opMetricRegisterAndMark(row);
96 opWithClientMetricRegisterAndMark(row);
97 }
98
99
100
101
102
103
104 private String getTableNameFromOp(Row op) {
105 final String tableRowKey = Bytes.toString(op.getRow());
106 if (tableRowKey.isEmpty()) {
107 return null;
108 }
109 final String[] splits = tableRowKey.split(",");
110 return splits.length > 0 ? splits[0] : null;
111 }
112
113
114
115
116
117
118 private String getRegionIdFromOp(Row op) {
119 final String tableRowKey = Bytes.toString(op.getRow());
120 if (tableRowKey.isEmpty()) {
121 return null;
122 }
123 final String[] splits = tableRowKey.split(",");
124 return splits.length > 2 ? splits[2] : null;
125 }
126
127 private boolean isMetaTableOp(ObserverContext<RegionCoprocessorEnvironment> e) {
128 return TableName.META_TABLE_NAME.equals(e.getEnvironment().getRegionInfo().getTable());
129 }
130
131 private void clientMetricRegisterAndMark() {
132
133 String clientIP = RpcServer.getRemoteIp() != null ? RpcServer.getRemoteIp().toString() : null;
134 if (clientIP == null || clientIP.isEmpty()) {
135 return;
136 }
137
138 String clientRequestMeter = clientRequestMeterName(clientIP);
139 clientMetricsLossyCounting.add(clientRequestMeter);
140 registerAndMarkMeter(clientRequestMeter);
141 }
142
143 private void tableMetricRegisterAndMark(Row op) {
144
145 String tableName = getTableNameFromOp(op);
146 if (tableName == null || tableName.isEmpty()) {
147 return;
148 }
149 String tableRequestMeter = tableMeterName(tableName);
150 registerAndMarkMeter(tableRequestMeter);
151 }
152
153 private void regionMetricRegisterAndMark(Row op) {
154
155 String regionId = getRegionIdFromOp(op);
156 if (regionId == null || regionId.isEmpty()) {
157 return;
158 }
159 String regionRequestMeter = regionMeterName(regionId);
160 regionMetricsLossyCounting.add(regionRequestMeter);
161 registerAndMarkMeter(regionRequestMeter);
162 }
163
164 private void opMetricRegisterAndMark(Row op) {
165
166 String opMeterName = opMeterName(op);
167 if (opMeterName == null || opMeterName.isEmpty()) {
168 return;
169 }
170 registerAndMarkMeter(opMeterName);
171 }
172
173 private void opWithClientMetricRegisterAndMark(Object op) {
174
175 String opWithClientMeterName = opWithClientMeterName(op);
176 if (opWithClientMeterName == null || opWithClientMeterName.isEmpty()) {
177 return;
178 }
179 registerAndMarkMeter(opWithClientMeterName);
180 }
181
182 private void registerAndMarkMeter(String requestMeter) {
183 if (requestMeter.isEmpty()) {
184 return;
185 }
186 if (!registry.get(requestMeter).isPresent()){
187 metrics.add(requestMeter);
188 }
189 registry.meter(requestMeter).mark();
190 }
191
192 private String opWithClientMeterName(Object op) {
193
194 String clientIP = RpcServer.getRemoteIp() != null ? RpcServer.getRemoteIp().toString() : "";
195 if (clientIP.isEmpty()) {
196 return "";
197 }
198 MetaTableOps ops = opsNameMap.get(op.getClass());
199 String opWithClientMeterName = "";
200 switch (ops) {
201 case GET:
202 opWithClientMeterName = String.format("MetaTable_client_%s_get_request", clientIP);
203 break;
204 case PUT:
205 opWithClientMeterName = String.format("MetaTable_client_%s_put_request", clientIP);
206 break;
207 case DELETE:
208 opWithClientMeterName = String.format("MetaTable_client_%s_delete_request", clientIP);
209 break;
210 default:
211 break;
212 }
213 return opWithClientMeterName;
214 }
215
216 private String opMeterName(Object op) {
217 MetaTableOps ops = opsNameMap.get(op.getClass());
218 String opMeterName = "";
219 switch (ops) {
220 case GET:
221 opMeterName = "MetaTable_get_request";
222 break;
223 case PUT:
224 opMeterName = "MetaTable_put_request";
225 break;
226 case DELETE:
227 opMeterName = "MetaTable_delete_request";
228 break;
229 default:
230 break;
231 }
232 return opMeterName;
233 }
234
235 private String tableMeterName(String tableName) {
236
237 return String.format("MetaTable_table_%s_request", tableName);
238 }
239
240 private String clientRequestMeterName(String clientIP) {
241
242 if (clientIP.isEmpty()) {
243 return "";
244 }
245 return String.format("MetaTable_client_%s_lossy_request", clientIP);
246 }
247
248 private String regionMeterName(String regionId) {
249
250 return String.format("MetaTable_region_%s_lossy_request", regionId);
251 }
252
253 @Override
254 public void start(CoprocessorEnvironment env) throws IOException {
255 if (env instanceof RegionCoprocessorEnvironment
256 && ((RegionCoprocessorEnvironment) env).getRegionInfo().getTable() != null
257 && ((RegionCoprocessorEnvironment) env).getRegionInfo().getTable()
258 .equals(TableName.META_TABLE_NAME)) {
259 RegionCoprocessorEnvironment regionCoprocessorEnv = (RegionCoprocessorEnvironment) env;
260 registry = regionCoprocessorEnv.getMetricRegistryForRegionServer();
261 LossyCounting.LossyCountingListener<String> listener =
262 new LossyCounting.LossyCountingListener<String>() {
263 @Override public void sweep(String key) {
264 registry.remove(key);
265 metrics.remove(key);
266 }
267 };
268 final Configuration conf = regionCoprocessorEnv.getConfiguration();
269 clientMetricsLossyCounting = new LossyCounting<>("clientMetaMetrics", conf, listener);
270 regionMetricsLossyCounting = new LossyCounting<>("regionMetaMetrics", conf, listener);
271
272 active = true;
273 }
274 }
275
276 @Override
277 public void stop(CoprocessorEnvironment env) throws IOException {
278
279 for (String metric:metrics){
280 registry.remove(metric);
281 }
282 }
283 }