PLaSK library

Loading...
Searching...
No Matches
log.cpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include <cstdio>
15
16#include "log.hpp"
17
18#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
19# include <plask/utils/minimal_windows.h>
20#else
21# include <unistd.h>
22#endif
23
24#ifdef OPENMP_FOUND
25# include "../parallel.hpp"
26#endif
27
28 namespace plask {
29
30#ifdef NDEBUG
31 PLASK_API LogLevel maxLoglevel = LOG_DETAIL;
32#else
33 PLASK_API LogLevel maxLoglevel = LOG_DEBUG;
34#endif
35
36 PLASK_API bool forcedLoglevel = false;
37
38#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
39 PLASK_API std::string host_name() {
40 char name[1024];
41 DWORD size = sizeof(name);
42 GetComputerNameEx(ComputerNameDnsHostname, name, &size);
43 return std::string(name);
44 }
45#else
46 PLASK_API std::string host_name() {
47 char name[1024];
48 ::gethostname(name, sizeof(name));
49 return std::string(name);
50 }
51#endif
52
53 Logger::Logger(): silent(false), color(
54# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
55 Logger::COLOR_WINDOWS
56# else
57 isatty(fileno(stderr))? Logger::COLOR_ANSI : Logger::COLOR_NONE
58# endif
59 ) {
60 if (const char* env = std::getenv("OMPI_COMM_WORLD_RANK"))
61 prefix = std::string(env) + " : ";
62 else if (const char* env = std::getenv("PMI_RANK"))
63 prefix = std::string(env) + " : ";
64 else if (const char* env = std::getenv("SLURM_PROCID"))
65 prefix = std::string(env) + " : ";
66 else if (const char* env = std::getenv("PBS_VNODENUM"))
67 prefix = std::string(env) + " : ";
68 else
69 prefix = "";
70}
71
72 struct StderrLogger: public plask::Logger {
73
74# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
75 void setcolor(unsigned short fg);
76 unsigned short previous_color;
77# endif
78
79 const char* head(plask::LogLevel level);
80
81 void writelog(plask::LogLevel level, const std::string& msg) override;
82
83};
84
85#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
86
87# define COL_BLACK 0
88# define COL_BLUE 1
89# define COL_GREEN 2
90# define COL_CYAN 3
91# define COL_RED 4
92# define COL_MAGENTA 5
93# define COL_BROWN 6
94# define COL_WHITE 7
95# define COL_GRAY 8
96# define COL_BRIGHT_BLUE 9
97# define COL_BRIGHT_GREEN 10
98# define COL_BRIGHT_CYAN 11
99# define COL_BRIGHT_RED 12
100# define COL_BRIGHT_MAGENTA 13
101# define COL_YELLOW 14
102# define COL_BRIGHT_WHITE 15
103
104 inline void StderrLogger::setcolor(unsigned short fg) {
105 HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
106 CONSOLE_SCREEN_BUFFER_INFO csbi;
107 GetConsoleScreenBufferInfo(handle, &csbi);
108 previous_color = csbi.wAttributes;
109 SetConsoleTextAttribute(handle, (csbi.wAttributes & 0xF0) | fg);
110 }
111
112#else
113
114#endif
115
116#define ANSI_DEFAULT "\033[00m"
117#define ANSI_BLACK "\033[30m"
118#define ANSI_RED "\033[31m"
119#define ANSI_GREEN "\033[32m"
120#define ANSI_BROWN "\033[33m"
121#define ANSI_BLUE "\033[34m"
122#define ANSI_MAGENTA "\033[35m"
123#define ANSI_CYAN "\033[36m"
124#define ANSI_WHITE "\033[37m"
125#define ANSI_GRAY "\033[30;01m"
126#define ANSI_BRIGHT_RED "\033[31;01m"
127#define ANSI_BRIGHT_GREEN "\033[32;01m"
128#define ANSI_YELLOW "\033[33;01m"
129#define ANSI_BRIGHT_BLUE "\033[34;01m"
130#define ANSI_BRIGHT_MAGENTA "\033[35;01m"
131#define ANSI_BRIGHT_CYAN "\033[36;01m"
132#define ANSI_BRIGHT_WHITE "\033[37;01m"
133 const char* StderrLogger::head(LogLevel level) {
134 if (color == StderrLogger::COLOR_ANSI)
135 switch (level) {
136 case LOG_CRITICAL_ERROR:return ANSI_BRIGHT_RED "CRITICAL ERROR";
137 case LOG_ERROR: return ANSI_BRIGHT_RED "ERROR ";
138 case LOG_WARNING: return ANSI_BROWN "WARNING ";
139 case LOG_IMPORTANT: return ANSI_BRIGHT_MAGENTA "IMPORTANT ";
140 case LOG_INFO: return ANSI_BRIGHT_BLUE "INFO ";
141 case LOG_RESULT: return ANSI_GREEN "RESULT ";
142 case LOG_DATA: return ANSI_CYAN "DATA ";
143 case LOG_DETAIL: return ANSI_DEFAULT "DETAIL ";
144 case LOG_ERROR_DETAIL: return ANSI_RED "ERROR DETAIL ";
145 case LOG_DEBUG: return ANSI_GRAY "DEBUG ";
146 }
147#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
148 else if (color == StderrLogger::COLOR_WINDOWS)
149 switch (level) {
150 case LOG_ERROR: setcolor(COL_BRIGHT_RED); return "ERROR ";
151 case LOG_CRITICAL_ERROR:setcolor(COL_BRIGHT_RED); return "CRITICAL ERROR";
152 case LOG_WARNING: setcolor(COL_BROWN); return "WARNING ";
153 case LOG_IMPORTANT: setcolor(COL_BRIGHT_MAGENTA); return "IMPORTANT ";
154 case LOG_INFO: setcolor(COL_BRIGHT_CYAN); return "INFO ";
155 case LOG_RESULT: setcolor(COL_GREEN); return "RESULT ";
156 case LOG_DATA: setcolor(COL_CYAN); return "DATA ";
157 case LOG_DETAIL: return "DETAIL ";
158 case LOG_ERROR_DETAIL: setcolor(COL_RED); return "ERROR DETAIL ";
159 case LOG_DEBUG: setcolor(COL_GRAY); return "DEBUG ";
160 }
161#endif
162 else
163 switch (level) {
164 case LOG_CRITICAL_ERROR:return "CRITICAL ERROR";
165 case LOG_ERROR: return "ERROR ";
166 case LOG_WARNING: return "WARNING ";
167 case LOG_IMPORTANT: return "IMPORTANT ";
168 case LOG_INFO: return "INFO ";
169 case LOG_RESULT: return "RESULT ";
170 case LOG_DATA: return "DATA ";
171 case LOG_DETAIL: return "DETAIL ";
172 case LOG_ERROR_DETAIL: return "ERROR DETAIL ";
173 case LOG_DEBUG: return "DEBUG ";
174 }
175 return "UNSPECIFIED "; // mostly to silence compiler warning than to use in the real life
176}
177
178 void StderrLogger::writelog(LogLevel level, const std::string& msg) {
179#ifdef OPENMP_FOUND
180 static OmpSingleLock loglock;
181 OmpLockGuard guard(loglock);
182#endif
183
184 static LogLevel prev_level; static std::string prev_msg;
185 if (level == prev_level && msg == prev_msg) return;
186 prev_level = level; prev_msg = msg;
187
188 if (color == COLOR_ANSI) {
189 fprintf(stderr, "%s: %s%s" ANSI_DEFAULT "\n", head(level), prefix.c_str(), msg.c_str());
190 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
191 } else if (color == COLOR_WINDOWS) {
192 fprintf(stderr, "%s: %s%s\n", head(level), prefix.c_str(), msg.c_str());
193 SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), previous_color);
194 #endif
195 } else {
196 fprintf(stderr, "%s: %s%s\n", head(level), prefix.c_str(), msg.c_str());
197 }
198}
199
200 PLASK_API shared_ptr<Logger> default_logger;
201
202 NoLogging::NoLogging(): old_state(default_logger->silent) {}
203
204
205 NoLogging::NoLogging(bool silent): old_state(default_logger->silent) {
206 default_logger->silent = silent;
207}
208
209 NoLogging::~NoLogging() {
210 default_logger->silent = old_state;
211}
212
214 void NoLogging::set(bool silent) {
215 default_logger->silent = silent;
216}
217
219 PLASK_API void createDefaultLogger() {
220 default_logger = shared_ptr<Logger>(new StderrLogger());
221}
222
223} // namespace plask