Skip to content

Commit 59fc163

Browse files
ankitsinghaljoshelser
authored andcommitted
HBASE-15519 Add per-user metrics with lossy counting
Introducing property hbase.regionserver.user.metrics.enabled(Default:true) to disable user metrics in case it accounts for any performance issues Close #661 Signed-off-by: Josh Elser <elserj@apache.org>
1 parent 14dcf1d commit 59fc163

File tree

16 files changed

+1022
-39
lines changed

16 files changed

+1022
-39
lines changed

hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ public interface MetricsRegionServerSourceFactory {
4444
*/
4545
MetricsRegionSource createRegion(MetricsRegionWrapper wrapper);
4646

47+
/**
48+
* Create a MetricsUserSource from a user
49+
* @return A metrics user source
50+
*/
51+
MetricsUserSource createUser(String shortUserName);
52+
53+
/**
54+
* Return the singleton instance for MetricsUserAggregateSource
55+
* @return A metrics user aggregate source
56+
*/
57+
MetricsUserAggregateSource getUserAggregate();
58+
4759
/**
4860
* Create a MetricsTableSource from a MetricsTableWrapper.
4961
*
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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.hbase.regionserver;
20+
21+
import org.apache.hadoop.hbase.metrics.BaseSource;
22+
import org.apache.yetus.audience.InterfaceAudience;
23+
24+
/**
25+
* This interface will be implemented by a MetricsSource that will export metrics from
26+
* multiple users into the hadoop metrics system.
27+
*/
28+
@InterfaceAudience.Private
29+
public interface MetricsUserAggregateSource extends BaseSource {
30+
31+
/**
32+
* The name of the metrics
33+
*/
34+
static final String METRICS_NAME = "Users";
35+
36+
/**
37+
* The name of the metrics context that metrics will be under.
38+
*/
39+
static final String METRICS_CONTEXT = "regionserver";
40+
41+
/**
42+
* Description
43+
*/
44+
static final String METRICS_DESCRIPTION = "Metrics about users connected to the regionserver";
45+
46+
/**
47+
* The name of the metrics context that metrics will be under in jmx
48+
*/
49+
static final String METRICS_JMX_CONTEXT = "RegionServer,sub=" + METRICS_NAME;
50+
51+
static final String NUM_USERS = "numUsers";
52+
static final String NUMBER_OF_USERS_DESC = "Number of users in the metrics system";
53+
54+
/**
55+
* Returns a MetricsUserSource if already exists, or creates and registers one for this user
56+
* @param user the user name
57+
* @return a metrics user source
58+
*/
59+
MetricsUserSource getOrCreateMetricsUser(String user);
60+
61+
void deregister(MetricsUserSource toRemove);
62+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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.hbase.regionserver;
20+
21+
import org.apache.yetus.audience.InterfaceAudience;
22+
23+
@InterfaceAudience.Private
24+
public interface MetricsUserSource extends Comparable<MetricsUserSource> {
25+
26+
String getUser();
27+
28+
void register();
29+
30+
void deregister();
31+
32+
void updatePut(long t);
33+
34+
void updateDelete(long t);
35+
36+
void updateGet(long t);
37+
38+
void updateIncrement(long t);
39+
40+
void updateAppend(long t);
41+
42+
void updateReplay(long t);
43+
44+
void updateScanTime(long t);
45+
}

hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,27 @@ public class MetricsRegionServerSourceFactoryImpl implements MetricsRegionServer
3030
public static enum FactoryStorage {
3131
INSTANCE;
3232
private Object aggLock = new Object();
33-
private MetricsRegionAggregateSourceImpl aggImpl;
33+
private MetricsRegionAggregateSourceImpl regionAggImpl;
34+
private MetricsUserAggregateSourceImpl userAggImpl;
3435
private MetricsTableAggregateSourceImpl tblAggImpl;
3536
private MetricsHeapMemoryManagerSourceImpl heapMemMngImpl;
3637
}
3738

38-
private synchronized MetricsRegionAggregateSourceImpl getAggregate() {
39+
private synchronized MetricsRegionAggregateSourceImpl getRegionAggregate() {
3940
synchronized (FactoryStorage.INSTANCE.aggLock) {
40-
if (FactoryStorage.INSTANCE.aggImpl == null) {
41-
FactoryStorage.INSTANCE.aggImpl = new MetricsRegionAggregateSourceImpl();
41+
if (FactoryStorage.INSTANCE.regionAggImpl == null) {
42+
FactoryStorage.INSTANCE.regionAggImpl = new MetricsRegionAggregateSourceImpl();
4243
}
43-
return FactoryStorage.INSTANCE.aggImpl;
44+
return FactoryStorage.INSTANCE.regionAggImpl;
45+
}
46+
}
47+
48+
public synchronized MetricsUserAggregateSourceImpl getUserAggregate() {
49+
synchronized (FactoryStorage.INSTANCE.aggLock) {
50+
if (FactoryStorage.INSTANCE.userAggImpl == null) {
51+
FactoryStorage.INSTANCE.userAggImpl = new MetricsUserAggregateSourceImpl();
52+
}
53+
return FactoryStorage.INSTANCE.userAggImpl;
4454
}
4555
}
4656

@@ -72,7 +82,7 @@ public synchronized MetricsRegionServerSource createServer(
7282

7383
@Override
7484
public MetricsRegionSource createRegion(MetricsRegionWrapper wrapper) {
75-
return new MetricsRegionSourceImpl(wrapper, getAggregate());
85+
return new MetricsRegionSourceImpl(wrapper, getRegionAggregate());
7686
}
7787

7888
@Override
@@ -83,4 +93,10 @@ public MetricsTableSource createTable(String table, MetricsTableWrapperAggregate
8393
public MetricsIOSource createIO(MetricsIOWrapper wrapper) {
8494
return new MetricsIOSourceImpl(wrapper);
8595
}
96+
97+
@Override
98+
public org.apache.hadoop.hbase.regionserver.MetricsUserSource createUser(String shortUserName) {
99+
return new org.apache.hadoop.hbase.regionserver.MetricsUserSourceImpl(shortUserName,
100+
getUserAggregate());
101+
}
86102
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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.hbase.regionserver;
20+
21+
import java.util.concurrent.ConcurrentHashMap;
22+
23+
import org.apache.hadoop.hbase.metrics.BaseSourceImpl;
24+
import org.apache.hadoop.metrics2.MetricsCollector;
25+
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
26+
import org.apache.hadoop.metrics2.lib.Interns;
27+
import org.apache.yetus.audience.InterfaceAudience;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
32+
33+
@InterfaceAudience.Private
34+
public class MetricsUserAggregateSourceImpl extends BaseSourceImpl
35+
implements MetricsUserAggregateSource {
36+
37+
private static final Logger LOG = LoggerFactory.getLogger(MetricsUserAggregateSourceImpl.class);
38+
39+
private final ConcurrentHashMap<String, MetricsUserSource> userSources =
40+
new ConcurrentHashMap<String, MetricsUserSource>();
41+
42+
public MetricsUserAggregateSourceImpl() {
43+
this(METRICS_NAME, METRICS_DESCRIPTION, METRICS_CONTEXT, METRICS_JMX_CONTEXT);
44+
}
45+
46+
public MetricsUserAggregateSourceImpl(String metricsName,
47+
String metricsDescription,
48+
String metricsContext,
49+
String metricsJmxContext) {
50+
super(metricsName, metricsDescription, metricsContext, metricsJmxContext);
51+
}
52+
53+
@Override
54+
public MetricsUserSource getOrCreateMetricsUser(String user) {
55+
MetricsUserSource source = userSources.get(user);
56+
if (source != null) {
57+
return source;
58+
}
59+
source = new MetricsUserSourceImpl(user, this);
60+
MetricsUserSource prev = userSources.putIfAbsent(user, source);
61+
62+
if (prev != null) {
63+
return prev;
64+
} else {
65+
// register the new metrics now
66+
register(source);
67+
}
68+
return source;
69+
}
70+
71+
public void register(MetricsUserSource source) {
72+
synchronized (this) {
73+
source.register();
74+
}
75+
}
76+
77+
@Override
78+
public void deregister(MetricsUserSource toRemove) {
79+
try {
80+
synchronized (this) {
81+
MetricsUserSource source = userSources.remove(toRemove.getUser());
82+
if (source != null) {
83+
source.deregister();
84+
}
85+
}
86+
} catch (Exception e) {
87+
// Ignored. If this errors out it means that someone is double
88+
// closing the user source and the user metrics is already nulled out.
89+
LOG.info("Error trying to remove " + toRemove + " from " + getClass().getSimpleName(), e);
90+
}
91+
}
92+
93+
@VisibleForTesting
94+
public ConcurrentHashMap<String, MetricsUserSource> getUserSources() {
95+
return userSources;
96+
}
97+
98+
@Override
99+
public void getMetrics(MetricsCollector collector, boolean all) {
100+
MetricsRecordBuilder mrb = collector.addRecord(metricsName);
101+
102+
if (userSources != null) {
103+
for (MetricsUserSource userMetricSource : userSources.values()) {
104+
if (userMetricSource instanceof MetricsUserSourceImpl) {
105+
((MetricsUserSourceImpl) userMetricSource).snapshot(mrb, all);
106+
}
107+
}
108+
mrb.addGauge(Interns.info(NUM_USERS, NUMBER_OF_USERS_DESC), userSources.size());
109+
metricsRegistry.snapshot(mrb, all);
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)