-
Alejandro Lopez Gestoso authoredAlejandro Lopez Gestoso authored
log.h 9.70 KiB
// Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
// Author Sergi Hernandez (shernand@iri.upc.edu)
// All rights reserved.
//
// This file is part of iriutils
// iriutils is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _LOG_H
#define _LOG_H
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <vector>
#include "mutex.h"
#include "ctime.h"
/**
* \brief Implementation of a log file
*
* This class allows easyliy handling log files in a class. The name of the
* file in which to save the user messages is fixed at construction time, and
* the corresponding file created. If a file with the same name already exists,
* it is deleted and a new one is created. The file is opened at construction
* time, and remains this way until the class is destroyed, even if the log is
* disabled.
*
* The message logging for a class can be enabled or disabled at any time. When
* enabled, the user can use the log() function to save messages into the file.
* These messages will each have the time stamp in which they where written. When
* disabled, the log() fnction will do nothing.
*
* The function is_enabled() make it possible to check if the log is enabled or
* not. By default, the ./log/ directory is used to store all the log files. The
* class provides a mutex object in order to avoid data corruption when multiple
* threads try to log messages to this object.
*/
class CLog
{
private:
/**
* \brief Log file structure
*
* This structure hold all the information regarding the file. It is initialized
* when the object is created and associated to the user provided filename. It
* is not possible to modify this structure directly, it will by updated when the
* log() function is used, and destroyed when the corresponding object is
* destroyed.
*/
std::fstream log_file;
/**
* \brief Log filename
*
* This string contains the full name of the log file including the path and
* default extension. It is initialized at construction time with the name
* provided by the user and can not be modified afterwards. It is possible
* to get the full filename using the get_filename() function.
*/
std::string filename;
/**
* \brief Enable flag
*
* Thif flag indicates if the particular log is enabled (true) or not (false).
* Its default value is true, so that when a new object of this class is created,
* it can immediatelly start logging user messages.
*/
bool enabled;
/**
* \brief A mutual exclusion object to properly handle the log file
*
* This object avoid that the messages written to the log file get corrupted due
* to concurrent write operations to a single file from different threads. When a
* thread wants to log a message, it first locks the mutex, then writes the message
* and finally frees the mutex.
*/
CMutex access;
/**
* \brief A time object to create the time stamps
*
* This attribute is used to get the current computer time each time a new log entry
* is created, and also output it in the desired format to be written into the log
* file. This object is initialized each time the log() function is called and can
* not be directlyy accessed by the user.
*/
CTime time_stamp;
public:
/**
* \brief Constructor
*
* This function initializes the file structure and associates it with the filename
* provided by the user. By default, both global and local enables are set to true.
* The values of all the attributes after calling this constructor is as follows:
*
* - log_file: An initialized FILE structure.
* - enable=true.
*
* \param filename a null-terminated string with the name of the log file to be
* created. The memory necessary for this string must be allocated by the calling
* process. The file name must not have any spaces or special character. The
* filename must not have any extension, '.log' is automatically appended.
*
* This function throws a CLogException if there is any error.
*/
CLog(const std::string& filename);
/**
* \brief Function to enable the log
* This function enable the particular log associated with the object. This function
* sets the enable attribute to true. The log file is already created when this
* function is called, and it is not affected by its call.
*
* This function throws an exception if there is any error.
*/
void enable(void);
/**
* \brief Function to disable the log
* This function disables the particular log associated with the object. This function
* sets the enable attribute to false. The log file is already created when this
* function is called, and it is not affected by its call.
*
* This function throws a CLogException if there is any error.
*/
void disable(void);
/**
* \brief Function to check if the log is enabled
*
* This function checks if the message logging for the corresponding object is enabled
* or not.
*
* This function throws a CLogException if there is any error.
*
* \return The state of the local enable, true if the particular log is enabled or false
* otherwise.
*
*/
bool is_enabled(void);
/**
* \brief Function to get the full filename
*
* This function returns the full filename of rthe log file including the path and the
* extension.
*
* This function throws a CLogException if there is any error.
*
* \return A null terminated string with the full filename of the log file.
*
*/
std::string get_filename(void);
/**
* \brief Function to set the time format
*
* This function sets the time format format to be used in each of the log
* entries.
*
* \param format the time format to be used. See the documentation on the
* ctimeformat enummeration type for more information.
*
*/
void set_time_format(ctimeformat format);
/**
* \brief Function to get the time format
*
* This functions returns the current time format used to generate each of the log
* entries in ctimeformat type.
*
* \return the current time format used. See the documentation on the ctimeformat
* enummeration type for more information.
*
*/
ctimeformat get_time_format();
/**
* \brief Function to write a variable to the log
*
* This function writes the user variable to the log file together with the time stamp at
* which the message has been logged. If the global enable is not set, or else, if it is
* set but the local enable is not, this function does nothing. The only way to actually
* log user messages is that both the local and global enables are set.
*
* This function throws a CLogException if there is any error.
*
* \param value any kind of basic C++ data types which provides an overloaded version of
* the << operator (int, double, std::string, etc.). Vectors are not supported
* by this function, use the log_vector() function instead.
*
*/
template<class T>
void log(const T& value)
{
this->access.enter();
this->time_stamp.set();
if (this->is_enabled())
this->log_file << "[" << this->time_stamp.getString() << "] - " << value << std::endl;
this->access.exit();
}
/**
* \brief Function to write a vector of variable to the log
*
* This function writes the user vector to the log file together with the time stamp at
* which the message has been logged. If the global enable is not set, or else, if it is
* set but the local enable is not, this function does nothing. The only way to actually
* log user messages is that both the local and global enables are set.
*
* This function throws a CLogException if there is any error.
*
* \param values a vector of any kind of basic C++ data types which provides an overloaded
* version of the << operator (int, double, std::string, etc.).
*
*/
template<class T>
void log_vector(const std::vector<T>& values)
{
unsigned int i=0;
this->access.enter();
this->time_stamp.set();
if (this->is_enabled())
{
this->log_file << "[" << this->time_stamp.getString() << "] - ";
for(i=0;i<values.size();i++)
{
this->log_file << values[i];
if(i<values.size()-1)
this->log_file << ",";
}
this->log_file << std::endl;
}
this->access.exit();
}
/**
* \brief Destructor
*
* This function closes the log file even if it is locally or globally disabled. All the
* associated memory is freed, but the value of the global enable is not modified
* because there may exist other CLog objects still created.
*
* This function throws a CLogException if there is any error.
*/
~CLog();
};
#endif