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