FFmpegfs Fuse Multi Media Filesystem 2.16
logging.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 Original author K. Henriksson
3 * Copyright (C) 2017-2024 Norbert Schlia (nschlia@oblivion-software.de)
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; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * On Debian systems, the complete text of the GNU General Public License
20 * Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
21 */
22
34#include "logging.h"
35#include "ffmpegfs.h"
36
37#include <sys/time.h>
38
39#include <cstdarg>
40#include <iostream>
41#include <syslog.h>
42#include <ostream>
43
44#define COLOUR_BLACK "\033[0;30m"
45#define COLOUR_DARK_GRAY "\033[1;30m"
46#define COLOUR_LIGHT_GRAY "\033[0;37m"
47#define COLOUR_RED "\033[0;31m"
48#define COLOUR_LIGHT_RED "\033[1;31m"
49#define COLOUR_GREEN "\033[0;32m"
50#define COLOUR_LIGHT_GREEN "\033[1;32m"
51#define COLOUR_BROWN_ORANGE "\033[0;33m"
52#define COLOUR_YELLOW "\033[1;33m"
53#define COLOUR_BLUE "\033[0;34m"
54#define COLOUR_LIGHT_BLUE "\033[1;34m"
55#define COLOUR_PURPLE "\033[0;35m"
56#define COLOUR_LIGHT_PURPLE "\033[1;35m"
57#define COLOUR_CYAN "\033[0;36m"
58#define COLOUR_LIGHT_CYAN "\033[1;36m"
59#define COLOUR_WHITE "\033[1;37m"
60#define COLOUR_RESET "\033[0m"
62std::unique_ptr<Logging> Logging::m_logging;
63
64std::recursive_mutex Logging::m_mutex;
65
66const std::map<Logging::LOGLEVEL, int> Logging::Logger::m_syslog_level_map =
67{
68 { LOGERROR, LOG_ERR },
69 { LOGWARN, LOG_WARNING },
70 { LOGINFO, LOG_INFO },
71 { LOGDEBUG, LOG_DEBUG },
72 { LOGTRACE, LOG_DEBUG },
73};
74
75const std::map<Logging::LOGLEVEL, std::string> Logging::Logger::m_level_name_map =
76{
77 { LOGERROR, "ERROR " },
78 { LOGWARN, "WARNING" },
79 { LOGINFO, "INFO " },
80 { LOGDEBUG, "DEBUG " },
81 { LOGTRACE, "TRACE " },
82};
83
84const std::map<Logging::LOGLEVEL, std::string> Logging::Logger::m_level_colour_map =
85{
91};
92
93Logging::Logging(const std::string &logfile, LOGLEVEL max_level, bool to_stderr, bool to_syslog) :
94 m_max_level(max_level),
95 m_to_stderr(to_stderr),
96 m_to_syslog(to_syslog)
97{
98 if (!logfile.empty())
99 {
100 m_logfile.open(logfile);
101 }
102
103 if (m_to_syslog)
104 {
105 openlog(PACKAGE, 0, LOG_USER);
106 }
107}
108
110{
111 std::lock_guard<std::recursive_mutex> lock_mutex(m_mutex);
112
113 // Construct string containing time
114 struct timeval tv;
115 long int millisec;
116 std::string time_string(sizeof("YYYY-MM-DD MM:HH:SS.###"), '\0'); // Reserve space for "YYYY-MM-DD MM:HH:SS.###" plus \0
117 std::string fmt;
118 std::string loglevel;
119 std::string filename;
120 std::string msg;
121
122 gettimeofday(&tv, NULL);
123
124 millisec = std::lrint(static_cast<double>(tv.tv_usec) / 1000.0); // Round to nearest millisec
125 if (millisec >= 1000)
126 { // Allow for rounding up to nearest second
127 millisec -= 1000;
128 tv.tv_sec++;
129 }
130
131 strsprintf(&fmt, "%%F %%T.%03d", millisec);
132
133 struct tm buf;
134 time_string.resize(strftime(&time_string[0], time_string.size(), fmt.c_str(), localtime_r(&tv.tv_sec, &buf))); // Mind the blank at the end
135
136 loglevel = m_level_name_map.at(m_loglevel) + ":";
137
138 msg = str();
139 trim(msg);
140
141 if (!m_filename.empty())
142 {
143 filename = m_filename;
144
145 if (replace_start(&filename, params.m_basepath))
146 {
147 filename = "INPUT [" + filename + "] ";
148 }
149 else if (replace_start(&filename, params.m_mountpath))
150 {
151 filename = "OUTPUT [" + filename + "] ";
152 }
153 else
154 {
155 std::string cachepath;
156
157 transcoder_cache_path(&cachepath);
158
159 if (replace_start(&filename, cachepath + params.m_mountpath + params.m_basepath))
160 {
161 filename = "CACHE [" + filename + "] ";
162 }
163 else
164 {
165 if (filename.size() && filename[0] == '/')
166 {
167 filename.erase(0, 1);
168 }
169 filename = "OTHER [" + filename + "] ";
170 }
171 }
172 }
173
174 if (m_logging->m_to_syslog)
175 {
176 syslog(m_syslog_level_map.at(m_loglevel), "%s %s%s", loglevel.c_str(), filename.c_str(), msg.c_str());
177 }
178
179 if (m_logging->m_logfile.is_open())
180 {
181 m_logging->m_logfile << time_string << " " << loglevel << " " << filename << msg << std::endl;
182 }
183
184 if (m_logging->m_to_stderr)
185 {
186 if (!filename.empty())
187 {
188 filename = COLOUR_LIGHT_PURPLE + filename + COLOUR_RESET;
189 }
190
191 if (m_loglevel <= LOGERROR)
192 {
193 msg = COLOUR_LIGHT_RED + msg + COLOUR_RESET;
194 }
195
196 std::clog << COLOUR_DARK_GRAY << time_string << " " << loglevel << COLOUR_RESET << " " << filename << msg << std::endl;
197 }
198}
199
201{
202 return m_logfile.fail();
203}
204
205Logging::Logger Log(Logging::LOGLEVEL loglevel, const std::string & filename)
206{
207 return {loglevel, filename};
208}
209
210bool Logging::init_logging(const std::string & logfile, LOGLEVEL max_level, bool to_stderr, bool to_syslog)
211{
212 if (m_logging != nullptr)
213 {
214 // Do not alloc twice
215 return false;
216 }
217
218 m_logging = std::make_unique<Logging>(logfile, max_level, to_stderr, to_syslog);
219 if (m_logging == nullptr)
220 {
221 return false; // Out of memory...
222 }
223 return !m_logging->GetFail();
224}
225
226void Logging::log_with_level(LOGLEVEL loglevel, const char * filename, const std::string & message)
227{
228 log_with_level(loglevel, std::string(filename != nullptr ? filename : ""), message);
229}
230
231void Logging::log_with_level(LOGLEVEL loglevel, const std::string & filename, const std::string & message)
232{
233 Log(loglevel, filename) << message;
234}
235
236std::string Logging::format_helper(const std::string &string_to_update,
237 const size_t __attribute__((unused)) index_to_replace)
238{
239 return string_to_update;
240}
Logging helper class.
Definition: logging.h:114
const LOGLEVEL m_loglevel
Log level required to write log entry.
Definition: logging.h:135
const std::string m_filename
Name of file for which this log entry was written. May be empty.
Definition: logging.h:137
virtual ~Logger()
Destroy Logger object.
Definition: logging.cc:109
static const std::map< LOGLEVEL, int > m_syslog_level_map
Map our log levels to syslog levels.
Definition: logging.h:139
static const std::map< LOGLEVEL, std::string > m_level_name_map
Map log level enums to strings.
Definition: logging.h:140
static const std::map< LOGLEVEL, std::string > m_level_colour_map
Map log level enums to colours (logging to stderr only)
Definition: logging.h:141
bool GetFail() const
Check whether either failbit or badbit is set.
Definition: logging.cc:200
static void log_with_level(LOGLEVEL loglevel, const char *filename, const std::string &message)
Write log entry.
Definition: logging.cc:226
static bool init_logging(const std::string &logfile, LOGLEVEL max_level, bool to_stderr, bool to_syslog)
Initialise the logging facility.
Definition: logging.cc:210
static std::unique_ptr< Logging > m_logging
Reference to self, Logging is a singleton.
Definition: logging.h:448
static std::string format_helper(const std::string &string_to_update, const size_t __attribute__((unused)) index_to_replace)
Standard format_helper without parameters.
Definition: logging.cc:236
Logging(const std::string &logfile, LOGLEVEL max_level, bool to_stderr, bool to_syslog)
Definition: logging.cc:93
friend Logger Log(LOGLEVEL loglevel, const std::string &filename)
Make logger class our friend for our constructor.
Definition: logging.cc:205
std::ofstream m_logfile
Log file object for writing to disk.
Definition: logging.h:450
static std::recursive_mutex m_mutex
Access mutex.
Definition: logging.h:449
const bool m_to_syslog
Whether to write log output to syslog.
Definition: logging.h:453
LOGLEVEL
Logging level types enum.
Definition: logging.h:85
std::string & trim(std::string &s)
trim from both ends
bool replace_start(std::string *str, const std::string &from, const std::string &to)
Replace start of string from "from" to "to".
const std::string & strsprintf(std::string *str, const std::string &format, Args ... args)
Format a std::string sprintf-like.
Definition: ffmpeg_utils.h:737
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
Definition: ffmpegfs.cc:74
Main include for FFmpegfs project.
void transcoder_cache_path(std::string *path)
Get transcoder cache path.
Definition: transcode.cc:195
#define COLOUR_DARK_GRAY
ANSI ESC for dark gray foreground.
Definition: logging.cc:45
#define COLOUR_GREEN
ANSI ESC for green foreground.
Definition: logging.cc:49
#define COLOUR_RED
ANSI ESC for red foreground.
Definition: logging.cc:47
#define COLOUR_WHITE
ANSI ESC for white foreground.
Definition: logging.cc:59
#define COLOUR_RESET
ANSI ESC to reset the foreground colour.
Definition: logging.cc:60
#define COLOUR_YELLOW
ANSI ESC for yellow foreground.
Definition: logging.cc:52
#define COLOUR_LIGHT_PURPLE
ANSI ESC for light purple foreground.
Definition: logging.cc:56
#define COLOUR_BLUE
ANSI ESC for blue foreground.
Definition: logging.cc:53
#define COLOUR_LIGHT_RED
ANSI ESC for light red foreground.
Definition: logging.cc:48
Provide various log facilities to stderr, disk or syslog.
constexpr Logging::LOGLEVEL LOGDEBUG
Shorthand for log level DEBUG.
Definition: logging.h:459
constexpr Logging::LOGLEVEL LOGTRACE
Shorthand for log level TRACE.
Definition: logging.h:460
constexpr Logging::LOGLEVEL LOGWARN
Shorthand for log level WARNING.
Definition: logging.h:457
constexpr Logging::LOGLEVEL LOGERROR
Shorthand for log level ERROR.
Definition: logging.h:456
constexpr Logging::LOGLEVEL LOGINFO
Shorthand for log level INFO.
Definition: logging.h:458
std::string m_mountpath
Mount path: Files from m_mountpath will be mapped to this directory.
Definition: ffmpegfs.h:197
std::string m_basepath
Base path: Files from this directory (including all sub directories) will be mapped to m_mountpath.
Definition: ffmpegfs.h:196