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

com.xceptance.xlt.engine.DataManagerImpl Maven / Gradle / Ivy

/*
 * Copyright (c) 2005-2022 Xceptance Software Technologies GmbH
 *
 * 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.xceptance.xlt.engine;

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.io.UnsupportedEncodingException;

import com.xceptance.xlt.api.engine.Data;
import com.xceptance.xlt.api.engine.DataManager;
import com.xceptance.xlt.api.engine.EventData;
import com.xceptance.xlt.api.util.XltLogger;
import com.xceptance.xlt.common.XltConstants;
import com.xceptance.xlt.engine.metrics.Metrics;

/**
 * Implementation of interface {@link DataManager}.
 * 
 * @author Jörg Werner (Xceptance Software Technologies GmbH)
 */
public class DataManagerImpl implements DataManager
{
    /**
     * System-dependent line separator.
     */
    private static final String LINE_SEPARATOR = System.lineSeparator();

    /**
     * A mutex object to guard parent directory creation. Necessary since File.mkdirs() is not thread-safe.
     */
    private static final Object mutex = new Object();

    /**
     * Whether or not logging is enabled.
     */
    private boolean loggingEnabled = true;

    /**
     * The beginning of the logging period.
     */
    private long startOfLoggingPeriod = Long.MIN_VALUE;

    /**
     * The end of the logging period.
     */
    private long endOfLoggingPeriod = Long.MAX_VALUE;

    /**
     * The number of logged events.
     */
    private int numberOfEvents;

    /**
     * Logger responsible for logging the statistics to the timer file(s).
     */
    private BufferedWriter logger;

    /**
     * Returns the number of events that have occurred.
     * 
     * @return the number of events
     */
    public int getNumberOfEvents()
    {
        return numberOfEvents;
    }

    /**
     * Back-reference to session using this data manager.
     * 

* Necessary as this data manager might be used by foreign threads (e.g. worker-threads of Grizzly WebSocket * server). */ private final SessionImpl session; /** * Creates a new data manager for the given session. * * @param session * the session that should use this data manager */ protected DataManagerImpl(final SessionImpl session) { this.session = session; } /** * {@inheritDoc} */ @Override public void logEvent(final String eventName, final String message) { final EventData e = new EventData(eventName); e.setTestCaseName(session.getUserName()); e.setMessage(message); logDataRecord(e); } /** * {@inheritDoc} */ @Override public synchronized void logDataRecord(final Data stats) { // update metrics for real-time reporting Metrics.getInstance().updateMetrics(stats); // get the statistics logger final BufferedWriter timerWriter = getTimerLogger(); // no statistics logger configured -> exit here if (timerWriter == null) { return; } // Check whether the data record falls into the logging period. // Take the data record's (start) time as the criterion. final long time = stats.getTime(); if (loggingEnabled && startOfLoggingPeriod <= time && time <= endOfLoggingPeriod) { // write the log line try { timerWriter.write(stats.toCSV().replaceAll("[\n\r]+", " ")); timerWriter.write(LINE_SEPARATOR); timerWriter.flush(); } catch (final IOException ex) { XltLogger.runTimeLogger.error("Failed to write statistics:", ex); } // special handling of events if (stats instanceof EventData) { final EventData event = (EventData) stats; if (XltLogger.runTimeLogger.isWarnEnabled()) { XltLogger.runTimeLogger.warn(String.format("EVENT: %2$s - %1$s - '%3$s'", event.getName(), event.getTestCaseName(), event.getMessage())); } numberOfEvents++; } } } /** * Returns the output logger. The logger is created if necessary. * * @return the logger creating the timer output */ private BufferedWriter getTimerLogger() { // check if logger has already been initialized synchronized (this) { if (logger != null) { return logger; } } // get the appropriate timer file final File file = getTimerFile(); // creation of timer file has failed for any reason -> exit here if (file == null) { return null; } try { logger = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), XltConstants.UTF8_ENCODING)); } catch (UnsupportedEncodingException | FileNotFoundException e) { XltLogger.runTimeLogger.error("Cannot create writer for file: " + file, e); } return logger; } /** * Returns the timer file for the current session. If it does not exist yet, it will be created. * * @return timer file */ File getTimerFile() { // create file handle for new file named 'timers.csv' rooted at the session's result directory final File file = new File(session.getResultsDirectory(), XltConstants.TIMER_FILENAME); try { // mkdirs is not thread-safe synchronized (mutex) { file.getParentFile().mkdirs(); } return file; } catch (final Exception e) { XltLogger.runTimeLogger.error("Cannot create file for output of timer: " + file, e); } return null; } /** * {@inheritDoc} */ @Override public long getStartOfLoggingPeriod() { return startOfLoggingPeriod; } /** * {@inheritDoc} */ @Override public long getEndOfLoggingPeriod() { return endOfLoggingPeriod; } /** * {@inheritDoc} */ @Override public boolean isLoggingEnabled() { return loggingEnabled; } /** * {@inheritDoc} */ @Override public void setStartOfLoggingPeriod(final long time) { startOfLoggingPeriod = time; } /** * {@inheritDoc} */ @Override public void setEndOfLoggingPeriod(final long time) { endOfLoggingPeriod = time; } /** * {@inheritDoc} */ @Override public void setLoggingEnabled(final boolean state) { loggingEnabled = state; } /** * Resets the timer logger. Any subsequent call to {@link #getTimerLogger()} will cause a new timer logger to be * created. */ public synchronized void resetLoggerFile() { logger = null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy