www.pudn.com > zfxcengine-0.1.0.zip > ceLogConfig.cpp
/* $Id: ceLogConfig.cpp,v 1.5 2005/07/03 17:01:44 andreaskohn Exp $ */ #include#include #include #include #include namespace ZFXCE { namespace Logging { using std::make_pair; using std::fgets; using std::fopen; using std::fclose; using std::feof; using std::strcmp; using std::strlen; using std::strchr; using std::memmove; LOG_INIT("ZFXCE::Logging") //////////////////////////////////////////////////////////////////////////////// ceLogDomain* ceLogConfig::getDomain(string domain, string file) { // TODO: domain inheritance? ceLogDomain* logDomain = NULL; map >::iterator it = getDomains().find(domain); if (it == getDomains().end()) { logDomain = new ceLogDomain(domain); getDomains()[domain] = make_pair(logDomain, file); } else { logDomain = (*it).second.first; } return logDomain; } //////////////////////////////////////////////////////////////////////////////// ceLogger* ceLogConfig::getLogger(string domain, string file) { return new ceLogger(getDomain(domain, file)); } //////////////////////////////////////////////////////////////////////////////// ceLogLevel ceLogConfig::parseLogLevel(const string& level) { if (level == "DEBUG") { return LOG_DEBUG; } else if (level == "INFO") { return LOG_INFO; } else if (level == "WARN") { return LOG_WARN; } else if (level == "ERROR") { return LOG_ERROR; } else if (level == "FATAL") { return LOG_FATAL; } // not a valid level return LOG_NUMLEVELS; } //////////////////////////////////////////////////////////////////////////////// const string ceLogConfig::getLogLevelName(const ceLogLevel level) { switch (level) { case LOG_DEBUG: return "DEBUG"; break; case LOG_INFO: return "INFO"; break; case LOG_WARN: return "WARN"; break; case LOG_ERROR: return "ERROR"; break; case LOG_FATAL: return "FATAL"; break; case LOG_NUMLEVELS: default: return "(unknown log level)"; break; } } //////////////////////////////////////////////////////////////////////////////// // [[domain][,level]=]filename //////////////////////////////////////////////////////////////////////////////// void ceLogConfig::parseLogDomain(const string& domain, string& targetDomain, ceLogLevel& targetLevel, ceLogStream*& targetStream) { targetDomain = ""; targetLevel = LOG_NUMLEVELS; targetStream = NULL; string::size_type pos = domain.rfind("="); if (pos != string::npos) { // XXX: perhaps we find a way to define other streams. string streamFileName = domain.substr(pos + 1); LOG_DEBUG1("stream %s, ", streamFileName.c_str()); targetStream = new ceStdioStream(streamFileName); string domainAndLevel = domain.substr(0, pos); pos = domainAndLevel.find(","); if (pos != string::npos) { // we have both, but domain may be empty targetDomain = domainAndLevel.substr(0, pos); LOG_DEBUG1("domain %s, ", targetDomain.c_str()); targetLevel = parseLogLevel(domainAndLevel.substr(pos + 1)); LOG_DEBUG1("level %s\n", getLogLevelName(targetLevel).c_str()); } else { // we only have a domain targetDomain = domainAndLevel; LOG_DEBUG1("domain %s, all levels\n", targetDomain.c_str()); } } else { targetStream = new ceStdioStream(domain); } } //////////////////////////////////////////////////////////////////////////////// // XXX: should perhaps be moved to ceLogDomain sometimes. Be careful, circular friendships may happen. void ceLogConfig::dumpDomain(ceLogDomain* domain, string file) { printf("%s (%s)\n", domain->getDomain().c_str(), file.c_str()); for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { list streams = domain->getStreams(i, false); bool enabled = domain->isLevelEnabled(i); if (enabled || streams.size() > 0) { printf("\t%s (%s)\n", getLogLevelName(i).c_str(), (enabled?"enabled":"disabled")); for (list ::iterator it = streams.begin(); it != streams.end(); it++) { printf("\t\t%s\n", (*it)->getInfo().c_str()); } } } } //////////////////////////////////////////////////////////////////////////////// void ceLogConfig::dumpDomains() { printf("Registered logging domains:\n"); for (map >::const_iterator it = getDomains().begin(); it != getDomains().end(); it++) { ceLogDomain* domain = (*it).second.first; string file = (*it).second.second; dumpDomain(domain, file); } printf("Default domain:\n"); dumpDomain(&getDefaultDomain(), string("ceLogConfig.cpp")); } //////////////////////////////////////////////////////////////////////////////// void ceLogConfig::init(int& argc, char**& argv) { list > domains; string configFile = "zfxceLogging.config"; bool doDumpDomains = false; // parse commands // and change argc and argv so that these args are removed for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--log") == 0) { domains.push_back(make_pair(argv[++i], "[command line]")); } else if (strcmp(argv[i], "--dump-domains") == 0) { doDumpDomains = true; } else if (strcmp(argv[i], "--log-config") == 0) { configFile = string(argv[++i]); } else if (strcmp(argv[i], "--log-help") == 0) { printf("Arguments supported by the logging system are: \n"); printf(" --log [[domain][,level]=]filename\n"); printf(" --dump-domains\n"); printf(" --log-config filename\n"); } // TODO: change argc, argv. } // open config file FILE* f = fopen(configFile.c_str(), "r"); if (f) { const int MAX_LINE = 2048; char buffer[MAX_LINE]; char nbuffer[MAX_LINE]; while (!feof(f)) { if (fgets(buffer, MAX_LINE, f) != NULL) { buffer[strlen(buffer) - 1] = 0; size_t j = 0; for (size_t i = 0; i < strlen(buffer); i++) { if (strchr(" \t\n\r", buffer[i]) == NULL) { nbuffer[j++] = buffer[i]; } } nbuffer[j] = 0; if (strlen(nbuffer) > 0) { domains.push_front(make_pair(nbuffer, configFile)); } } } fclose(f); } // initialize domains string targetDomain = ""; ceLogLevel targetLevel = LOG_NUMLEVELS; ceLogStream* targetStream = NULL; for (list >::const_iterator it = domains.begin(); it != domains.end(); it++) { parseLogDomain((*it).first, targetDomain, targetLevel, targetStream); if (targetStream == NULL) { // ignore this line continue; } if (targetDomain == "") { if (targetLevel == LOG_NUMLEVELS) { // insert for all for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { getDefaultDomain().attachStream(i, targetStream); } } else { getDefaultDomain().attachStream(targetLevel, targetStream); } } else { ceLogDomain* domain = getDomain(targetDomain, (*it).second); if (targetLevel == LOG_NUMLEVELS) { // insert for all for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { domain->attachStream(i, targetStream); domain->enableLevel(i, true); } } else { domain->attachStream(targetLevel, targetStream); domain->enableLevel(targetLevel, true); } } } // if we were to dump domains, do it now. Auto-domains, command-line // domains and domains created before init() are now initialized. // We can't get information about stuff that gets initialized later. if (doDumpDomains) { dumpDomains(); } LOG_DEBUG("ceLogInit::init(): argc and argv are not updated.\n"); } //////////////////////////////////////////////////////////////////////////////// map >& ceLogConfig::getDomains() { static map > _domains; return _domains; } //////////////////////////////////////////////////////////////////////////////// bool& ceLogConfig::getAllDisabled() { static bool _allDisabled = false; return _allDisabled; } //////////////////////////////////////////////////////////////////////////////// ceLogDomain& ceLogConfig::getDefaultDomain() { static ceLogDomain _defaultDomain("[default]"); return _defaultDomain; } //////////////////////////////////////////////////////////////////////////////// } // namespace Logging } // namespace ZFXCE