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

com.hazelcast.internal.monitors.PerformanceLog Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
 *
 * 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 com.hazelcast.internal.monitors;

import com.hazelcast.core.Member;
import com.hazelcast.instance.GroupProperties;
import com.hazelcast.instance.HazelcastInstanceImpl;
import com.hazelcast.logging.ILogger;
import com.hazelcast.nio.Address;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;

import static com.hazelcast.instance.GroupProperty.PERFORMANCE_MONITOR_MAX_ROLLED_FILE_COUNT;
import static com.hazelcast.instance.GroupProperty.PERFORMANCE_MONITOR_MAX_ROLLED_FILE_SIZE_MB;
import static com.hazelcast.nio.IOUtil.closeResource;
import static java.lang.Math.round;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;

/**
 * Represents the PerformanceLogFile.
 *
 * Should only be called from the {@link PerformanceMonitor}.
 */
final class PerformanceLog {

    private static final int ONE_MB = 1024 * 1024;
    private static final int INITIAL_CHAR_BUFF_SIZE = 4 * 1024;

    // points to the file where the log content is written to.
    volatile File file;

    private final PerformanceMonitor performanceMonitor;
    private final HazelcastInstanceImpl hazelcastInstance;
    private final ILogger logger;
    private final String pathname;

    private char[] charBuff = new char[INITIAL_CHAR_BUFF_SIZE];
    private int index;
    private BufferedWriter bufferedWriter;
    private int maxRollingFileCount;
    private int maxRollingFileSizeBytes;
    private final PerformanceLogWriter logWriter;
    // calling File.length generates a lot of litter; so we'll track it ourselves.
    private long fileLength;

    PerformanceLog(PerformanceMonitor performanceMonitor) {
        this.performanceMonitor = performanceMonitor;
        this.logWriter = performanceMonitor.singleLine
                ? new SingleLinePerformanceLogWriter()
                : new MultiLinePerformanceLogWriter();
        this.logger = performanceMonitor.nodeEngine.getLogger(PerformanceLog.class);
        this.hazelcastInstance = (HazelcastInstanceImpl) performanceMonitor.nodeEngine.getHazelcastInstance();
        this.pathname = getPathName();

        GroupProperties props = hazelcastInstance.node.getGroupProperties();
        this.maxRollingFileCount = props.getInteger(PERFORMANCE_MONITOR_MAX_ROLLED_FILE_COUNT);
        // we accept a float so it becomes easier to testing to create a small file.
        this.maxRollingFileSizeBytes = round(ONE_MB * props.getFloat(PERFORMANCE_MONITOR_MAX_ROLLED_FILE_SIZE_MB));

        logger.finest("maxRollingFileSizeBytes:" + maxRollingFileSizeBytes + " maxRollingFileCount:" + maxRollingFileCount);
    }

    private String getPathName() {
        Member localMember = hazelcastInstance.getCluster().getLocalMember();
        Address address = localMember.getAddress();
        String addressString = address.getHost().replace(":", "_") + "#" + address.getPort();
        return "performance-" + addressString + "-" + currentTimeMillis() + "-%03d.log";
    }

    public void render(PerformanceMonitorPlugin plugin) {
        try {
            if (file == null) {
                file = new File(format(pathname, index));
                bufferedWriter = newWriter();
                renderStaticPlugins();
            }

            renderPlugin(plugin);

            bufferedWriter.flush();
            if (fileLength >= maxRollingFileSizeBytes) {
                rollover();
            }
        } catch (IOException e) {
            logger.warning("Failed to write to file:" + file.getAbsolutePath(), e);
            file = null;
            closeResource(bufferedWriter);
            bufferedWriter = null;
        } catch (RuntimeException e) {
            logger.warning("Failed to write file: " + file, e);
        }
    }

    private void renderStaticPlugins() throws IOException {
        for (PerformanceMonitorPlugin plugin : performanceMonitor.staticTasks.get()) {
            renderPlugin(plugin);
        }
    }

    private void renderPlugin(PerformanceMonitorPlugin plugin) throws IOException {
        logWriter.write(plugin);
        //bufferedWriter.append()
        int desiredLength = charBuff.length;
        int actualSize = logWriter.length();
        while (desiredLength < actualSize) {
            desiredLength *= 2;
        }

        if (desiredLength != charBuff.length) {
            charBuff = new char[desiredLength];
        }

        logWriter.copyInto(charBuff);
        bufferedWriter.write(charBuff, 0, actualSize);
        fileLength += actualSize;
    }

    private BufferedWriter newWriter() throws FileNotFoundException {
        FileOutputStream fos = new FileOutputStream(file, true);
        CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
        return new BufferedWriter(new OutputStreamWriter(fos, encoder));
    }

    @SuppressFBWarnings({"RV_RETURN_VALUE_IGNORED_BAD_PRACTICE" })
    private void rollover() {
        closeResource(bufferedWriter);
        bufferedWriter = null;
        file = null;
        fileLength = 0;
        index++;

        File file = new File(format(pathname, index - maxRollingFileCount));
        // we don't care if the file was deleted or not.
        file.delete();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy