Loading...
Searching...
No Matches
Log.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef DRAIN_LOG_H_
33#define DRAIN_LOG_H_
34
35#include <cstddef> // nullptr
36#include <stdlib.h>
37#include <sstream>
38#include <string>
39#include <iostream>
40#include <fstream>
41#include <stdexcept>
42
43//#include <ctime>
44#include <sys/time.h>
45#include <string.h> // strrchr()
46
47#include <syslog.h>
48#include <map>
49
50// Backport nullptr_t streaming for C++14 (operator<< for nullptr_t added in C++17).
51// Global-namespace placement ensures it is found by unqualified lookup in templates.
52#if __cplusplus < 201703L
53#ifndef DRAIN_NULLPTR_STREAM_COMPAT
54#define DRAIN_NULLPTR_STREAM_COMPAT
55inline std::ostream & operator<<(std::ostream & os, std::nullptr_t) {
56 return os << static_cast<const void *>(nullptr);
57}
58#endif
59#endif
60
61#include "StringBuilder.h"
62// #include "TextStyle.h"
63#include "TextStyleVT100.h"
64/*
65#define LOG_EMERG 0 // system is unusable //
66#define LOG_ALERT 1 // action must be taken immediately // RACK examples
67#define LOG_CRIT 2 // critical conditions //
68#define LOG_ERR 3 // error conditions // // File read/write failed
69#define LOG_WARNING 4 // warning conditions // // HDF5 empty or contains no relevant data
70#define LOG_NOTICE 5 // normal but significant condition // No volumes used for a composite
71#define LOG_INFO 6 // informational // // Read/Write File, start/end of operator
72#define LOG_DEBUG 7 // debug-level messages // Store variable
73 10 // Write control files (function input, output)
74 11 // Write intermediate results in files
75 15 // Debug 1D loops
76 20 // Debug 2D loops
77
78Compare with Python: https://docs.python.org/3/library/logging.html#logging-levels
79 */
80
81
82/*
83#ifdef __GNUC__
84 inline std::string className(const std::string & prettyFunction)
85 {
86 const size_t colons = prettyFunction.find("::");
87 if (colons == std::string::npos){
88 return "::";
89 }
90 else {
91 const size_t begin = prettyFunction.substr(0, colons).rfind(" ") + 1;
92 const size_t end = colons - begin;
93 return prettyFunction.substr(begin,end);
94 }
95}
96#define CLASSNAME className(__PRETTY_FUNCTION__)
97#else
98#define CLASSNAME __FILE__
99#endif
100*/
101
102namespace drain {
103
104// using namespace std;
105
108
109 /*
110 Notification(const std::string & key="", int vt100color=35){
111 set(key, vt100color);
112 };
113 */
114
115 template <typename ... T>
116 Notification(const std::string & key, const T &... args){
117
118 this->key = key;
119
120 TextStyleVT100 vt100;
121 std::stringstream sstr;
122 //vt100.write(sstr, args..., key);
123 vt100.append(sstr, args...);
124 vt100color = sstr.str();
125 }
126
127
128 //void set(const std::string & key, int vt100color);
129
130
131 std::string key;
132 std::string vt100color;
133
134};
135
136// extern unsigned int Debug; // getting obsolete
137
139class Logger;
140
142
159class Log {
160
161public:
162
164 typedef unsigned short level_t;
165
166 //typedef std::vector<Notification> notif_dict_t;
167 typedef std::map<int,std::string> status_dict_t;
168
169 const
170 static status_dict_t statusDict;
171
172 // experimental
173 int id = 0;
174
176
179 inline
180 Log(std::ostream & ostr=std::cerr, int verbosityLevel=LOG_WARNING) : ostrPtr(&ostr), verbosityLevel(verbosityLevel) // VT100(true),
181 {
182 resetTime();
183 //std::cerr << "start monitor, level=" << verbosityLevel << std::endl;
184 };
185
186 inline
187 Log(const Log &m) : ostrPtr(m.ostrPtr), verbosityLevel(m.verbosityLevel) { // VT100(m.VT100),
188 resetTime();
189 };
190
191 inline
192 ~Log(){
193 close(); // Note: external ofstream will not be closed.
194 /*
195 if (ostrPtr != nullptr){ // it never is...
196 ostrPtr->close();
197 }
198 */
199 }
200
201
202 inline
203 void setOstr(std::ostream & ostr){
204 /*
205 if (ostrPtr != nullptr){ // it never is...
206 ostrPtr->close();
207 }
208 */
209 close();
210 ostrPtr = &ostr;
211 }
212
213 inline
214 void setOstr(const std::string & filename){
215 /*
216 if (ostrPtr != nullptr){ // it never is...
217 ostrPtr->close();
218 }
219 */
220 close();
221 ofstr.open(filename, std::ios::out);
222 ostrPtr = &ofstr;
223 }
224
226 void close(){
227 if (ofstr.is_open()){
228 ostrPtr = nullptr; // or what, std::cerr ?
229 ofstr.close();
230 }
231 }
232
233 //
234 inline
235 void setVerbosity(level_t level){
236 verbosityLevel = level;
237 };
238
239 void setVerbosity(const std::string & level);
240
241 inline
242 int getVerbosity() const {
243 return verbosityLevel;
244 };
245
246 void flush(level_t level, const std::string & prefix, const std::stringstream & sstr);
247
248 //void flush(level_t level, const Notification & notif, const std::string & prefix, const std::ostream & sstr);
249 void flush(level_t level, const Notification & notif, const std::string & prefix, const std::stringstream & sstr);
250
251
252 inline
253 long getRelativeMilliseconds(){
254 return getMilliseconds() - millisecondsStart;
255 }
256
257 static inline
258 long getMilliseconds(){
259 timeval time;
260 gettimeofday(&time, NULL);
261 return (time.tv_sec * 1000) + (time.tv_usec / 1000);
262 }
263
264 inline
265 void resetTime(){
266 millisecondsStart = getMilliseconds();
267 };
268
269 static
270 bool USE_VT100; // = true;
271
272 // static
273 // const notif_dict_t & getDict();
274
275protected:
276
277 std::ostream *ostrPtr = & std::cerr;
278
279 std::ofstream ofstr;
280
281 level_t verbosityLevel = LOG_NOTICE;
282
283 long millisecondsStart = 0;
284
285 //drain::Dictionary<int, Notification> dict;
286
287};
288
289//extern Log monitor;
290
291Log & getLog();
292
293namespace image {
294
295Log & getImgLog();
296
297} // namespace image
298
299
301class DrainException : public std::runtime_error {
302
303public:
304
305
306
307 // Either this or previous is unneeded?
308 template<typename T,typename ... TT>
309 DrainException(const T &elem, const TT &... rest) : std::runtime_error(drain::StringBuilder<>(elem, rest...)){
310 }
311
312
313};
314
316// #define DRAIN_LOG(name) '#', #name, '=', name
317#define DRAIN_LOG(name) ' ', #name, '=', name
318
319
320
322
325//class Logger : public std::stringstream {
326class Logger : public StreamBuilder<0> {
327
328 std::stringstream & message;
329
330public:
331
332
333
334 typedef Log::level_t level_t;
335
337
339 template <typename ... TT>
340 Logger(const char *filename, const TT & ...args);
341 //Logger(const char *filename, const std::string & name = "");
342
344
346 template <typename ... TT>
347 Logger(Log &log, const char *filename, const TT & ...args); //const char *className = NULL);
348 //Logger(Log &log, const char *filename, const std::string & name = ""); //const char *className = NULL);
349
350 ~Logger();
351
353
357 inline
358 bool isLevel(level_t l){
359 return (monitor.getVerbosity() >= l);
360 };
361
363
367 inline
368 bool isDebug(level_t l=0){
369 return isLevel(LOG_DEBUG+l);
370 //return (monitor.getVerbosity() >= (LOG_DEBUG+l));
371 };
372
373
374
376 template <int L, typename ... TT>
377 inline
378 Logger & start(const TT &... args){
379 static const Notification notif(__FUNCTION__, TextStyle::DIM); //, TextStyle::BOLD
380 initMessage<L>(notif);
381 flush(args...);
382 return *this;
383 }
384
385
387 template<typename ... TT>
388 inline
389 Logger & quit(const TT &... args){
390 static const Notification notif(__FUNCTION__, TextStyle::PURPLE, TextStyle::REVERSE, TextStyle::BOLD);
391 initMessage<LOG_EMERG>(notif);
392 flush(args...);
393 return *this;
394 }
395
397 template<typename ... TT>
398 inline
399 Logger & alert(const TT &... args){
400 static const Notification notif(__FUNCTION__, TextStyle::PURPLE, TextStyle::BOLD);
401 initMessage<LOG_ALERT>(notif);
402 flush(args...);
403 return *this;
404 }
405
407 template<typename ... TT>
408 inline
409 Logger & critical(const TT &... args){
410 static const Notification notif(__FUNCTION__, TextStyle::RED, TextStyle::REVERSE);
411 initMessage<LOG_CRIT>(notif);
412 flush(args...);
413 return *this;
414 }
415
417 /*
418 inline
419 Logger & error(){
420 return initMessage<LOG_ERR>();
421 };
422 */
423
424 template<typename ... TT>
425 inline
426 Logger & error(const TT &... args){
427 static const Notification notif(__FUNCTION__, TextStyle::RED, TextStyle::BOLD);
428 // error();
429 initMessage<LOG_ERR>(notif);
430 flush(args...);
431 return *this;
432 }
433
434
435 // LOG_WARNING
436
438 template<typename ... TT>
439 inline
440 Logger & warn(const TT &... args){
441 // warn();
442 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::BOLD);
443 initMessage<LOG_WARNING>(notif);
444 flush(args...);
445 return *this;
446 }
447
449 template<int L=LOG_WARNING,typename ... TT>
450 inline
451 Logger & discouraged(const TT &... args){
452 //static const Notification notif(__FUNCTION__, 35);
453 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::DIM);
454 initMessage<L>(notif);
455 flush(args...);
456 return *this;
457 }
458
459
461 template<int L=LOG_WARNING,typename ... TT>
462 inline
463 Logger & fail(const TT &... args){
464 //static const Notification notif(__FUNCTION__, 33);
465 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::DIM);
466 initMessage<L>(notif);
467 flush(args...);
468 return *this;
469 }
470
472 // Valid alternative should be displayed.
473 template<int L=LOG_WARNING,typename ... TT>
474 inline
475 Logger & obsolete(const TT &... args){
476 //static const Notification notif(__FUNCTION__, 35);
477 static const Notification notif(__FUNCTION__, TextStyle::PURPLE, TextStyle::DIM, TextStyle::UNDERLINE);
478 initMessage<L>(notif);
479 flush(args...);
480 return *this;
481 }
482
484 template<int L=LOG_WARNING,typename ... TT>
485 inline
486 Logger & attention(const TT &... args){
487 static const Notification notif(__FUNCTION__, TextStyle::CYAN, TextStyle::REVERSE); // , TextStyle::DIM); // 46);
488 initMessage<L>(notif);
489 flush(args...);
490 return *this;
491 }
492
493
494 // LOG_NOTICE
495
497 template<typename ... TT>
498 inline
499 Logger & note(const TT &... args){
500 static const Notification notif(__FUNCTION__, TextStyle::BOLD);
501 initMessage<LOG_NOTICE>(notif);
502 //initMessage<LOG_NOTICE>();
503 flush(args...);
504 return *this;
505 }
506
508 template<int L=LOG_NOTICE,typename ... TT>
509 inline
510 Logger & suspicious(const TT &... args){
511 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::DIM);
512 initMessage<L>(notif);
513 flush(args...);
514 return *this;
515 }
516
517
519 template<int L=LOG_NOTICE,typename ... TT>
520 inline
521 Logger & unimplemented(const TT &... args){
522 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::BOLD); // , 35); // , TextStyle::OVERLINE
523 initMessage<L>(notif);
524 flush(args...);
525 return *this;
526 }
527
529 template<int L=LOG_NOTICE,typename ... TT>
530 inline
531 Logger & deprecating(const TT &... args){
532 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::DIM, TextStyle::UNDERLINE); //33);
533 initMessage<L>(notif);
534 flush(args...);
535 return *this;
536 }
537
539 template<int L=LOG_NOTICE,typename ... TT>
540 inline
541 Logger & special(const TT &... args){
542 static const Notification notif(__FUNCTION__, TextStyle::CYAN); //36);
543 initMessage<L>(notif);
544 flush(args...);
545 return *this;
546 }
547
548
549 template<int L=LOG_NOTICE,typename ... TT>
550 inline
551 Logger & experimental(const TT &... args){
552 static const Notification notif(__FUNCTION__, TextStyle::CYAN, TextStyle::REVERSE, TextStyle::DIM); // 94);
553 initMessage<L>(notif);
554 flush(args...);
555 return *this;
556 }
557
558 template<int L=LOG_NOTICE,typename ... TT>
559 inline
560 Logger & advice(const TT &... args){
561 static const Notification notif(__FUNCTION__, TextStyle::Colour::PURPLE);// 40); ,
562 initMessage<L>(notif);
563 flush(args...);
564 return *this;
565 }
566
567
568 // LOG_INFO
569
570 template<typename ... TT>
571 inline
572 Logger & info(const TT &... args){
573 static const Notification notif(__FUNCTION__, TextStyle::WHITE); //32);
574 initMessage<LOG_INFO>(notif);
575 // initMessage<LOG_INFO>();
576 flush(args...);
577 return *this;
578 }
579
580 template<int L=LOG_INFO,typename ... TT>
581 inline
582 Logger & ok(const TT &... args){
583 static const Notification notif(__FUNCTION__, TextStyle::GREEN); //32);
584 initMessage<L>(notif);
585 flush(args...);
586 return *this;
587 }
588
590 template<int L=LOG_INFO,typename ... TT>
591 inline
592 Logger & accept(const TT &... args){
593 //static const Notification notif(__FUNCTION__, 42);
594 static const Notification notif(__FUNCTION__, TextStyle::GREEN, TextStyle::REVERSE, TextStyle::DIM);
595 initMessage<L>(notif);
596 flush(args...);
597 return *this;
598 }
599
601
604 template<int L=LOG_INFO,typename ... TT>
605 inline
606 Logger & pending(const TT &... args){
607 //static const Notification notif(__FUNCTION__, 42);
608 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::REVERSE, TextStyle::DIM);
609 initMessage<L>(notif);
610 flush(args...);
611 return *this;
612 }
613
615
618 template<int L=LOG_INFO,typename ... TT>
619 inline
620 Logger & reject(const TT &... args){
621 // static const Notification notif(__FUNCTION__, 41);
622 static const Notification notif(__FUNCTION__, TextStyle::RED, TextStyle::REVERSE, TextStyle::DIM);
623 initMessage<L>(notif);
624 flush(args...);
625 return *this;
626 }
627
628
630 template<int L=LOG_INFO,typename ... TT>
631 inline
632 Logger & success(const TT &... args){
633 // static const Notification notif(__FUNCTION__, 92);
634 static const Notification notif(__FUNCTION__, TextStyle::GREEN, TextStyle::DIM);
635 initMessage<L>(notif);
636 flush(args...);
637 return *this;
638 }
639
640
642 template<int L=LOG_INFO,typename ... TT>
643 inline
644 Logger & hint(const TT &... args){
645 static const Notification notif(__FUNCTION__, TextStyle::CYAN, TextStyle::DIM, TextStyle::ITALIC);
646 initMessage<L>(notif);
647 flush(args...);
648 return *this;
649 }
650
651
652 template<int L=LOG_INFO,typename ... TT>
653 inline
654 Logger & revised(const TT &... args){
655 static const Notification notif(__FUNCTION__, TextStyle::YELLOW, TextStyle::ITALIC); // , TextStyle::DIM
656 initMessage<L>(notif);
657 flush(args...);
658 return *this;
659 }
660
661
662
664
674 template<typename ... TT>
675 inline
676 Logger & debug(const TT &... args){
677 static const Notification notif(__FUNCTION__, TextStyle::DIM);
678 initMessage<LOG_DEBUG>(notif);
679 flush(args...);
680 return *this;
681 }
682
684 template<typename ... TT>
685 inline
686 Logger & debug2(const TT &... args){
687 static const Notification notif(__FUNCTION__, TextStyle::DIM, TextStyle::ITALIC);
688 initMessage<LOG_DEBUG+1>(notif);
689 flush(args...);
690 return *this;
691 }
692
693 template<typename ... TT>
694 inline
695 Logger & debug3(const TT &... args){
696 static const Notification notif(__FUNCTION__, TextStyle::CYAN, TextStyle::DIM, TextStyle::ITALIC);
697 initMessage<LOG_DEBUG+2>(notif);
698 flush(args...);
699 return *this;
700 }
701
702
703 inline
704 Logger & log(level_t level){
705 initMessage(level); // avoid
706 return *this;
707 };
708
709 // Experimental! For mout.log(level)(args); !
710 template<typename ... TT>
711 inline
712 Logger & operator()(const TT &... args){
713 flush(args...);
714 return *this;
715 }
716
717
718 static bool TIMING; // = false;
719 static char MARKER;
720
721 bool timing;
722
724 //Logger & timestamp(const std::string & label);
725
729 inline
731 if (TIMING && !timing){
732 initTiming(this->prefix);
733 }
734 };
735
739 template<typename ... TT>
740 void startTiming(const TT &... args){
741 if (TIMING && !timing){ // consider error if already timing?
742 initTiming(args...);
743 }
744 }
745
746 //template<typename ... TT>
747 //void endTiming(const TT &... args){
748 void endTiming(){
749 if (timing){
750 time = monitor.getMilliseconds() - time;
751 std::cerr << "TIMING:" << MARKER << "</div> ";
752 //describeTiming(args...); // STORE timing label?
753 // << ": "
754 std::cerr << "<b>" << (static_cast<float>(time)/1000.0f) << "</b>" << "<br/>" << '\n';
755 /*
756 std::cerr << "TIMING:" << MARKER << "</ol> ";
757 //describeTiming(args...); // STORE timing label?
758 // << ": "
759 std::cerr << "<b>" << (static_cast<float>(time)/1000.0f) << "</b>" << "</li>" << '\n';
760 */
761 timing = false;
762 }
763 }
764
765
766public:
767
768
770 // Logger & timestamp();
771
772
774
775 Logger &operator<<(const std::ostream & sstr) {
776 // TODO if (!message.empty())
777 if (level <= monitor.getVerbosity())
778 message << sstr.rdbuf(); // so simple? See StreamBuilder for additional checks
779 return *this;
780 }
781
782 inline
783 Logger &operator<<(const std::type_info & type) {
784 if (level <= monitor.getVerbosity()){
785 message << Type::call<simpleName>(type);
786 }
787 return *this;
788 }
789
790
791 template <class T>
792 Logger &operator<<(const T & x) {
793 //cerr << "source input:" << x << '\n';
794 if (level <= monitor.getVerbosity())
795 message << x;
796 return *this;
797 }
798
800 inline
801 Logger &operator<<(std::nullptr_t) {
802 if (level <= monitor.getVerbosity())
803 message << static_cast<const void *>(nullptr);
804 return *this;
805 }
806
807 typedef void * oper;
808 static oper endl;
809
810
811 inline
812 void end(){
813 monitor.flush(level, *notif_ptr, prefix, message);
814 }
815
817 inline
818 Logger &operator<<(oper ){ // oper op
819 monitor.flush(level, *notif_ptr, prefix, message);
820 return *this; // <- drop this?
821 }
822
824 inline
826
827 if (&l != this){
828 message << " NOTE: Logger" << __FUNCTION__ << " flush with non-this Logger";
829 }
830 monitor.flush(level, *notif_ptr, prefix, message);
831 return *this;
832 }
833
834 inline
835 int getVerbosity() const {
836 return monitor.getVerbosity();
837 };
838
839protected:
840
841 Log & monitor;
842
843 std::string prefix;
844
845 level_t level;
846 time_t time;
847
848 const Notification * notif_ptr;
849
850protected:
851
852 template<typename ... TT>
853 void initTiming(const TT &... args){
854 timing = true; // consider error if already timing?
855 std::cerr << "TIMING:" << MARKER; // << "<li>";
856 describeTiming(args...);
857 // std::cerr << " [" << prefix << "] <ol>" << '\n';
858 //std::cerr << " <ol>" << '\n';
859 std::cerr << " <div>" << '\n';
860 time = monitor.getMilliseconds();
861 }
862
863
864 template<typename T, typename ... TT>
865 void describeTiming(const T & arg, const TT &... args){
866 std::cerr << arg;
867 describeTiming(args...);
868 }
869
870 inline
871 void describeTiming(){
872 };
873
882
888 template<typename ... TT>
889 inline
890 //void setPrefix(const char * filename, const char * func_name, const TT &... args){
891 void setPrefix(const char * filename, const TT &... args){
892
893 std::stringstream sstr;
894
895 if (filename){
896
897 if (*filename != '\0'){
898
899 const char * s2 = strrchr(filename, '/');
900 if (s2 == nullptr)
901 s2 = filename;
902 else
903 ++s2;
904
906 const char * s3 = strrchr(s2, '.');
907 if (s3 == nullptr)
908 sstr << s2;
909 //prefix.assign(s2);
910 else
911 //prefix.assign(s2, s3-s2);
912 sstr.write(s2, size_t(s3-s2));
913 // prefix.append(":");
914 // sstr << ':';
915 }
916 }
917 // NEW sstr << func_name << ": ";
918 //appendPrefix(sstr, func_name, args...);
919 appendPrefix(sstr, args...);
920 prefix = sstr.str();
921 }
922
923 /*
924 template<typename T, typename ... TT>
925 inline
926 void setPrefix(const TT &... args){
927 std::stringstream sstr;
928 appendPrefix(sstr, args...);
929 prefix = sstr.str();
930 }
931 */
932
933
934 inline
935 void appendPrefix(std::stringstream &){ // sstr
936 }
937
938 template<typename T, typename ... TT>
939 void appendPrefix(std::stringstream & sstr, const T & arg, const TT &... args){
940 sstr << ":" << arg;
941 appendPrefix(sstr, args...);
942 }
943
944 template <level_t L>
945 Logger & initMessage(const Notification & notif){
946 this->notif_ptr = & notif;
947 this->level = L;
948 this->message.str("");
949 return *this;
950 }
951 //void initMessage(level_t level);
952
953 /*
954 template <level_t L>
955 Logger & initMessage(){
956
957 static
958 const Notification & notif = Log::getDict()[L];
959
960 this->notif_ptr = &notif;
961 this->level = L;
962 this->message.str("");
963 return *this;
964 }
965 */
966
968 Logger & initMessage(level_t level);
969
970 /*
971 inline
972 Logger & initMessage(level_t level){
973 static const Notification notif(__FUNCTION__); // TextStyle::DIM, TextStyle::ITALIC);
974 this->notif_ptr = & notif; // Log::getDict()[level];
975 this->level = level;
976 this->message.str("");
977 return *this;
978 }
979 */
980
981 template<typename T, typename ... TT>
982 inline
983 Logger & flush(const T & arg, const TT &... rest){
984 //*this << arg;
985 append(arg);
986 flush(rest...);
987 return *this;
988 }
989
990 template<typename T>
991 inline
992 Logger & flush(const T & arg){
993 // *this << arg;
994 append(arg);
995 monitor.flush(level, *notif_ptr, prefix, message);
996 return *this;
997 }
998
999 inline
1000 Logger & flush(){
1001 return *this;
1002 };
1003
1004 template<typename T>
1005 inline
1006 void append(const T & arg){
1007 *this << arg;
1008 }
1009
1010 /*
1011 inline
1012 Logger & flush(){
1013 monitor.flush(level, *notif_ptr, prefix, message);
1014 return *this;
1015 };
1016 */
1017
1018
1019};
1020
1021
1022// TODO: CHECK: unused parameter 'colour' - this specialization writes a fixed placeholder
1023// "<color>" instead of encoding the actual colour (same pattern as the TextStyle/TextStyleVT100
1024// operator<< stubs, which also emit a fixed placeholder). Looks like unfinished functionality.
1025template <>
1026inline
1027void Logger::append(const TextStyle::Colour & colour){
1028 *this << "<color>";
1029}
1030
1031
1032template <typename ... TT>
1033Logger::Logger(const char *filename, const TT & ...args):
1034 message(*this),
1035 timing(false),
1036 monitor(getLog()),
1037 level(LOG_NOTICE),
1038 time(getLog().getMilliseconds()),
1039 notif_ptr(NULL){
1040 setPrefix(filename, args...);
1041}
1042
1043template <typename ... TT>
1044Logger::Logger(Log &log, const char *filename, const TT & ...args):
1045 message(*this),
1046 timing(false),
1047 monitor(log),
1048 level(LOG_NOTICE),
1049 time(log.getMilliseconds()),
1050 notif_ptr(NULL){
1051 setPrefix(filename, args...);
1052}
1053//std::ostream &operator<<(std::ostream &ostr, const Log &error);
1054
1055
1056}
1057
1058//const std::string FEELU(__FILE__);
1059
1060#endif /* DEBUG_H_ */
1061
1062// Drain
DOC: Add class description.
Definition Log.h:301
Handler for notifications sent by a Logger.
Definition Log.h:159
unsigned short level_t
Log verbosity level type.
Definition Log.h:164
Log(std::ostream &ostr=std::cerr, int verbosityLevel=LOG_WARNING)
Definition Log.h:180
void close()
Closes internal ofstr, if used. External ofstream will not be closed.
Definition Log.h:226
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & start(const TT &... args)
General.
Definition Log.h:378
Logger & operator<<(const std::ostream &sstr)
Send a longer [INFO] preceded with a time stamp.
Definition Log.h:775
Logger & discouraged(const TT &... args)
Warning on user's convention or action that can potentially cause errors or confusions.
Definition Log.h:451
Logger & pending(const TT &... args)
Report a conditional accept/reject, to be completed next.
Definition Log.h:606
Logger & operator<<(const Logger &l)
NEW: sending "mout" insread of "mout.endl" Handling flush operator.
Definition Log.h:825
bool isDebug(level_t l=0)
Returns true, if the debug level of the monitor is at least l.
Definition Log.h:368
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:440
Logger & success(const TT &... args)
Some processing step has completed with desired result.
Definition Log.h:632
Logger & alert(const TT &... args)
Quits immediately, dumps pending messages.
Definition Log.h:399
Logger & operator<<(oper)
Handling flush operator.
Definition Log.h:818
void setPrefix(const char *filename, const TT &... args)
Sets a label that starts every line in the log.
Definition Log.h:891
Logger & obsolete(const TT &... args)
Feature has been removed. Special type of Logger::warn().
Definition Log.h:475
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:676
Logger & quit(const TT &... args)
Quits immediately, dumps pending messages.
Definition Log.h:389
Logger & note(const TT &... args)
For top-level information.
Definition Log.h:499
Logger & hint(const TT &... args)
Like advice, but weaker.
Definition Log.h:644
void startTiming(const TT &... args)
Definition Log.h:740
void startTiming()
Send a short [INFO] preceded with a time stamp.
Definition Log.h:730
Logger & critical(const TT &... args)
Quits immediately, dumps pending messages.
Definition Log.h:409
Logger & special(const TT &... args)
Other useful information.
Definition Log.h:541
Logger & reject(const TT &... args)
Some input has been rejected, for example by a syntax.
Definition Log.h:620
Logger & fail(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:463
bool isLevel(level_t l)
Returns true, if the log monitor level is at least l.
Definition Log.h:358
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:486
Logger(const char *filename, const TT &...args)
Start logging,.
Definition Log.h:1033
Logger & error(const TT &... args)
Echoes.
Definition Log.h:426
Logger & suspicious(const TT &... args)
A weak warning about something going possibly wrong.
Definition Log.h:510
Logger & accept(const TT &... args)
Some input has been accepted, for example by a syntax.
Definition Log.h:592
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:521
Logger & operator<<(std::nullptr_t)
nullptr_t overload: avoids ambiguous operator<< in C++14.
Definition Log.h:801
Logger & deprecating(const TT &... args)
Feature will be removed. Special type of Logger::note().
Definition Log.h:531
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:686
Definition StreamBuilder.h:54
Definition StringBuilder.h:58
Definition TextStyleVT100.h:51
Definition Data.h:1473
std::ostream & operator<<(std::ostream &ostr, const PlainData< DT > &d)
Definition Data.h:631
DOC: Add class description.
Definition Log.h:107