Skyward boardcore
Loading...
Searching...
No Matches
PrintLogger.cpp
Go to the documentation of this file.
1/* Copyright (c) 2021 Skyward Experimental Rocketry
2 * Author: Luca Erbetta
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "PrintLogger.h"
24
25#include <utils/KernelTime.h>
26
27using miosix::Lock;
28
29namespace Boardcore
30{
31
32static string getLevelString(uint8_t level)
33{
34 switch (level)
35 {
36 case LOGL_DEBUG:
37 return "DEBUG";
38 case LOGL_INFO:
39 return "INFO";
40 case LOGL_WARNING:
41 return "WARNING";
42 case LOGL_ERROR:
43 return "ERROR";
44 case LOGL_CRITICAL:
45 return "CRITICAL";
46 default:
47 return std::to_string(level);
48 }
49}
50
51static string truncateFileName(const string& name, int depth = 0)
52{
53 // Find the first separator
54 auto start = name.find_last_of("\\/");
55
56 // Now traverse the path until we reach the end or the required depth
57 for (int i = 0; i < depth && start != string::npos; i++)
58 start = name.find_last_of("\\/", start - 1);
59
60 // Truncate the path if needed
61 return start == string::npos
62 ? name
63 : "..." + string{name.cbegin() + start, name.cend()};
64}
65
66void LogSink::log(const LogRecord& record)
67{
68 using namespace fmt::literals;
69 if (record.level >= minimumLevel)
70 {
71 float ts = Kernel::getOldTick() / 1000.0f;
72 int min = ts / 60;
73 string tsStr = fmt::format("{:02d}:{:06.3f}", min, (ts - min * 60));
74
75 logImpl(fmt::format(
76 format, "ts"_a = tsStr, "file"_a = truncateFileName(record.file, 1),
77 "line"_a = // cppcheck-suppress AssignmentIntegerToAddress
78 record.line,
79 "fun"_a = record.function, "lvl"_a = getLevelString(record.level),
80 "name"_a = record.name, "msg"_a = record.message));
81 }
82}
83
84void FileLogSink::logImpl(const string& l)
85{
86 Lock<FastMutex> lock(mutex);
87 fwrite(l.c_str(), sizeof(char), l.length(), f);
88}
89
90void FileLogSinkBuffered::logImpl(const string& l)
91{
92 Lock<FastMutex> lock(mutex);
94 strncpy(s.logString, l.c_str(), MAX_LOG_STRING_SIZE - 1);
95 logger.log(s);
96}
97
99{
100 return PrintLogger(parent, this->name + "." + name);
101}
102
103LogRecord PrintLogger::buildLogRecord(uint8_t level, const string& function,
104 const string& file, int line,
105 fmt::string_view format,
106 fmt::format_args args)
107{
108 LogRecord record;
109 record.level = level;
110 record.function = function;
111 record.file = file;
112 record.line = line;
113 record.name = name;
114 try
115 {
116 record.message = fmt::vformat(format, args);
117 }
118 catch (const std::exception& e)
119 {
120 record.level = LOGL_ERROR;
121 record.message = "FMT Formatting error! " + string(e.what());
122 }
123
124 return record;
125}
126
127void PrintLogger::vlog(uint8_t level, const string& function,
128 const string& file, int line, fmt::string_view format,
129 fmt::format_args args)
130{
131 parent.log(buildLogRecord(level, function, file, line, format, args));
132}
133
134void PrintLogger::vlogAsync(uint8_t level, const string& function,
135 const string& file, int line,
136 fmt::string_view format, fmt::format_args args)
137{
138 parent.logAsync(buildLogRecord(level, function, file, line, format, args));
139}
140
141void Logging::log(const LogRecord& record)
142{
143 for (auto& s : sinks)
144 if (s->isEnabled())
145 s->log(record);
146}
147
148void Logging::logAsync(const LogRecord& record) { asyncLog.log(record); }
149
150Logging::AsyncLogger::AsyncLogger(Logging& parent) : parent(parent) {}
151
152void Logging::AsyncLogger::log(const LogRecord& record)
153{
154 {
155 Lock<FastMutex> l(mutex);
156 records.put(record);
157 }
158
159 cv.signal();
160}
161
162void Logging::AsyncLogger::run()
163{
164 while (!shouldStop())
165 {
166 LogRecord rec;
167 {
168 Lock<FastMutex> l(mutex);
169 while (records.isEmpty())
170 cv.wait(mutex);
171
172 rec = records.pop();
173 }
174
175 parent.log(rec);
176 }
177}
178
179} // namespace Boardcore
if(canDrivers[canDev]) canDrivers[canDev] -> handleRXInterrupt(fifo)
void logImpl(const std::string &l) override
void logImpl(const std::string &l) override
miosix::FastMutex mutex
Definition LogSink.h:80
void log(const LogRecord &record)
virtual void logImpl(const std::string &l)=0
LoggerResult log(const T &t)
Call this function to log a class.
Definition Logger.h:224
PrintLogger(Logging &logging, const string &name)
Definition PrintLogger.h:60
PrintLogger getChild(const string &name)
PrintLogger l
Definition CanDriver.cpp:41
long long getOldTick()
Get the current time in milliseconds.
Definition KernelTime.h:43
This file includes all the types the logdecoder script will decode.