OpenShot Library | libopenshot 0.2.7
ZmqLogger.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @brief Source file for ZeroMQ-based Logger class
4 * @author Jonathan Thomas <jonathan@openshot.org>
5 *
6 * @ref License
7 */
8
9/* LICENSE
10 *
11 * Copyright (c) 2008-2019 OpenShot Studios, LLC
12 * <http://www.openshotstudios.com/>. This file is part of
13 * OpenShot Library (libopenshot), an open-source project dedicated to
14 * delivering high quality video editing and animation solutions to the
15 * world. For more information visit <http://www.openshot.org/>.
16 *
17 * OpenShot Library (libopenshot) is free software: you can redistribute it
18 * and/or modify it under the terms of the GNU Lesser General Public License
19 * as published by the Free Software Foundation, either version 3 of the
20 * License, or (at your option) any later version.
21 *
22 * OpenShot Library (libopenshot) is distributed in the hope that it will be
23 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public License
28 * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29 */
30
31#include "ZmqLogger.h"
32#include "Exceptions.h"
33
34#if USE_RESVG == 1
35 #include "ResvgQt.h"
36#endif
37
38using namespace openshot;
39
40#include <sstream>
41#include <iostream>
42#include <iomanip>
43#include <ctime>
44#include <thread> // for std::this_thread::sleep_for
45#include <chrono> // for std::duration::microseconds
46
47
48// Global reference to logger
49ZmqLogger *ZmqLogger::m_pInstance = NULL;
50
51// Create or Get an instance of the logger singleton
52ZmqLogger *ZmqLogger::Instance()
53{
54 if (!m_pInstance) {
55 // Create the actual instance of logger only once
56 m_pInstance = new ZmqLogger;
57
58 // init ZMQ variables
59 m_pInstance->context = NULL;
60 m_pInstance->publisher = NULL;
61 m_pInstance->connection = "";
62
63 // Default connection
64 m_pInstance->Connection("tcp://*:5556");
65
66 // Init enabled to False (force user to call Enable())
67 m_pInstance->enabled = false;
68
69 #if USE_RESVG == 1
70 // Init resvg logging (if needed)
71 // This can only happen 1 time or it will crash
72 ResvgRenderer::initLog();
73 #endif
74 }
75
76 return m_pInstance;
77}
78
79// Set the connection for this logger
80void ZmqLogger::Connection(std::string new_connection)
81{
82 // Create a scoped lock, allowing only a single thread to run the following code at one time
83 const juce::GenericScopedLock<juce::CriticalSection> lock(loggerCriticalSection);
84
85 // Does anything need to happen?
86 if (new_connection == connection)
87 return;
88 else
89 // Set new connection
90 connection = new_connection;
91
92 if (context == NULL) {
93 // Create ZMQ Context
94 context = new zmq::context_t(1);
95 }
96
97 if (publisher != NULL) {
98 // Close an existing bound publisher socket
99 publisher->close();
100 publisher = NULL;
101 }
102
103 // Create new publisher instance
104 publisher = new zmq::socket_t(*context, ZMQ_PUB);
105
106 // Bind to the socket
107 try {
108 publisher->bind(connection.c_str());
109
110 } catch (zmq::error_t &e) {
111 std::cout << "ZmqLogger::Connection - Error binding to " << connection << ". Switching to an available port." << std::endl;
112 connection = "tcp://*:*";
113 publisher->bind(connection.c_str());
114 }
115
116 // Sleeping to allow connection to wake up (0.25 seconds)
117 std::this_thread::sleep_for(std::chrono::milliseconds(250));
118}
119
120void ZmqLogger::Log(std::string message)
121{
122 if (!enabled)
123 // Don't do anything
124 return;
125
126 // Create a scoped lock, allowing only a single thread to run the following code at one time
127 const juce::GenericScopedLock<juce::CriticalSection> lock(loggerCriticalSection);
128
129 // Send message over socket (ZeroMQ)
130 zmq::message_t reply (message.length());
131 std::memcpy (reply.data(), message.c_str(), message.length());
132
133#if ZMQ_VERSION > ZMQ_MAKE_VERSION(4, 3, 1)
134 // Set flags for immediate delivery (new API)
135 publisher->send(reply, zmq::send_flags::dontwait);
136#else
137 publisher->send(reply);
138#endif
139
140 // Also log to file, if open
141 LogToFile(message);
142}
143
144// Log message to a file (if path set)
145void ZmqLogger::LogToFile(std::string message)
146{
147 // Write to log file (if opened, and force it to write to disk in case of a crash)
148 if (log_file.is_open())
149 log_file << message << std::flush;
150}
151
152void ZmqLogger::Path(std::string new_path)
153{
154 // Update path
155 file_path = new_path;
156
157 // Close file (if already open)
158 if (log_file.is_open())
159 log_file.close();
160
161 // Open file (write + append)
162 log_file.open (file_path.c_str(), std::ios::out | std::ios::app);
163
164 // Get current time and log first message
165 std::time_t now = std::time(0);
166 std::tm* localtm = std::localtime(&now);
167 log_file << "------------------------------------------" << std::endl;
168 log_file << "libopenshot logging: " << std::asctime(localtm);
169 log_file << "------------------------------------------" << std::endl;
170}
171
173{
174 // Disable logger as it no longer needed
175 enabled = false;
176
177 // Close file (if already open)
178 if (log_file.is_open())
179 log_file.close();
180
181 // Close socket (if any)
182 if (publisher != NULL) {
183 // Close an existing bound publisher socket
184 publisher->close();
185 publisher = NULL;
186 }
187}
188
189// Append debug information
190void ZmqLogger::AppendDebugMethod(std::string method_name,
191 std::string arg1_name, float arg1_value,
192 std::string arg2_name, float arg2_value,
193 std::string arg3_name, float arg3_value,
194 std::string arg4_name, float arg4_value,
195 std::string arg5_name, float arg5_value,
196 std::string arg6_name, float arg6_value)
197{
198 if (!enabled && !openshot::Settings::Instance()->DEBUG_TO_STDERR)
199 // Don't do anything
200 return;
201
202 {
203 // Create a scoped lock, allowing only a single thread to run the following code at one time
204 const juce::GenericScopedLock<juce::CriticalSection> lock(loggerCriticalSection);
205
206 std::stringstream message;
207 message << std::fixed << std::setprecision(4);
208
209 // Construct message
210 message << method_name << " (";
211
212 if (arg1_name.length() > 0)
213 message << arg1_name << "=" << arg1_value;
214
215 if (arg2_name.length() > 0)
216 message << ", " << arg2_name << "=" << arg2_value;
217
218 if (arg3_name.length() > 0)
219 message << ", " << arg3_name << "=" << arg3_value;
220
221 if (arg4_name.length() > 0)
222 message << ", " << arg4_name << "=" << arg4_value;
223
224 if (arg5_name.length() > 0)
225 message << ", " << arg5_name << "=" << arg5_value;
226
227 if (arg6_name.length() > 0)
228 message << ", " << arg6_name << "=" << arg6_value;
229
230 message << ")" << std::endl;
231
232 if (openshot::Settings::Instance()->DEBUG_TO_STDERR) {
233 // Print message to stderr
234 std::clog << message.str();
235 }
236
237 if (enabled) {
238 // Send message through ZMQ
239 Log(message.str());
240 }
241 }
242}
Header file for all Exception classes.
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:41
This class is used for logging and sending those logs over a ZemoMQ socket to a listener.
Definition: ZmqLogger.h:57
void Close()
Close logger (sockets and/or files)
Definition: ZmqLogger.cpp:172
void Log(std::string message)
Log message to all subscribers of this logger (if any)
Definition: ZmqLogger.cpp:120
void Path(std::string new_path)
Set or change the file path (optional)
Definition: ZmqLogger.cpp:152
void LogToFile(std::string message)
Log message to a file (if path set)
Definition: ZmqLogger.cpp:145
void Connection(std::string new_connection)
Set or change connection info for logger (i.e. tcp://*:5556)
Definition: ZmqLogger.cpp:80
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.
Definition: ZmqLogger.cpp:190
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:47