OpenShot Library | libopenshot 0.3.3
Loading...
Searching...
No Matches
ZmqLogger.cpp
Go to the documentation of this file.
1
9// Copyright (c) 2008-2019 OpenShot Studios, LLC
10//
11// SPDX-License-Identifier: LGPL-3.0-or-later
12
13#include "ZmqLogger.h"
14#include "Exceptions.h"
15#include "Settings.h"
16
17#if USE_RESVG == 1
18 #include "ResvgQt.h"
19#endif
20
21using namespace openshot;
22
23#include <sstream>
24#include <iostream>
25#include <iomanip>
26#include <ctime>
27#include <thread> // for std::this_thread::sleep_for
28#include <chrono> // for std::duration::microseconds
29
30
31// Global reference to logger
32ZmqLogger *ZmqLogger::m_pInstance = NULL;
33
34// Create or Get an instance of the logger singleton
36{
37 if (!m_pInstance) {
38 // Create the actual instance of logger only once
39 m_pInstance = new ZmqLogger;
40
41 // init ZMQ variables
42 m_pInstance->context = NULL;
43 m_pInstance->publisher = NULL;
44 m_pInstance->connection = "";
45
46 // Default connection
47 m_pInstance->Connection("tcp://*:5556");
48
49 // Init enabled to False (force user to call Enable())
50 m_pInstance->enabled = false;
51
52 #if USE_RESVG == 1
53 // Init resvg logging (if needed)
54 // This can only happen 1 time or it will crash
55 ResvgRenderer::initLog();
56 #endif
57 }
58
59 return m_pInstance;
60}
61
62// Set the connection for this logger
63void ZmqLogger::Connection(std::string new_connection)
64{
65 // Create a scoped lock, allowing only a single thread to run the following code at one time
66 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
67
68 // Does anything need to happen?
69 if (new_connection == connection)
70 return;
71 else
72 // Set new connection
73 connection = new_connection;
74
75 if (context == NULL) {
76 // Create ZMQ Context
77 context = new zmq::context_t(1);
78 }
79
80 if (publisher != NULL) {
81 // Close an existing bound publisher socket
82 publisher->close();
83 publisher = NULL;
84 }
85
86 // Create new publisher instance
87 publisher = new zmq::socket_t(*context, ZMQ_PUB);
88
89 // Bind to the socket
90 try {
91 publisher->bind(connection.c_str());
92
93 } catch (zmq::error_t &e) {
94 std::cout << "ZmqLogger::Connection - Error binding to " << connection << ". Switching to an available port." << std::endl;
95 connection = "tcp://*:*";
96 publisher->bind(connection.c_str());
97 }
98
99 // Sleeping to allow connection to wake up (0.25 seconds)
100 std::this_thread::sleep_for(std::chrono::milliseconds(250));
101}
102
103void ZmqLogger::Log(std::string message)
104{
105 if (!enabled)
106 // Don't do anything
107 return;
108
109 // Create a scoped lock, allowing only a single thread to run the following code at one time
110 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
111
112 // Send message over socket (ZeroMQ)
113 zmq::message_t reply (message.length());
114 std::memcpy (reply.data(), message.c_str(), message.length());
115
116#if ZMQ_VERSION > ZMQ_MAKE_VERSION(4, 3, 1)
117 // Set flags for immediate delivery (new API)
118 publisher->send(reply, zmq::send_flags::dontwait);
119#else
120 publisher->send(reply);
121#endif
122
123 // Also log to file, if open
124 LogToFile(message);
125}
126
127// Log message to a file (if path set)
128void ZmqLogger::LogToFile(std::string message)
129{
130 // Write to log file (if opened, and force it to write to disk in case of a crash)
131 if (log_file.is_open())
132 log_file << message << std::flush;
133}
134
135void ZmqLogger::Path(std::string new_path)
136{
137 // Update path
138 file_path = new_path;
139
140 // Close file (if already open)
141 if (log_file.is_open())
142 log_file.close();
143
144 // Open file (write + append)
145 log_file.open (file_path.c_str(), std::ios::out | std::ios::app);
146
147 // Get current time and log first message
148 std::time_t now = std::time(0);
149 std::tm* localtm = std::localtime(&now);
150 log_file << "------------------------------------------" << std::endl;
151 log_file << "libopenshot logging: " << std::asctime(localtm);
152 log_file << "------------------------------------------" << std::endl;
153}
154
156{
157 // Disable logger as it no longer needed
158 enabled = false;
159
160 // Close file (if already open)
161 if (log_file.is_open())
162 log_file.close();
163
164 // Close socket (if any)
165 if (publisher != NULL) {
166 // Close an existing bound publisher socket
167 publisher->close();
168 publisher = NULL;
169 }
170
171 // Terminate zmq threads
172 if (context != NULL) {
173 context->close();
174 }
175}
176
177// Append debug information
178void ZmqLogger::AppendDebugMethod(std::string method_name,
179 std::string arg1_name, float arg1_value,
180 std::string arg2_name, float arg2_value,
181 std::string arg3_name, float arg3_value,
182 std::string arg4_name, float arg4_value,
183 std::string arg5_name, float arg5_value,
184 std::string arg6_name, float arg6_value)
185{
186 if (!enabled && !openshot::Settings::Instance()->DEBUG_TO_STDERR)
187 // Don't do anything
188 return;
189
190 {
191 // Create a scoped lock, allowing only a single thread to run the following code at one time
192 const std::lock_guard<std::recursive_mutex> lock(loggerMutex);
193
194 std::stringstream message;
195 message << std::fixed << std::setprecision(4);
196
197 // Construct message
198 message << method_name << " (";
199
200 if (arg1_name.length() > 0)
201 message << arg1_name << "=" << arg1_value;
202
203 if (arg2_name.length() > 0)
204 message << ", " << arg2_name << "=" << arg2_value;
205
206 if (arg3_name.length() > 0)
207 message << ", " << arg3_name << "=" << arg3_value;
208
209 if (arg4_name.length() > 0)
210 message << ", " << arg4_name << "=" << arg4_value;
211
212 if (arg5_name.length() > 0)
213 message << ", " << arg5_name << "=" << arg5_value;
214
215 if (arg6_name.length() > 0)
216 message << ", " << arg6_name << "=" << arg6_value;
217
218 message << ")" << std::endl;
219
220 if (openshot::Settings::Instance()->DEBUG_TO_STDERR) {
221 // Print message to stderr
222 std::clog << message.str();
223 }
224
225 if (enabled) {
226 // Send message through ZMQ
227 Log(message.str());
228 }
229 }
230}
Header file for all Exception classes.
Header file for global Settings class.
Header file for ZeroMQ-based Logger class.
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
Definition Settings.cpp:23
This class is used for logging and sending those logs over a ZemoMQ socket to a listener.
Definition ZmqLogger.h:32
void Close()
Close logger (sockets and/or files)
void Log(std::string message)
Log message to all subscribers of this logger (if any)
void Path(std::string new_path)
Set or change the file path (optional)
void LogToFile(std::string message)
Log message to a file (if path set)
void Connection(std::string new_connection)
Set or change connection info for logger (i.e. tcp://*:5556)
Definition ZmqLogger.cpp:63
void AppendDebugMethod(std::string method_name, std::string arg1_name="", float arg1_value=-1.0, std::string arg2_name="", float arg2_value=-1.0, std::string arg3_name="", float arg3_value=-1.0, std::string arg4_name="", float arg4_value=-1.0, std::string arg5_name="", float arg5_value=-1.0, std::string arg6_name="", float arg6_value=-1.0)
Append debug information.
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
Definition ZmqLogger.cpp:35
This namespace is the default namespace for all code in the openshot library.
Definition Compressor.h:29