All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hbase.coprocessor.MetaTableMetrics Maven / Gradle / Ivy

There is a newer version: 3.0.0-beta-1
Show newest version
/*
 *
 * 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.hbase.coprocessor;

import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CoprocessorEnvironment;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Durability;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Row;
import org.apache.hadoop.hbase.ipc.RpcServer;
import org.apache.hadoop.hbase.metrics.MetricRegistry;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.LossyCounting;
import org.apache.hadoop.hbase.wal.WALEdit;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;

/**
 * A coprocessor that collects metrics from meta table.
 * 

* These metrics will be available through the regular Hadoop metrics2 sinks (ganglia, opentsdb, * etc) as well as JMX output. *

* @see MetaTableMetrics */ @InterfaceAudience.Private public class MetaTableMetrics implements RegionCoprocessor { private ExampleRegionObserverMeta observer; private MetricRegistry registry; private LossyCounting clientMetricsLossyCounting, regionMetricsLossyCounting; private boolean active = false; private Set metrics = ConcurrentHashMap.newKeySet(); enum MetaTableOps { GET, PUT, DELETE, } private ImmutableMap, MetaTableOps> opsNameMap = ImmutableMap., MetaTableOps>builder() .put(Put.class, MetaTableOps.PUT) .put(Get.class, MetaTableOps.GET) .put(Delete.class, MetaTableOps.DELETE) .build(); class ExampleRegionObserverMeta implements RegionCoprocessor, RegionObserver { @Override public Optional getRegionObserver() { return Optional.of(this); } @Override public void preGetOp(ObserverContext e, Get get, List results) throws IOException { registerAndMarkMetrics(e, get); } @Override public void prePut(ObserverContext e, Put put, WALEdit edit, Durability durability) throws IOException { registerAndMarkMetrics(e, put); } @Override public void preDelete(ObserverContext e, Delete delete, WALEdit edit, Durability durability) { registerAndMarkMetrics(e, delete); } private void registerAndMarkMetrics(ObserverContext e, Row row){ if (!active || !isMetaTableOp(e)) { return; } tableMetricRegisterAndMark(row); clientMetricRegisterAndMark(); regionMetricRegisterAndMark(row); opMetricRegisterAndMark(row); opWithClientMetricRegisterAndMark(row); } /** * Get table name from Ops such as: get, put, delete. * @param op such as get, put or delete. */ private String getTableNameFromOp(Row op) { final String tableRowKey = Bytes.toString(op.getRow()); if (StringUtils.isEmpty(tableRowKey)) { return null; } final String[] splits = tableRowKey.split(","); return splits.length > 0 ? splits[0] : null; } /** * Get regionId from Ops such as: get, put, delete. * @param op such as get, put or delete. */ private String getRegionIdFromOp(Row op) { final String tableRowKey = Bytes.toString(op.getRow()); if (StringUtils.isEmpty(tableRowKey)) { return null; } final String[] splits = tableRowKey.split(","); return splits.length > 2 ? splits[2] : null; } private boolean isMetaTableOp(ObserverContext e) { return TableName.META_TABLE_NAME .equals(e.getEnvironment().getRegionInfo().getTable()); } private void clientMetricRegisterAndMark() { // Mark client metric String clientIP = RpcServer.getRemoteIp() != null ? RpcServer.getRemoteIp().toString() : null; if (clientIP == null || clientIP.isEmpty()) { return; } String clientRequestMeter = clientRequestMeterName(clientIP); clientMetricsLossyCounting.add(clientRequestMeter); registerAndMarkMeter(clientRequestMeter); } private void tableMetricRegisterAndMark(Row op) { // Mark table metric String tableName = getTableNameFromOp(op); if (tableName == null || tableName.isEmpty()) { return; } String tableRequestMeter = tableMeterName(tableName); registerAndMarkMeter(tableRequestMeter); } private void regionMetricRegisterAndMark(Row op) { // Mark region metric String regionId = getRegionIdFromOp(op); if (regionId == null || regionId.isEmpty()) { return; } String regionRequestMeter = regionMeterName(regionId); regionMetricsLossyCounting.add(regionRequestMeter); registerAndMarkMeter(regionRequestMeter); } private void opMetricRegisterAndMark(Row op) { // Mark access type ["get", "put", "delete"] metric String opMeterName = opMeterName(op); if (opMeterName == null || opMeterName.isEmpty()) { return; } registerAndMarkMeter(opMeterName); } private void opWithClientMetricRegisterAndMark(Object op) { // // Mark client + access type metric String opWithClientMeterName = opWithClientMeterName(op); if (opWithClientMeterName == null || opWithClientMeterName.isEmpty()) { return; } registerAndMarkMeter(opWithClientMeterName); } // Helper function to register and mark meter if not present private void registerAndMarkMeter(String requestMeter) { if (requestMeter.isEmpty()) { return; } if(!registry.get(requestMeter).isPresent()){ metrics.add(requestMeter); } registry.meter(requestMeter).mark(); } private String opWithClientMeterName(Object op) { // Extract meter name containing the client IP String clientIP = RpcServer.getRemoteIp() != null ? RpcServer.getRemoteIp().toString() : ""; if (clientIP.isEmpty()) { return ""; } MetaTableOps ops = opsNameMap.get(op.getClass()); String opWithClientMeterName = ""; switch (ops) { case GET: opWithClientMeterName = String.format("MetaTable_client_%s_get_request", clientIP); break; case PUT: opWithClientMeterName = String.format("MetaTable_client_%s_put_request", clientIP); break; case DELETE: opWithClientMeterName = String.format("MetaTable_client_%s_delete_request", clientIP); break; default: break; } return opWithClientMeterName; } private String opMeterName(Object op) { // Extract meter name containing the access type MetaTableOps ops = opsNameMap.get(op.getClass()); String opMeterName = ""; switch (ops) { case GET: opMeterName = "MetaTable_get_request"; break; case PUT: opMeterName = "MetaTable_put_request"; break; case DELETE: opMeterName = "MetaTable_delete_request"; break; default: break; } return opMeterName; } private String tableMeterName(String tableName) { // Extract meter name containing the table name return String.format("MetaTable_table_%s_request", tableName); } private String clientRequestMeterName(String clientIP) { // Extract meter name containing the client IP if (clientIP.isEmpty()) { return ""; } return String.format("MetaTable_client_%s_lossy_request", clientIP); } private String regionMeterName(String regionId) { // Extract meter name containing the region ID return String.format("MetaTable_region_%s_lossy_request", regionId); } } @Override public Optional getRegionObserver() { return Optional.of(observer); } @Override public void start(CoprocessorEnvironment env) throws IOException { observer = new ExampleRegionObserverMeta(); if (env instanceof RegionCoprocessorEnvironment && ((RegionCoprocessorEnvironment) env).getRegionInfo().getTable() != null && ((RegionCoprocessorEnvironment) env).getRegionInfo().getTable() .equals(TableName.META_TABLE_NAME)) { RegionCoprocessorEnvironment regionCoprocessorEnv = (RegionCoprocessorEnvironment) env; registry = regionCoprocessorEnv.getMetricRegistryForRegionServer(); LossyCounting.LossyCountingListener listener = key -> { registry.remove(key); metrics.remove(key); }; final Configuration conf = regionCoprocessorEnv.getConfiguration(); clientMetricsLossyCounting = new LossyCounting("clientMetaMetrics", conf, listener); regionMetricsLossyCounting = new LossyCounting("regionMetaMetrics", conf, listener); // only be active mode when this region holds meta table. active = true; } } @Override public void stop(CoprocessorEnvironment env) throws IOException { // since meta region can move around, clear stale metrics when stop. for(String metric:metrics){ registry.remove(metric); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy