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