DPsim
Logger.cpp
1 /* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2  * EONERC, RWTH Aachen University
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7  *********************************************************************************/
8 
9 #include <iomanip>
10 #include <memory>
11 
12 #include <spdlog/sinks/null_sink.h>
13 #include <spdlog/sinks/stdout_color_sinks.h>
14 
15 #include <dpsim-models/Filesystem.h>
16 #include <dpsim-models/Logger.h>
17 
18 using namespace CPS;
19 
20 void Logger::setLogLevel(std::shared_ptr<spdlog::logger> logger,
21  Logger::Level level) {
22  logger->set_level(level);
23 }
24 
25 void Logger::setLogPattern(std::shared_ptr<spdlog::logger> logger,
26  std::string pattern) {
27  logger->set_pattern(pattern);
28 }
29 
30 // #### to string methods ####
31 String Logger::matrixToString(const Matrix &mat) {
32  std::stringstream ss;
33  ss << std::scientific << "\n" << mat;
34  return ss.str();
35 }
36 
37 String Logger::matrixCompToString(const MatrixComp &mat) {
38  std::stringstream ss;
39  ss << std::scientific << "\n" << mat;
40  return ss.str();
41 }
42 
43 String Logger::sparseMatrixToString(const SparseMatrix &mat) {
44  return matrixToString(Matrix(mat));
45 }
46 
47 String Logger::sparseMatrixCompToString(const SparseMatrixComp &mat) {
48  return matrixCompToString(MatrixComp(mat));
49 }
50 
51 String Logger::phasorMatrixToString(const MatrixComp &mat) {
52  std::stringstream ss;
53  ss << std::scientific << Math::abs(mat) << "\n\n" << Math::phase(mat);
54  return ss.str();
55 }
56 
57 String Logger::phasorToString(const Complex &num) {
58  std::stringstream ss;
59  ss << std::defaultfloat << Math::abs(num) << "<" << Math::phaseDeg(num);
60  return ss.str();
61 }
62 
63 String Logger::complexToString(const Complex &num) {
64  std::stringstream ss;
65  ss << std::defaultfloat << num.real() << "+j" << num.imag();
66  return ss.str();
67 }
68 
69 String Logger::realToString(const Real &num) {
70  std::stringstream ss;
71  ss << std::defaultfloat << num;
72  return ss.str();
73 }
74 
75 String Logger::prefix() {
76  char *p = getenv("CPS_LOG_PREFIX");
77 
78  return p ? p : "";
79 }
80 
81 String Logger::logDir() {
82  char *p = getenv("CPS_LOG_DIR");
83 
84  return p ? p : "logs";
85 }
86 
88 void Logger::setLogDir(String path) {
89 #ifdef __linux__
90  setenv("CPS_LOG_DIR", path.c_str(), 1);
91 #elif defined(_WIN32)
92  String var = "CPS_LOG_DIR=" + path;
93  _putenv(var.c_str());
94 #endif
95 }
96 
97 String Logger::getCSVColumnNames(std::vector<String> names) {
98  std::stringstream ss;
99  ss << std::right << std::setw(14) << "time";
100  for (auto name : names) {
101  ss << ", " << std::right << std::setw(13) << name;
102  }
103  ss << '\n';
104 
105  return ss.str();
106 }
107 
108 String Logger::getCSVLineFromData(Real time, Real data) {
109  std::stringstream ss;
110  ss << std::scientific << std::right << std::setw(14) << time;
111  ss << ", " << std::right << std::setw(13) << data;
112  ss << '\n';
113 
114  return ss.str();
115 }
116 
117 String Logger::getCSVLineFromData(Real time, const Matrix &data) {
118  std::stringstream ss;
119  ss << std::scientific << std::right << std::setw(14) << time;
120  for (Int i = 0; i < data.rows(); i++) {
121  ss << ", " << std::right << std::setw(13) << data(i, 0);
122  }
123  ss << '\n';
124 
125  return ss.str();
126 }
127 
128 String Logger::getCSVLineFromData(Real time, const MatrixComp &data) {
129  std::stringstream ss;
130  ss << std::scientific << std::right << std::setw(14) << time;
131  for (Int i = 0; i < data.rows(); i++) {
132  ss << ", " << std::right << std::setw(13) << data(i, 0);
133  }
134  ss << '\n';
135 
136  return ss.str();
137 }
138 
139 Logger::Log Logger::get(const std::string &name, Level filelevel,
140  Level clilevel) {
141  Logger::Log logger = spdlog::get(name);
142 
143  if (!logger) {
144  logger = create(name, filelevel, clilevel);
145  }
146 
147  return logger;
148 }
149 
150 Logger::Log Logger::create(const std::string &name, Level filelevel,
151  Level clilevel) {
152  String logDir = Logger::logDir();
153  String filename = logDir + "/" + name + ".log";
154  std::vector<spdlog::sink_ptr> sinks;
155  Logger::Log ret;
156 
157  // Create log folder if it does not exist
158  fs::path p = filename;
159  if (p.has_parent_path() && !fs::exists(p.parent_path()))
160  fs::create_directories(p.parent_path());
161 
162  if (clilevel != Logger::Level::off) {
163  auto console_sink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
164  console_sink->set_level(clilevel);
165  console_sink->set_pattern(
166  fmt::format("{}[%T.%f %n %^%l%$] %v", CPS::Logger::prefix()));
167  sinks.push_back(console_sink);
168  }
169 
170  if (filelevel != Logger::Level::off) {
171  auto file_sink =
172  std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
173  file_sink->set_level(filelevel);
174  file_sink->set_pattern(prefix() + "[%L] %v");
175  sinks.push_back(file_sink);
176  }
177 
178  if (filelevel == Logger::Level::off && clilevel == Logger::Level::off) {
179  ret = spdlog::create<spdlog::sinks::null_sink_st>(name);
180  } else {
181  ret = std::make_shared<spdlog::logger>(name, begin(sinks), end(sinks));
182  }
183 
184  return ret;
185 }
static void setLogDir(String path)
Set env variable CPS_LOG_DIR and overwrite.
Definition: Logger.cpp:88