summaryrefslogtreecommitdiffstats
path: root/ml/dlib/examples/logger_ex_2.cpp
blob: 99332bffcc094078a51e5258139d8fe87a55a776 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt

/*

    This is a somewhat complex example illustrating the use of the logger object 
    from the dlib C++ Library.  It will demonstrate using multiple loggers and threads.  


    The output of this program looks like this:
    0 INFO  [0] example: This is an informational message.
    0 WARN  [0] example: The variable is bigger than 4!  Its value is 8
    0 INFO  [0] example: make two threads
    0 WARN  [0] example.test_class: warning!  someone called warning()!
    0 INFO  [0] example: we are going to sleep for half a second.
    0 INFO  [1] example.thread: entering our thread
    0 WARN  [1] example.test_class: warning!  someone called warning()!
    0 INFO  [2] example.thread: entering our thread
    0 WARN  [2] example.test_class: warning!  someone called warning()!
  203 INFO  [1] example.thread: exiting our thread
  203 INFO  [2] example.thread: exiting our thread
  503 INFO  [0] example: we just woke up
  503 INFO  [0] example: program ending


*/


#include <dlib/logger.h>
#include <dlib/misc_api.h>
#include <dlib/threads.h>

using namespace dlib;

/*
    Here we create three loggers.  Note that it is the case that:
        - logp.is_child_of(logp) == true
        - logt.is_child_of(logp) == true
        - logc.is_child_of(logp) == true

    logp is the child of itself because all loggers are their own children :)  But the other
    two are child loggers of logp because their names start with logp.name() + "." which means
    that whenever you set a property on a logger it will also set that same property on all of
    the logger's children.
*/
logger logp("example");
logger logt("example.thread");
logger logc("example.test_class");

class test
{
public:
    test ()
    {
        // this message won't get logged because LINFO is too low
        logc << LINFO << "constructed a test object";
    }

    ~test ()
    {
        // this message won't get logged because LINFO is too low
        logc << LINFO << "destructed a test object";
    }

    void warning ()
    {
        logc << LWARN << "warning!  someone called warning()!";
    }
};

void thread (void*)
{
    logt << LINFO << "entering our thread";

    
    test mytest;
    mytest.warning();

    dlib::sleep(200);

    logt << LINFO << "exiting our thread";
}


void setup_loggers (
)
{
    // Create a logger that has the same name as our root logger logp.  This isn't very useful in 
    // this example program but if you had loggers defined in other files then you might not have
    // easy access to them when starting up your program and setting log levels.  This mechanism
    // allows you to manipulate the properties of any logger so long as you know its name.
    logger temp_log("example");

    // For this example I don't want to log debug messages so I'm setting the logging level of 
    // All our loggers to LINFO.  Note that this statement sets all three of our loggers to this
    // logging level because they are all children of temp_log.   
    temp_log.set_level(LINFO);


    // In addition I only want the example.test_class to print LWARN or higher messages so I'm going
    // to set that here too.  Note that we set this value after calling temp_log.set_level(). If we 
    // did it the other way around the set_level() call on temp_log would set logc_temp.level() and 
    // logc.level() back to LINFO since temp_log is a parent of logc_temp.
    logger logc_temp("example.test_class");
    logc_temp.set_level(LWARN);


    // Finally, note that you can also configure your loggers from a text config file.  
    // See the documentation for the configure_loggers_from_file() function for details.
}

int main()
{
    setup_loggers();

    // print our first message.  It will go to cout because that is the default.
    logp << LINFO << "This is an informational message.";

    int variable = 8;

    // Here is a debug message.  It won't print though because its log level is too low (it is below LINFO).
    logp << LDEBUG << "The integer variable is set to " << variable;

    
    if (variable > 4)
        logp << LWARN << "The variable is bigger than 4!  Its value is " << variable;

    logp << LINFO << "make two threads";
    create_new_thread(thread,0);
    create_new_thread(thread,0);

    test mytest;
    mytest.warning();

    logp << LINFO << "we are going to sleep for half a second.";
    // sleep for half a second
    dlib::sleep(500);
    logp << LINFO << "we just woke up";



    logp << LINFO << "program ending";


    // It is also worth pointing out that the logger messages are atomic.  This means, for example, that
    // in the above log statements that involve a string literal and a variable, no other thread can
    // come in and print a log message in-between the literal string and the variable.  This is good
    // because it means your messages don't get corrupted.  However, this also means that you shouldn't 
    // make any function calls inside a logging statement if those calls might try to log a message 
    // themselves since the atomic nature of the logger would cause your application to deadlock.
}