Caffe2 - C++ API
A deep learning, cross platform ML framework
logging.cc
1 #include "caffe2/core/logging.h"
2 #include "caffe2/core/flags.h"
3 
4 #include <algorithm>
5 #include <cstring>
6 #include <numeric>
7 
8 // Common code that we use regardless of whether we use glog or not.
9 
10 CAFFE2_DEFINE_bool(caffe2_use_fatal_for_enforce, false,
11  "If set true, when CAFFE_ENFORCE is not met, abort instead "
12  "of throwing an exception.");
13 
14 namespace caffe2 {
15 std::string StripBasename(const std::string &full_path) {
16  const char kSeparator = '/';
17  size_t pos = full_path.rfind(kSeparator);
18  if (pos != std::string::npos) {
19  return full_path.substr(pos + 1, std::string::npos);
20  } else {
21  return full_path;
22  }
23 }
24 
25 size_t ReplaceAll(string& s, const char* from, const char* to) {
26  CAFFE_ENFORCE(from && *from);
27  CAFFE_ENFORCE(to);
28 
29  size_t numReplaced = 0;
30  string::size_type lenFrom = std::strlen(from);
31  string::size_type lenTo = std::strlen(to);
32  for (string::size_type pos = s.find(from); pos != string::npos;
33  pos = s.find(from, pos + lenTo)) {
34  s.replace(pos, lenFrom, to);
35  numReplaced++;
36  }
37  return numReplaced;
38 }
39 
40 static std::function<string(void)> FetchStackTrace = []() { return ""; };
41 
42 void SetStackTraceFetcher(std::function<string(void)> fetcher) {
43  FetchStackTrace = fetcher;
44 }
45 
46 static std::function<void(const OperatorDef&)> OperatorLogger =
47  [](const OperatorDef&) { return; };
48 
49 void SetOperatorLogger(std::function<void(const OperatorDef&)> tracer) {
50  OperatorLogger = tracer;
51 }
52 
53 std::function<void(const OperatorDef&)> GetOperatorLogger() {
54  return OperatorLogger;
55 }
56 
57 EnforceNotMet::EnforceNotMet(
58  const char* file,
59  const int line,
60  const char* condition,
61  const string& msg,
62  const void* caller)
63  : msg_stack_{MakeString(
64  "[enforce fail at ",
65  StripBasename(std::string(file)),
66  ":",
67  line,
68  "] ",
69  condition,
70  ". ",
71  msg,
72  " ")},
73  stack_trace_(FetchStackTrace()) {
74  if (FLAGS_caffe2_use_fatal_for_enforce) {
75  LOG(FATAL) << msg_stack_[0];
76  }
77  caller_ = caller;
78  full_msg_ = this->msg();
79 }
80 
81 void EnforceNotMet::AppendMessage(const string& msg) {
82  msg_stack_.push_back(msg);
83  full_msg_ = this->msg();
84 }
85 
86 string EnforceNotMet::msg() const {
87  return std::accumulate(msg_stack_.begin(), msg_stack_.end(), string("")) +
88  stack_trace_;
89 }
90 
91 const char* EnforceNotMet::what() const noexcept {
92  return full_msg_.c_str();
93 }
94 
95 const void* EnforceNotMet::caller() const noexcept {
96  return caller_;
97 }
98 
99 } // namespace caffe2
100 
101 
102 #ifdef CAFFE2_USE_GOOGLE_GLOG
103 
104 #ifdef CAFFE2_USE_GFLAGS
105 // GLOG's minloglevel
106 CAFFE2_DECLARE_int(minloglevel);
107 // GLOG's verbose log value.
108 CAFFE2_DECLARE_int(v);
109 // GLOG's logtostderr value
110 CAFFE2_DECLARE_bool(logtostderr);
111 
112 #else
113 
114 using fLI::FLAGS_minloglevel;
115 using fLI::FLAGS_v;
116 using fLB::FLAGS_logtostderr;
117 
118 #endif // CAFFE2_USE_GFLAGS
119 
120 CAFFE2_DEFINE_int(caffe2_log_level, google::GLOG_ERROR,
121  "The minimum log level that caffe2 will output.");
122 
123 // Google glog's api does not have an external function that allows one to check
124 // if glog is initialized or not. It does have an internal function - so we are
125 // declaring it here. This is a hack but has been used by a bunch of others too
126 // (e.g. Torch).
127 namespace google {
128 namespace glog_internal_namespace_ {
129 bool IsGoogleLoggingInitialized();
130 } // namespace glog_internal_namespace_
131 } // namespace google
132 
133 
134 namespace caffe2 {
135 bool InitCaffeLogging(int* argc, char** argv) {
136  if (*argc == 0) return true;
137 #if !defined(_MSC_VER)
138  // This trick can only be used on UNIX platforms
139  if (!::google::glog_internal_namespace_::IsGoogleLoggingInitialized())
140 #endif
141  {
142  ::google::InitGoogleLogging(argv[0]);
143 #if !defined(_MSC_VER)
144  // This is never defined on Windows
145  ::google::InstallFailureSignalHandler();
146 #endif
147  }
148  // If caffe2_log_level is set and is lower than the min log level by glog,
149  // we will transfer the caffe2_log_level setting to glog to override that.
150  FLAGS_minloglevel = std::min(FLAGS_caffe2_log_level, FLAGS_minloglevel);
151  // If caffe2_log_level is explicitly set, let's also turn on logtostderr.
152  if (FLAGS_caffe2_log_level < google::GLOG_ERROR) {
153  FLAGS_logtostderr = 1;
154  }
155  // Also, transfer the caffe2_log_level verbose setting to glog.
156  if (FLAGS_caffe2_log_level < 0) {
157  FLAGS_v = std::min(FLAGS_v, -FLAGS_caffe2_log_level);
158  }
159  return true;
160 }
161 
162 void ShowLogInfoToStderr() {
163  FLAGS_logtostderr = 1;
164  FLAGS_minloglevel = std::min(FLAGS_minloglevel, google::GLOG_INFO);
165 }
166 } // namespace caffe2
167 
168 #else // !CAFFE2_USE_GOOGLE_GLOG
169 
170 #ifdef ANDROID
171 #include <android/log.h>
172 #endif // ANDROID
173 
174 CAFFE2_DEFINE_int(caffe2_log_level, ERROR,
175  "The minimum log level that caffe2 will output.");
176 
177 namespace caffe2 {
178 bool InitCaffeLogging(int* argc, char** argv) {
179  // When doing InitCaffeLogging, we will assume that caffe's flag paser has
180  // already finished.
181  if (*argc == 0) return true;
183  std::cerr << "InitCaffeLogging() has to be called after "
184  "ParseCaffeCommandLineFlags. Modify your program to make sure "
185  "of this." << std::endl;
186  return false;
187  }
188  if (FLAGS_caffe2_log_level > FATAL) {
189  std::cerr << "The log level of Caffe2 has to be no larger than FATAL("
190  << FATAL << "). Capping it to FATAL." << std::endl;
191  FLAGS_caffe2_log_level = FATAL;
192  }
193  return true;
194 }
195 
197  FLAGS_caffe2_log_level = INFO;
198 }
199 
200 MessageLogger::MessageLogger(const char *file, int line, int severity)
201  : severity_(severity) {
202  if (severity_ < FLAGS_caffe2_log_level) {
203  // Nothing needs to be logged.
204  return;
205  }
206 #ifdef ANDROID
207  tag_ = "native";
208 #else // !ANDROID
209  tag_ = "";
210 #endif // ANDROID
211  /*
212  time_t rawtime;
213  struct tm * timeinfo;
214  time(&rawtime);
215  timeinfo = localtime(&rawtime);
216  std::chrono::nanoseconds ns =
217  std::chrono::duration_cast<std::chrono::nanoseconds>(
218  std::chrono::high_resolution_clock::now().time_since_epoch());
219  */
220  stream_ << "[" << CAFFE2_SEVERITY_PREFIX[std::min(4, FATAL - severity_)]
221  //<< (timeinfo->tm_mon + 1) * 100 + timeinfo->tm_mday
222  //<< std::setfill('0')
223  //<< " " << std::setw(2) << timeinfo->tm_hour
224  //<< ":" << std::setw(2) << timeinfo->tm_min
225  //<< ":" << std::setw(2) << timeinfo->tm_sec
226  //<< "." << std::setw(9) << ns.count() % 1000000000
227  << " " << StripBasename(std::string(file)) << ":" << line << "] ";
228 }
229 
230 // Output the contents of the stream to the proper channel on destruction.
231 MessageLogger::~MessageLogger() {
232  if (severity_ < FLAGS_caffe2_log_level) {
233  // Nothing needs to be logged.
234  return;
235  }
236  stream_ << "\n";
237 #ifdef ANDROID
238  static const int android_log_levels[] = {
239  ANDROID_LOG_FATAL, // LOG_FATAL
240  ANDROID_LOG_ERROR, // LOG_ERROR
241  ANDROID_LOG_WARN, // LOG_WARNING
242  ANDROID_LOG_INFO, // LOG_INFO
243  ANDROID_LOG_DEBUG, // VLOG(1)
244  ANDROID_LOG_VERBOSE, // VLOG(2) .. VLOG(N)
245  };
246  int android_level_index = FATAL - std::min(FATAL, severity_);
247  int level = android_log_levels[std::min(android_level_index, 5)];
248  // Output the log string the Android log at the appropriate level.
249  __android_log_print(level, tag_, "%s", stream_.str().c_str());
250  // Indicate termination if needed.
251  if (severity_ == FATAL) {
252  __android_log_print(ANDROID_LOG_FATAL, tag_, "terminating.\n");
253  }
254 #else // !ANDROID
255  if (severity_ >= FLAGS_caffe2_log_level) {
256  // If not building on Android, log all output to std::cerr.
257  std::cerr << stream_.str();
258  }
259 #endif // ANDROID
260  if (severity_ == FATAL) {
261  DealWithFatal();
262  }
263 }
264 
265 } // namespace caffe2
266 
267 #endif // !CAFFE2_USE_GOOGLE_GLOG
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
void ShowLogInfoToStderr()
A utility to allow one to show log info to stderr after the program starts.
Definition: logging.cc:196
Commandline flags support for Caffe2.
bool CommandLineFlagsHasBeenParsed()
Checks if the commandline flags has already been passed.
Definition: flags.cc:139