Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/output/LogWriter.cc @ 12073

Last change on this file since 12073 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 6.3 KB
RevLine 
[8774]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
[8848]29/**
30    @file
31    @brief Implementation of the LogWriter singleton.
32*/
33
[8774]34#include "LogWriter.h"
35
36#include <ctime>
[11071]37#include <chrono>
[8833]38#include <cstdlib>
[8774]39
40#include "OutputManager.h"
41#include "MemoryWriter.h"
[9550]42#include "util/Convert.h"
[8774]43
44namespace orxonox
45{
[11071]46    static constexpr int MAX_ARCHIVED_FILES = 9;
[9550]47
[8848]48    /**
49        @brief Constructor, initializes the desired output levels and the name and path of the log-file, and opens the log-file.
50
51        By default, LogWriter receives all output up to level::internal_info.
52        The log-file has a default name which usually doesn't change. The path
53        is initialized with a temporary directory, depending on the system,
54        and can be changed later.
55    */
[8799]56    LogWriter::LogWriter() : BaseWriter("Log")
[8774]57    {
58        this->setLevelMax(level::internal_info);
59
[8799]60        this->filename_ = "orxonox.log";
[8774]61
[8848]62        // get the path for a temporary file, depending on the system
[8774]63#ifdef ORXONOX_PLATFORM_WINDOWS
[9550]64        this->directory_ = getenv("TEMP");
[8774]65#else
[9550]66        this->directory_ = "/tmp";
[8774]67#endif
68
[9550]69        // send a message to the user so that he can find the file in the case of a crash.
70        OutputManager::getInstance().pushMessage(level::user_info, context::undefined(), "Opening log file " + this->getPath());
71
[8774]72        this->openFile();
73    }
74
[8848]75    /**
76        @brief Destructor, closes the log-file.
77    */
[8774]78    LogWriter::~LogWriter()
79    {
80        this->closeFile();
81    }
82
[8848]83    /**
84        @brief Opens the log-file in order to write output to it.
85    */
[8774]86    void LogWriter::openFile()
87    {
[9550]88        // archive the old log file
89        this->archive();
[8774]90
[8848]91        // open the file
[9550]92        this->file_.open(this->getPath().c_str(), std::fstream::out);
[8774]93
[8848]94        // check if it worked and print some output
[8774]95        if (this->file_.is_open())
[8795]96            this->printLine("Log file opened", level::none);
[8774]97        else
[8831]98            OutputManager::getInstance().pushMessage(level::user_warning, context::undefined(), "Failed to open log file. File logging disabled.");
[8774]99    }
100
[8848]101    /**
102        @brief Closes the log-file.
103    */
[8774]104    void LogWriter::closeFile()
105    {
106        if (this->file_.is_open())
107        {
[8795]108            this->printLine("Log file closed", level::none);
[8774]109            this->file_.close();
110        }
111    }
112
[8848]113    /**
[9550]114     * @brief Archives old copies of the log file by adding increasing numbers to the filename.
115     */
116    void LogWriter::archive(int index)
117    {
118        std::string oldPath = this->getArchivedPath(index);
119
120        // see if the file already exists, otherwise return
121        std::ifstream stream(oldPath.c_str());
122        bool exists = stream.is_open();
123        stream.close();
124
125        if (!exists)
126            return;
127
128        if (index < MAX_ARCHIVED_FILES)
129        {
130            // increment the index and archive the file with the next higher index
131            this->archive(++index);
132
133            // create the new path based on the incremented index
134            std::string newPath = this->getArchivedPath(index);
135
136            // move the file
137            std::rename(oldPath.c_str(), newPath.c_str());
138        }
139        else
140        {
141            // delete the file
142            std::remove(oldPath.c_str());
143        }
144    }
145   
146    /**
147     * @brief Returns the path for archived copies of the logfile (based on the archive index)
148     */
149    std::string LogWriter::getArchivedPath(int index) const
150    {
151        std::string path = this->getPath();
152        if (index > 0)
153            path += '.' + multi_cast<std::string>(index);
154        return path;
155    }
156
157    /**
[8848]158        @brief Changes the path of the log-file. Re-writes the log-file by using MemoryWriter.
159    */
[9550]160    void LogWriter::setLogDirectory(const std::string& directory)
[8774]161    {
[8848]162        // notify about the change of the log-file (because the old file will no longer be updated)
[9550]163        OutputManager::getInstance().pushMessage(level::internal_info, context::undefined(), "Migrating log file from " + this->directory_ + "\nto " + directory);
[8774]164
[8848]165        // close the old file, update the path and open the new file
[8774]166        this->closeFile();
[9550]167        this->directory_ = directory;
[8774]168        this->openFile();
169
[8848]170        // request old output from MemoryWriter
[9550]171        if (OutputManager::getInstance().getMemoryWriter())
172            OutputManager::getInstance().getMemoryWriter()->resendOutput(this);
[8774]173    }
174
[8848]175    /**
176        @brief Inherited function from BaseWriter, writers output together with a timestamp to the log-file.
177    */
[8795]178    void LogWriter::printLine(const std::string& line, OutputLevel)
[8774]179    {
[8794]180        if (!this->file_.is_open())
181            return;
182
[11071]183        // get the milliseconds
184        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
185        std::chrono::system_clock::duration timeSinceEpoch = now.time_since_epoch();
186        std::chrono::milliseconds millisSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(timeSinceEpoch);
187        unsigned int millis = (millisSinceEpoch.count() % 1000);
188
[8848]189        // get the current time
[11071]190        time_t rawtime = std::chrono::system_clock::to_time_t(now);
191        struct tm* timeinfo = localtime(&rawtime);
[8774]192
[11071]193        // format time: hh:mm:ss:xxx
194        char buffer[13];
195        snprintf(buffer, sizeof(buffer), "%.2i:%.2i:%.2i:%.3i", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, millis);
196
[8848]197        // print timestamp and output line to the log file
[11071]198        this->file_ << buffer << ' ' << line << std::endl;
[8774]199    }
200}
Note: See TracBrowser for help on using the repository browser.