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

co.cask.cdap.common.logging.LogFileWriter Maven / Gradle / Ivy

There is a newer version: 5.1.2
Show newest version
/*
 * Copyright © 2014 Cask Data, Inc.
 *
 * Licensed 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 co.cask.cdap.common.logging;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * A LogWriter that writes to file.
 */
public class LogFileWriter implements LogWriter {

  static final Charset CHARSET_UTF8 = Charset.forName("UTF-8");

  LogConfiguration config;
  FileSystem fileSystem;
  private FSDataOutputStream out;

  @Override
  public void configure(LogConfiguration config) throws IOException {
    // remember configuration
    this.config = config;
    // open a file system
    fileSystem = config.getFileSystem();
    // make sure the base path exists in the file system
    createPath(config.getLogFilePath());
    // open the file to write to (create or append)
    openFileForWrite(config.getLogFilePath(), makeFileName(0));
  }

  @Override
  public void log(LogEvent event) throws IOException {
    synchronized (this) {
      // append message to current file
      persistMessage(formatMessage(event));
      // if necessary, rotate the log
      // - check size of current file, if exceeds:
      if (getCurrentFileSize() > config.getSizeThreshold()) {
        // roll the existing log files
        roll();
        // - open a new file
        openFileForWrite(config.getLogFilePath(), makeFileName(0));
      }
    }
  }

  private void roll() throws IOException {
    // close current
    closeFile();
    // delete oldest
    deleteFile(config.getLogFilePath(),
        makeFileName(config.getMaxInstances() - 1));
    // rename all files
    for (int i = config.getMaxInstances() - 1; i > 0; --i) {
      renameFile(config.getLogFilePath(),
          makeFileName(i - 1), makeFileName(i));
    }
  }

  @Override
  public void close() throws IOException {
    closeFile();
  }

  String formatMessage(LogEvent event) {
      return String.format("%s [%s] %s", event.getTag(),
          event.getLevel(), event.getMessage());
  }

  String makeFileName(int instance) {
    if (instance == 0) {
      return config.getLogFileName();
    } else {
      return String.format("%s.%d", config.getLogFileName(), instance);
    }
  }

  void createPath(String path) throws IOException {
    fileSystem.mkdirs(new Path(path));
  }

  void openFileForWrite(String path, String name) throws IOException {
    Path filePath = new Path(path, name);
    if (!fileSystem.exists(filePath)) {
      out = fileSystem.create(filePath);
    } else {
      out = fileSystem.append(filePath);
    }
  }

  void closeFile() throws IOException {
    synchronized (this) {
      if (out != null) {
        out.close();
        out = null;
      }
    }
  }

  void persistMessage(String message) throws IOException {
    synchronized (this) {
      out.write(message.getBytes(CHARSET_UTF8));
      out.write('\n');
      out.hflush();
    }
  }

  @Override
  public long getWritePosition() throws IOException {
    return getCurrentFileSize();
  }

  long getCurrentFileSize() throws IOException {
    return out.getPos();
  }

  void deleteFile(String path, String name) throws IOException {
    if (fileSystem.exists(new Path(path, name))) {
      fileSystem.delete(new Path(path, name), false);
    }
  }

  void renameFile(String path, String oldName, String newName)
      throws IOException {
    Path oldPath = new Path(path, oldName);
    if (!fileSystem.exists(oldPath)) {
      return;
    }
    Path newPath = new Path(path, newName);
    fileSystem.rename(oldPath, newPath);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy