001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.regionserver.wal;
019
020import java.io.IOException;
021import org.apache.hadoop.fs.Path;
022import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
023import org.apache.hadoop.hbase.TableName;
024import org.apache.hadoop.hbase.wal.WALEdit;
025import org.apache.hadoop.hbase.wal.WALKey;
026import org.apache.hadoop.util.StringUtils;
027import org.apache.yetus.audience.InterfaceAudience;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * Class used to push numbers about the WAL into the metrics subsystem. This will take a single
033 * function call and turn it into multiple manipulations of the hadoop metrics system.
034 */
035@InterfaceAudience.Private
036public class MetricsWAL implements WALActionsListener {
037  private static final Logger LOG = LoggerFactory.getLogger(MetricsWAL.class);
038
039  private final MetricsWALSource source;
040
041  public MetricsWAL() {
042    this(CompatibilitySingletonFactory.getInstance(MetricsWALSource.class));
043  }
044
045  MetricsWAL(MetricsWALSource s) {
046    this.source = s;
047  }
048
049  @Override
050  public void postSync(final long timeInNanos, final int handlerSyncs) {
051    source.incrementSyncTime(timeInNanos / 1000000L);
052  }
053
054  @Override
055  public void postAppend(final long size, final long time, final WALKey logkey,
056    final WALEdit logEdit) throws IOException {
057    TableName tableName = logkey.getTableName();
058    source.incrementAppendCount(tableName);
059    source.incrementAppendTime(time);
060    source.incrementAppendSize(tableName, size);
061    source.incrementWrittenBytes(size);
062
063    if (time > 1000) {
064      source.incrementSlowAppendCount();
065      LOG.warn(String.format("%s took %d ms appending an edit to wal; len~=%s",
066        Thread.currentThread().getName(), time, StringUtils.humanReadableInt(size)));
067    }
068  }
069
070  @Override
071  public void logRollRequested(WALActionsListener.RollRequestReason reason) {
072    source.incrementLogRollRequested();
073    switch (reason) {
074      case ERROR:
075        source.incrementErrorLogRoll();
076        break;
077      case LOW_REPLICATION:
078        source.incrementLowReplicationLogRoll();
079        break;
080      case SIZE:
081        source.incrementSizeLogRoll();
082        break;
083      case SLOW_SYNC:
084        source.incrementSlowSyncLogRoll();
085        break;
086      default:
087        break;
088    }
089  }
090
091  @Override
092  public void postLogRoll(Path oldPath, Path newPath) {
093    // oldPath can be null if this is the first time we created a wal
094    // Also newPath can be equal to oldPath if AbstractFSWAL#replaceWriter fails
095    if (newPath != oldPath) {
096      source.incrementSuccessfulLogRolls();
097    }
098  }
099}