1 /*
2 mkvpropedit -- utility for editing properties of existing Matroska files
3
4 Distributed under the GPL v2
5 see the file COPYING for details
6 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
7
8 Written by Moritz Bunkus <moritz@bunkus.org>.
9 */
10
11 #include "common/common_pch.h"
12
13 #include <ctime>
14 #include <iostream>
15
16 #include <QDateTime>
17
18 #include "common/date_time.h"
19 #include "common/logger.h"
20 #if defined(SYS_WINDOWS)
21 # include "common/logger/windows.h"
22 #endif // SYS_WINDOWS
23 #include "common/fs_sys_helpers.h"
24 #include "common/mm_io_x.h"
25 #include "common/mm_file_io.h"
26 #include "common/mm_proxy_io.h"
27 #include "common/mm_text_io.h"
28 #include "common/path.h"
29 #include "common/strings/formatting.h"
30
31 namespace mtx::log {
32
33 target_cptr target_c::s_default_logger;
34
35 static QDateTime s_program_start_time;
36
target_c()37 target_c::target_c()
38 : m_log_start{mtx::sys::get_current_time_millis()}
39 {
40 }
41
42 std::string
format_line(std::string const & message)43 target_c::format_line(std::string const &message) {
44 auto timestamp = mtx::date_time::format(QDateTime::currentDateTime(), "%Y-%m-%d %H:%M:%S");
45 auto line = fmt::format("[mtx] {0} +{1}ms {2}", timestamp, runtime(), message);
46
47 if (message.size() && (message[message.size() - 1] != '\n'))
48 line += "\n";
49
50 return line;
51 }
52
53 target_c &
get_default_logger()54 target_c::get_default_logger() {
55 if (s_default_logger)
56 return *s_default_logger;
57
58 auto var = mtx::sys::get_environment_variable("MTX_LOGGER");
59
60 if (var.empty()) {
61 #if defined(SYS_WINDOWS)
62 var = "debug";
63 #else
64 var = "stderr";
65 #endif // SYS_WINDOWS
66 }
67
68 auto spec = mtx::string::split(var, ":", 2);
69
70 if (spec[0] == "file") {
71 auto file = (spec.size() > 1) && !spec[1].empty() ? spec[1] : "mkvtoolnix-debug.txt"s;
72
73 set_default_logger(target_cptr{new file_target_c{mtx::fs::to_path(file)}});
74
75 #if defined(SYS_WINDOWS)
76 } else if (spec[0] == "debug") {
77 set_default_logger(target_cptr{new windows_debug_target_c{}});
78 #endif // SYS_WINDOWS
79
80 } else
81 set_default_logger(target_cptr{new stderr_target_c{}});
82
83 return *s_default_logger;
84 }
85
86 void
set_default_logger(target_cptr const & logger)87 target_c::set_default_logger(target_cptr const &logger) {
88 s_default_logger = logger;
89 }
90
91 int64_t
runtime()92 target_c::runtime() {
93 return s_program_start_time.msecsTo(QDateTime::currentDateTime());
94 }
95
96 // ----------------------------------------------------------------------
97
file_target_c(std::filesystem::path file_name)98 file_target_c::file_target_c(std::filesystem::path file_name)
99 : target_c{}
100 , m_file_name{std::move(file_name)}
101 {
102 if (!mtx::fs::is_absolute(m_file_name))
103 m_file_name = std::filesystem::temp_directory_path() / mtx::fs::to_path(m_file_name);
104
105 if (std::filesystem::is_regular_file(m_file_name)) {
106 std::error_code ec;
107 std::filesystem::remove(m_file_name, ec);
108 }
109 }
110
111 void
log_line(std::string const & message)112 file_target_c::log_line(std::string const &message) {
113 try {
114 mm_text_io_c out(std::make_shared<mm_file_io_c>(m_file_name.u8string(), std::filesystem::is_regular_file(m_file_name) ? MODE_WRITE : MODE_CREATE));
115 out.setFilePointer(0, libebml::seek_end);
116 out.puts(format_line(message));
117 } catch (mtx::mm_io::exception &ex) {
118 }
119 }
120
121 // ----------------------------------------------------------------------
122
stderr_target_c()123 stderr_target_c::stderr_target_c()
124 : target_c{}
125 {
126 }
127
128 void
log_line(std::string const & message)129 stderr_target_c::log_line(std::string const &message) {
130 std::cerr << message;
131 }
132
133 // ----------------------------------------------------------------------
134
135 void
init()136 init() {
137 s_program_start_time = QDateTime::currentDateTime();
138 }
139
140 }
141