log.h 3.04 KB
Newer Older
1
2
3
4
/*!
 * Copyright (c) 2016 Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE file in the project root for license information.
 */
Guolin Ke's avatar
Guolin Ke committed
5
6
7
#ifndef LIGHTGBM_UTILS_LOG_H_
#define LIGHTGBM_UTILS_LOG_H_

8
9
#include <string>
#include <cstdarg>
Guolin Ke's avatar
Guolin Ke committed
10
11
12
#include <cstdio>
#include <cstdlib>
#include <cstring>
13
#include <exception>
14
#include <iostream>
15
#include <stdexcept>
Guolin Ke's avatar
Guolin Ke committed
16
17
18

namespace LightGBM {

19
#if defined(_MSC_VER)
20
#define THREAD_LOCAL __declspec(thread)
21
22
23
#else
#define THREAD_LOCAL thread_local
#endif
Guolin Ke's avatar
Guolin Ke committed
24

Qiwei Ye's avatar
Qiwei Ye committed
25
26
27
28
#ifndef CHECK
#define CHECK(condition)                                   \
  if (!(condition)) Log::Fatal("Check failed: " #condition \
     " at %s, line %d .\n", __FILE__,  __LINE__);
Guolin Ke's avatar
Guolin Ke committed
29
#endif
Qiwei Ye's avatar
Qiwei Ye committed
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
#ifndef CHECK_EQ
#define CHECK_EQ(a, b) CHECK((a) == (b))
#endif

#ifndef CHECK_NE
#define CHECK_NE(a, b) CHECK((a) != (b))
#endif

#ifndef CHECK_GE
#define CHECK_GE(a, b) CHECK((a) >= (b))
#endif

#ifndef CHECK_LE
#define CHECK_LE(a, b) CHECK((a) <= (b))
#endif

#ifndef CHECK_GT
#define CHECK_GT(a, b) CHECK((a) > (b))
#endif

#ifndef CHECK_LT
#define CHECK_LT(a, b) CHECK((a) < (b))
#endif

Qiwei Ye's avatar
Qiwei Ye committed
55
56
#ifndef CHECK_NOTNULL
#define CHECK_NOTNULL(pointer)                             \
Guolin Ke's avatar
Guolin Ke committed
57
  if ((pointer) == nullptr) LightGBM::Log::Fatal(#pointer " Can't be NULL at %s, line %d .\n", __FILE__,  __LINE__);
Guolin Ke's avatar
Guolin Ke committed
58
#endif
Qiwei Ye's avatar
Qiwei Ye committed
59

Guolin Ke's avatar
Guolin Ke committed
60

Guolin Ke's avatar
Guolin Ke committed
61
62
enum class LogLevel: int {
  Fatal = -1,
Qiwei Ye's avatar
Qiwei Ye committed
63
  Warning = 0,
Qiwei Ye's avatar
Qiwei Ye committed
64
  Info = 1,
Guolin Ke's avatar
Guolin Ke committed
65
  Debug = 2,
Guolin Ke's avatar
Guolin Ke committed
66
67
};

Qiwei Ye's avatar
Qiwei Ye committed
68
69

/*!
70
* \brief A static Log class
Qiwei Ye's avatar
Qiwei Ye committed
71
72
*/
class Log {
Nikita Titov's avatar
Nikita Titov committed
73
 public:
Qiwei Ye's avatar
Qiwei Ye committed
74
75
76
77
  /*!
  * \brief Resets the minimal log level. It is INFO by default.
  * \param level The new minimal log level.
  */
Guolin Ke's avatar
Guolin Ke committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  static void ResetLogLevel(LogLevel level) {
    GetLevel() = level;
  }

  static void Debug(const char *format, ...) {
    va_list val;
    va_start(val, format);
    Write(LogLevel::Debug, "Debug", format, val);
    va_end(val);
  }
  static void Info(const char *format, ...) {
    va_list val;
    va_start(val, format);
    Write(LogLevel::Info, "Info", format, val);
    va_end(val);
  }
Qiwei Ye's avatar
Qiwei Ye committed
94
  static void Warning(const char *format, ...) {
Guolin Ke's avatar
Guolin Ke committed
95
96
    va_list val;
    va_start(val, format);
Qiwei Ye's avatar
Qiwei Ye committed
97
    Write(LogLevel::Warning, "Warning", format, val);
Guolin Ke's avatar
Guolin Ke committed
98
99
100
101
    va_end(val);
  }
  static void Fatal(const char *format, ...) {
    va_list val;
102
    char str_buf[1024];
Guolin Ke's avatar
Guolin Ke committed
103
    va_start(val, format);
104
105
106
107
108
#ifdef _MSC_VER
    vsprintf_s(str_buf, format, val);
#else
    vsprintf(str_buf, format, val);
#endif
Guolin Ke's avatar
Guolin Ke committed
109
    va_end(val);
Guolin Ke's avatar
Guolin Ke committed
110
111
    fprintf(stderr, "[LightGBM] [Fatal] %s\n", str_buf);
    fflush(stderr);
112
    throw std::runtime_error(std::string(str_buf));
Guolin Ke's avatar
Guolin Ke committed
113
  }
Qiwei Ye's avatar
Qiwei Ye committed
114

Nikita Titov's avatar
Nikita Titov committed
115
 private:
Guolin Ke's avatar
Guolin Ke committed
116
117
118
119
120
  static void Write(LogLevel level, const char* level_str, const char *format, va_list val) {
    if (level <= GetLevel()) {  // omit the message with low level
      // write to STDOUT
      printf("[LightGBM] [%s] ", level_str);
      vprintf(format, val);
121
      printf("\n");
Guolin Ke's avatar
Guolin Ke committed
122
123
124
125
      fflush(stdout);
    }
  }

126
  // a trick to use static variable in header file.
Guolin Ke's avatar
Guolin Ke committed
127
  // May be not good, but avoid to use an additional cpp file
128
  static LogLevel& GetLevel() { static THREAD_LOCAL LogLevel level = LogLevel::Info; return level; }
Qiwei Ye's avatar
Qiwei Ye committed
129
};
Guolin Ke's avatar
Guolin Ke committed
130
131

}  // namespace LightGBM
Guolin Ke's avatar
Guolin Ke committed
132
#endif   // LightGBM_UTILS_LOG_H_