source: cpp/common/loggers/loggers.cpp @ 874

Last change on this file since 874 was 874, checked in by Maciej Komosinski, 5 years ago

Introduced a function logLevelName() to avoid potential errors, e.g. forgetting "+1" in LOG_LEVEL[level+1]

  • Property svn:eol-style set to native
File size: 4.5 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[874]2// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
[375]5#include "loggers.h"
[841]6#include <common/util-string.h>
[511]7#include <string.h>
[109]8
[511]9void logMessage(const char *obj, const char *method, int level, const char *msg)
[109]10{
[378]11        tlsGetRef(message_handler_manager_instance).send(obj, method, level, msg);
[109]12}
13
[375]14THREAD_LOCAL_DEF(LoggerManager, message_handler_manager_instance);
[109]15
[378]16void LoggerManager::send(int position, const char *obj, const char *method, int level, const char *msg)
[109]17{
[378]18        if (position >= (int)loggers.size()) position = loggers.size() - 1;
19        bool blocked = false;
20        for (int i = position; i >= 0; i--)
[109]21        {
[378]22                LoggerBase *logger = loggers[i];
23                if ((!(logger->options & LoggerBase::Paused)) &&
24                        ((!blocked) || (logger->options & LoggerBase::CannotBeBlocked)))
[336]25                {
[378]26                        logger->handle(obj, method, level, msg);
27                        if (!(logger->options & LoggerBase::DontBlock)) blocked = true;
[336]28                }
[109]29        }
30}
31
[378]32int LoggerManager::add(LoggerBase *logger)
[109]33{
[378]34        logger->manager = this;
35        loggers.push_back(logger);
36        return loggers.size() - 1;
[109]37}
38
[375]39void LoggerManager::remove(int i)
[109]40{
[378]41        LoggerBase *h = loggers[i];
[373]42        h->manager = NULL;
[378]43        loggers.erase(loggers.begin() + i);
[109]44}
45
[378]46void LoggerManager::remove(LoggerBase *logger)
[109]47{
[378]48        int index = find(logger);
49        if (index >= 0)
50                remove(index);
[109]51}
52
[375]53void LoggerManager::removeAll()
[109]54{
[378]55        while (loggers.size() > 0)
56                remove(loggers.size() - 1);
[109]57}
58
59//////////////////////////////////
60
[378]61void LoggerBase::send(const char *obj, const char *method, int level, const char *msg)
[109]62{
[336]63        if (!isEnabled()) return;
[378]64        int position = manager->find(this);
65        if (position >= 0) manager->send(position - 1, obj, method, level, msg);
[109]66}
67
[378]68void LoggerBase::logPrintf(const char *obj, const char *method, int level, const char *msg, ...)
[109]69{
[336]70        if (!isEnabled()) return;
71        string buf;
72        va_list argptr;
[378]73        va_start(argptr, msg);
74        buf = ssprintf_va(msg, argptr);
[336]75        va_end(argptr);
[378]76        send(obj, method, level, buf.c_str());
[109]77}
78
79
[375]80void LoggerBase::enable()
[109]81{
[336]82        if (isEnabled()) return;
[372]83        tlsGetRef(message_handler_manager_instance).add(this);
[109]84}
85
[375]86void LoggerBase::disable()
[109]87{
[336]88        if (!isEnabled()) return;
[372]89        tlsGetRef(message_handler_manager_instance).remove(this);
[109]90}
91
[375]92void LoggerBase::pause()
[336]93{
94        if (isPaused()) return;
95        options |= Paused;
96}
97
[375]98void LoggerBase::resume()
[336]99{
100        if (!isPaused()) return;
101        options &= ~Paused;
102}
103
[511]104void LoggerBase::handle(const char *obj, const char *method, int level, const char *msg)
105{
106        int line = 0; //all lines except the first one get the "..." prefix
107        const char* nextsep;
108        do
109        {
110                nextsep = strchr(msg, '\n');
111                if (nextsep == NULL) //last chunk, until the end
112                        nextsep = strchr(msg, '\0');
113                if ((nextsep > msg) && (nextsep[-1] == '\r'))
114                        nextsep--;
115                if (line == 0)
116                {
117                        if (*nextsep == 0) //there was only one line! no need to modify it in any way.
118                                handleSingleLine(obj, method, level, msg);
119                        else //first line from multi-line
120                                handleSingleLine(obj, method, level, string(msg, nextsep - msg).c_str());
121                }
122                else //consecutive lines from multi-line
123                        handleSingleLine(obj, method, level, (LOG_MULTILINE_CONTINUATION + string(msg, nextsep - msg)).c_str()); //could also add line numbers like ...(3)... but let's keep the prefix short and simple
124                line++;
[873]125                if ((options & Paused) != 0) break; //seemingly pointless test (it was already checked), but 'options' can change inside handleSingleLine().
[511]126                if ((nextsep[0] == '\r') && (nextsep[1] == '\n'))
127                        msg = nextsep + 2;
128                else if (*nextsep)
129                        msg = nextsep + 1;
130        } while (*nextsep);
131}
132
[109]133/////////////////////////////////
134
[378]135void LoggerToMemory::handle(const char *obj, const char *method, int level, const char *msg)
[109]136{
[378]137        if (level > maxlevel) maxlevel = level;
138        if (level >= LOG_INFO) infocount++;
139        if (level >= LOG_WARN) warncount++;
140        if (level >= LOG_ERROR) errcount++;
[109]141
[378]142        if (level >= minleveltostore)
[109]143        {
[373]144                storedcount++;
[336]145                if (options & (StoreFirstMessage | StoreAllMessages))
[109]146                {
[378]147                        if (!((options&StoreFirstMessage) && (msgs.length() > 0)))
[109]148                        {
[378]149                                if (msgs.length() > 0) msgs += '\n';
[874]150                                msgs += ssprintf(LOG_FORMAT, logLevelName(level), obj, method, msg);
[109]151                        }
152                }
153        }
154}
[452]155
156string LoggerToMemory::getCountSummary() const
157{
[522]158        if (getInfoCount())
[452]159        {
[522]160                string msg;
161                if (getErrorCount())
162                        msg = ssprintf("%d error(s)", getErrorCount());
163                int w;
164                if (w = getWarningCount() - getErrorCount())
165                        msg += ssprintf("%s%d warning(s)", (getErrorCount() ? ", " : ""), w);
166                if (w = getInfoCount() - getWarningCount())
167                        msg += ssprintf("%s%d message(s)", (getWarningCount() ? ", " : ""), w);
168                return msg;
[452]169        }
[522]170        return string("");
[452]171}
Note: See TracBrowser for help on using the repository browser.