Path: blob/trunk/cpp/webdriver-interactions/logging.h
2867 views
/*1Licensed to the Software Freedom Conservancy (SFC) under one2or more contributor license agreements. See the NOTICE file3distributed with this work for additional information4regarding copyright ownership. The SFC licenses this file5to you under the Apache License, Version 2.0 (the "License");6you may not use this file except in compliance with the License.7You may obtain a copy of the License at89http://www.apache.org/licenses/LICENSE-2.01011Unless required by applicable law or agreed to in writing, software12distributed under the License is distributed on an "AS IS" BASIS,13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14See the License for the specific language governing permissions and15limitations under the License.16*/1718#ifndef logging_h19#define logging_h2021#ifdef _WIN3222#pragma warning(push)23#pragma warning(disable:4996 4717)24#define fileno _fileno25#define isatty _isatty26#define lseek _lseek27#ifdef _ftime28#define ftime _ftime29#endif30#endif3132#ifdef unix33#include <sys/types.h>34#include <unistd.h>35#else36#include <io.h>37#include <comdef.h>38#endif39#include <stdio.h>40#include <stdlib.h>41#include <sys/timeb.h>42#include <time.h>43#include <sstream>44#include <string>45#include <iostream>4647template <class _LOGGER> class Logger {48public:49Logger() : fatal_(false) {}5051enum LogLevel {52logFATAL = 0, logERROR, logWARN, logINFO, logDEBUG, logTRACE };5354~Logger() {55os_ << std::endl, _LOGGER::Log(os_.str(), fatal_);56if (fatal_) {57exit(EXIT_FAILURE);58}59}6061static void Level(const std::string& level) {62Level() = ToLogLevel(level);63}6465static LogLevel& Level() {66static LogLevel level = GetLogLevelEnv();67return level;68}6970std::ostringstream& Stream(LogLevel level) {71static char severity[] = { 'F', 'E', 'W', 'I', 'D', 'T' };72os_ << severity[level] << ' ' << Time();73if (level == logFATAL)74fatal_ = true, os_ << L"FATAL ";75return os_;76}7778static std::string Time() {79struct timeb tb; ftime(&tb);8081char time[26];82size_t length = strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S:",83localtime(reinterpret_cast<const time_t*>(&tb.time)));84sprintf(time + length, "%03u ", tb.millitm);8586return time;87}8889private:9091static LogLevel ToLogLevel(const std::string& level) {92if (level == "ERROR") {93return logERROR;94} else if (level == "WARN" ) {95return logWARN;96} else if (level == "INFO" ) {97return logINFO;98} else if (level == "DEBUG") {99return logDEBUG;100} else if (level == "TRACE") {101return logTRACE;102} else {103return logFATAL;104}105}106107static LogLevel GetLogLevelEnv() {108char* tmp = getenv("SELENIUM_LOG_LEVEL");109return tmp ? ToLogLevel(std::string(tmp)) : logFATAL;110}111112std::ostringstream os_;113bool fatal_;114};115116class LOG : public Logger<LOG> {117public:118static void File(const std::string& name, const char* openMode = "w") {119const std::string& file = Name(name);120if (file == "stdout") {121LOG::File() = stdout;122} else if (file == "stderr") {123LOG::File() = stderr;124} else {125LOG::File() = fopen(file.c_str(), openMode);126}127}128129static void Limit(off_t size) {130LOG::Limit() = size;131}132133private:134static std::string& Name(const std::string& name) {135static std::string file_name = "stdout";136if (!name.empty())137file_name.assign(name);138return file_name;139}140141static FILE*& File() {142static FILE* file = stdout;143return file;144}145146static off_t& Limit() {147static off_t size_limit = 0;148return size_limit;149}150151static void Log(const std::string& str, bool fatal) {152if (fatal) Limit() = 0;153154FILE* output = File();155if (output) {156fwrite(str.data(), sizeof(char), str.size(), output);157fflush(output);158159if (Limit() && !isatty(fileno(output))) {160if (lseek(fileno(output), 0, SEEK_END) > Limit()) {161fclose(output), File("");162}163}164}165166if (fatal && !isatty(fileno(output))) {167fputs(str.c_str(), stderr);168}169}170171friend class Logger<LOG>;172};173174#ifdef _WIN32175#pragma warning(pop)176#endif177178179#define LOG(LEVEL) \180if (LOG::log ## LEVEL > LOG::Level()) ; \181else LOG().Stream(LOG::log ## LEVEL) << __FILE__ << "(" << __LINE__ << ") " /* << stuff here */182183#ifdef _WIN32184#define LOGHR(LEVEL,HR) LOG( ## LEVEL) << HR << " [" << (_bstr_t(_com_error((DWORD) HR).ErrorMessage())) << "]: "185#define LOGERR(LEVEL) LOG( ## LEVEL) << " [Windows Error " << (::GetLastError()) << "]: "186#define LOGWSTRING(STR) _bstr_t( (## STR).c_str())187#endif188189190#endif // logging_h191192193