casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LogSink.h
Go to the documentation of this file.
1 //# LogSink.h: Distribute LogMessages to their destination(s)
2 //# Copyright (C) 1996,2000,2001,2003,2016
3 //# Associated Universities, Inc. Washington DC, USA.
4 //#
5 //# This library is free software; you can redistribute it and/or modify it
6 //# under the terms of the GNU Library General Public License as published by
7 //# the Free Software Foundation; either version 2 of the License, or (at your
8 //# option) any later version.
9 //#
10 //# This library is distributed in the hope that it will be useful, but WITHOUT
11 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 //# License for more details.
14 //#
15 //# You should have received a copy of the GNU Library General Public License
16 //# along with this library; if not, write to the Free Software Foundation,
17 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 //#
19 //# Correspondence concerning AIPS++ should be addressed as follows:
20 //# Internet email: aips2-request@nrao.edu.
21 //# Postal address: AIPS++ Project Office
22 //# National Radio Astronomy Observatory
23 //# 520 Edgemont Road
24 //# Charlottesville, VA 22903-2475 USA
25 //#
26 //#
27 //# $Id$
28 
29 #ifndef CASA_LOGSINK_H
30 #define CASA_LOGSINK_H
31 
32 #include <casacore/casa/aips.h>
34 
37 #include <casacore/casa/iosfwd.h>
38 
39 #include <mutex>
40 
41 namespace casacore { //# NAMESPACE CASACORE - BEGIN
42 
43 // <summary>
44 // Distribute LogMessages to their destination(s)
45 // </summary>
46 
47 // <use visibility=export>
48 
49 // <reviewed reviewer="wbrouw" date="1996/08/21" tests="tLogging.cc" demos="dLogging.cc">
50 // </reviewed>
51 
52 // <prerequisite>
53 // <li> <linkto class="LogMessage">LogMessage</linkto>
54 // <li> <linkto class="LogSinkInterface">LogSinkInterface</linkto>, if you are
55 // interested in extending the set of destinations a <src>LogMessage</src> can
56 // be sent.
57 // </prerequisite>
58 //
59 // <etymology>
60 // Log as in "Log Book." Sink from its common usage ("source/sink") as a thing
61 // which can accept some substance or energy.
62 // </etymology>
63 //
64 // <synopsis>
65 // The LogSink class supplies the destination for
66 // <linkto class="LogMessage">LogMessage</linkto>s. There are two destinations
67 // available through the <src>LogSink</src>
68 // <ol>
69 // <li> A <i>global</i> destination, which is shared by all LogSinks. The global
70 // destination will typically be a GUI window or standard output.
71 // <li> A <i>local</i> destination which is intended to log changes to
72 // particular dataset(s). The local destination will typically be a
73 // Casacore <linkto class="Table">Table</linkto>, but there is also
74 // a local sink for temporary storage in memory.
75 // </ol>
76 // Normally the <src>post()</src> member function will be called which
77 // sends the message to both the global and local destinations, however one or
78 // the other may be chosen via <src>LogSink::postGlobally()</src> and
79 // <src>postLocally()</src> member functions.
80 //
81 // The global sink will normally be set by system library code (it defaults to
82 // using <src>cerr</src>. The type of local sink is defined at
83 // construction time. Presently you can choose one of:
84 // <ol>
85 // <li> a <linkto class="NullLogSink">NullLogSink</linkto> which merely
86 // discards the logging messages.
87 // <li> a <linkto class="StreamLogSink">StreamLogSink</linkto> which sends
88 // the log messages to an <src>ostream</src> (typically <src>cerr</src>)
89 // <li> a <linkto class="TableLogSink">TableLogSink</linkto> which sends
90 // the messages to a Casacore <linkto class=Table>Table</linkto>.
91 // </ol>
92 //
93 // Every <src>LogSink</src> has an attached
94 // <linkto class=LogFilterInterface>LogFilterInterface</linkto>
95 // which is used to reject or pass messages.
96 // The local and global sinks have their own filters, so they can
97 // pass different message priorities (e.g., global <src>DEBUGGING</src> and
98 // local <src>NORMAL</src>). Generally applications code shouldn't change the
99 // global filter.
100 //
101 // </synopsis>
102 //
103 // <example>
104 // <srcblock>
105 // LogMessage logMessage(...);
106 // LogSink logger(LogMessage::NORMAL, "logtable"); // log locally to a 'logtable'
107 // logMessage.message("this is a message").line(__LINE__);
108 // logger.post(logMessage); // local and global
109 // </srcblock>
110 // More complete examples are in <linkto file=Logging.h>Logging.h</linkto>.
111 // </example>
112 //
113 // <h3>Advanced topics</h3>
114 // All possible sinks are derived from an abstract base class:
115 // <linkto class=LogSinkInterface>LogSinkInterface</linkto>. If you want to
116 // allow for logging to a different type of sink (i.e. different from
117 // a stream or Table) , you first need to derive a new class from
118 // <src>LogSinkInterface</src>, and then add a new constructor to
119 // <src>LogSink</src>.
120 //
121 // <src>LogSink</src> itself contains a reference to the actual object that
122 // disposes of the messages. Several <src>LogSink</src>'s can share the same
123 // actual sink via the copy constructor or assignment operator.
124 // <srcblock>
125 // LogSink logger1(LogMessage::NORMAL, "logtable");
126 // LogSink logger2(logger1); // logger2 references logger1
127 // logger2.post(message); // ends up in "logtable"
128 // </srcblock>
129 // You can even have different <src>LogFilterInterface</src>'s
130 // attached to the different <src>LogSink</src>s.
131 //
132 // <motivation>
133 // Logging changes to data and informing users what the software is doing in
134 // detail.
135 // </motivation>
136 //
137 // <todo asof="1996/07/24">
138 // <li> More sink types - in particular to Glish.
139 // <li> A "tee" Sink type might be useful.
140 // </todo>
141 
142 class LogSink : public LogSinkInterface
143 {
144 public:
145  //#If you add more sink types, modify the <ol> in the synopsis as well.
146  // Create a null local sink that throws all messages away or create
147  // a memory local sink that holds the messages in memory.
148  // If a filter isn't defined, default to <src>NORMAL</src>.
149  // <group>
151  Bool nullSink = True);
152  explicit LogSink (const LogFilterInterface &filter, Bool nullSink = True);
153  // </group>
154 
155  // Log to an ostream. It is the responsiblity of the caller to ensure that
156  // <src>os</src> will last as long as the <src>LogSink</src>s that use it.
157  // Normally you would use <src>&cerr</src> as the argument.
158  // <group>
159  LogSink (LogMessage::Priority filter, ostream *os,
160  Bool useGlobalSink = True);
161  LogSink (const LogFilterInterface &filter, ostream *os,
162  Bool useGlobalSink = True);
163  // </group>
164 
165  // Log to the given sink.
166  // It is primarily intended to log to a
167  // <linkto class=TableLogSink>TableLogSink</linkto>.
168  LogSink (const LogFilterInterface &filter,
170 
171  // Make a referencing copy of <src>other</src>. That is, if you post a
172  // message to the new object, it behaves as if you had posted it to the
173  // old one (so long as their filters are the same).
174  // <group>
175  LogSink (const LogSink &other);
176  LogSink &operator= (const LogSink &other);
177  // </group>
178 
179  // Temporary to avoid problem that the bool constructor is taken
180  // if a char* is passed.
181  // They are not implemented, so compiler should give warning.
182  // The 3rd argument is added to make it different from current
183  // version which is still in the system library.
184  LogSink (const LogFilterInterface &filter, const String &fileName, Int n=0);
185  LogSink (const LogFilterInterface &filter, const Char* fileName, Int n=0);
186  LogSink (LogMessage::Priority, const String &fileName, Int n=0);
187  LogSink (LogMessage::Priority, const Char* fileName, Int n=0);
188 
189  ~LogSink();
190 
191  // Send <src>message</src> to both the local and global sink. Return
192  // <src>True</src> if it passes either of them.
193  Bool post (const LogMessage &message);
194 
195  // Send <src>message</src> to the global sink only. Returns <src>True</src>
196  // if it passes the filter.
197  static Bool postGlobally (const LogMessage &message);
198  // Send <src>message</src> to the local sink only. Returns <src>True</src>
199  // if it passes the filter.
200  virtual Bool postLocally (const LogMessage &message);
201 
202  // Post <src>message</src> and then throw an <src>AipsError</src> exception
203  // containing <src>message.toString()</src>. It is always posted as a
204  // <src>SEVERE</src> priority message, no matter what
205  // <src>message.priority()</src> says.
206  // <group>
207  template<typename EXC> void postThenThrow (const LogMessage &message,
208  const EXC& exc)
209  { preparePostThenThrow(message, exc); throw exc; }
210  static void postGloballyThenThrow (const LogMessage &message);
211  // </group>
212 
213  // Get number of messages in local sink.
214  virtual uInt nelements() const;
215 
216  // Get given part of the i-th message from the local sink.
217  // <group>
218  virtual Double getTime (uInt i) const;
219  virtual String getPriority (uInt i) const;
220  virtual String getMessage (uInt i) const;
221  virtual String getLocation (uInt i) const;
222  virtual String getObjectID (uInt i) const;
223  // </group>
224 
225  // Write a message (usually from another logsink) into the local one.
226  // The default implementation does nothing.
227  virtual void writeLocally (Double time, const String& message,
228  const String& priority, const String& location,
229  const String& objectID);
230 
231  // Clear the local sink (i.e. remove all messages from it).
232  virtual void clearLocally();
233 
234  //# Bring out of LogSinkInterface only for documentation purposes
235  // Get or set the filter of this particular <src>LogSink</src>.
236  // <group>
237  virtual const LogFilterInterface &filter() const;
238  virtual LogSinkInterface &filter (const LogFilterInterface &filter);
239  // </group>
240 
241  // Change the sink that this <src>LogSink</src> actually uses.
242  // <group>
243  const LogSinkInterface &localSink() const;
245  LogSink &localSink (LogSinkInterface *&fromNew);
246  // </group>
247 
248  // Get/set the global sink or check if the global sink is null. The global
249  // sink defaults to using <src>cerr</src>. Generally applications code
250  // shouldn't change the global sink. More so, calling globalSink(fromNew)
251  // while using the global sink is not thread-safe. And fromNew is set to 0.
252  // <group>
253  static LogSinkInterface &globalSink();
254  static void globalSink (LogSinkInterface *&fromNew);
255  static Bool nullGlobalSink();
256  // </group>
257 
258  // Write any pending output (by default also the global sink).
259  virtual void flush (Bool global=True);
260 
261  // Returns the id for this class...
262  static String localId( );
263  // Returns the id of the LogSink in use...
264  String id( ) const;
265 
266 private:
267 
268  // LsiIntermediate is a helper class to allow LogSinkInterface to implement
269  // semantics that allow causing all classes accessing the log sink to be
270  // aimed at a different sink object. This used to be done by using an
271  // odd "replace" method in CountedPtr; however, this is functionality is
272  // being removed to CountedPtr as it is modernized so this class was
273  // created to serve this narrow purpose.
274 
276 
277  public:
278 
279 
283 
286  Bool operator! () const { return ! logSinkInterface_p;}
287 
288  void replace (LogSinkInterface * newLsi) { delete logSinkInterface_p; logSinkInterface_p = newLsi;}
289 
290  private:
291 
292  // Copy ctor and op= are private and not defined to prevent double-delete.
293 
296 
298 
299  };
300 
301  // Prepare for postThenThrow function.
302  void preparePostThenThrow(const LogMessage &message, const AipsError& x) ;
303 
304  // Create the global sink (attached to cerr). Always called using theirCallOnce.
305  static void createGlobalSink();
306 
307  //# Data members.
310  static std::once_flag theirCallOnceFlag;
311 
312  // The following is a reference to the global sink. It is created to
313  // ensure that the global sink is not destroyed before the last local
314  // reference to it is destroyed. This can happen if you have a static
315  // LogSink (or LogIO).
318 };
319 
320 
321 
322 } //# NAMESPACE CASACORE - END
323 
324 #endif
int Int
Definition: aipstype.h:50
LsiIntermediate & operator=(const LsiIntermediate &)
static void createGlobalSink()
Create the global sink (attached to cerr).
Abstract base class for filtering LogMessages.
LogSinkInterface * operator->()
Definition: LogSink.h:285
TableExprNode time(const TableExprNode &node)
Definition: ExprNode.h:1580
static String localId()
Returns the id for this class...
virtual const LogFilterInterface & filter() const
Get or set the filter of this particular LogSink.
String id() const
Returns the id of the LogSink in use...
virtual Bool postLocally(const LogMessage &message)
Send message to the local sink only.
char Char
Definition: aipstype.h:46
LogSink(LogMessage::Priority filter=LogMessage::NORMAL, Bool nullSink=True)
Create a null local sink that throws all messages away or create a memory local sink that holds the m...
virtual String getPriority(uInt i) const
LsiIntermediate is a helper class to allow LogSinkInterface to implement semantics that allow causing...
Definition: LogSink.h:275
void replace(LogSinkInterface *newLsi)
Definition: LogSink.h:288
static LogSinkInterface & globalSink()
Get/set the global sink or check if the global sink is null.
void postThenThrow(const LogMessage &message, const EXC &exc)
Post message and then throw an AipsError exception containing message.toString(). ...
Definition: LogSink.h:207
LsiIntermediate(LogSinkInterface *lsi)
Definition: LogSink.h:281
Accepts LogMessages and posts them to some destination.
CountedPtr< LsiIntermediate > local_ref_to_global_p
The following is a reference to the global sink.
Definition: LogSink.h:316
Referenced counted pointer for constant data.
Definition: CountedPtr.h:80
Bool post(const LogMessage &message)
Send message to both the local and global sink.
virtual void flush(Bool global=True)
Write any pending output (by default also the global sink).
double Double
Definition: aipstype.h:55
static Bool postGlobally(const LogMessage &message)
Send message to the global sink only.
static void postGloballyThenThrow(const LogMessage &message)
void preparePostThenThrow(const LogMessage &message, const AipsError &x)
Prepare for postThenThrow function.
virtual uInt nelements() const
Get number of messages in local sink.
virtual String getObjectID(uInt i) const
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
LogSinkInterface * logSinkInterface_p
Definition: LogSink.h:297
static std::once_flag theirCallOnceFlag
Definition: LogSink.h:310
CountedPtr< LogSinkInterface > local_sink_p
Definition: LogSink.h:308
virtual String getMessage(uInt i) const
Priority
An &quot;importance&quot; which is assigned to each LogMessage.
Definition: LogMessage.h:105
Base class for all Casacore library errors.
Definition: Error.h:134
Distribute LogMessages to their destination(s)
Definition: LogSink.h:142
Bool useGlobalSink_p
Definition: LogSink.h:317
const LogSinkInterface & localSink() const
Change the sink that this LogSink actually uses.
String: the storage and methods of handling collections of characters.
Definition: String.h:225
static CountedPtr< LsiIntermediate > * global_sink_p
Definition: LogSink.h:309
virtual void clearLocally()
Clear the local sink (i.e.
LogSinkInterface & operator*()
Definition: LogSink.h:284
const Bool True
Definition: aipstype.h:43
Informational log messages with with time, priority, and origin.
Definition: LogMessage.h:101
virtual String getLocation(uInt i) const
virtual Double getTime(uInt i) const
Get given part of the i-th message from the local sink.
static Bool nullGlobalSink()
LogSink & operator=(const LogSink &other)
unsigned int uInt
Definition: aipstype.h:51
virtual void writeLocally(Double time, const String &message, const String &priority, const String &location, const String &objectID)
Write a message (usually from another logsink) into the local one.