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::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 (!::google::glog_internal_namespace_::IsGoogleLoggingInitialized()) {
138  ::google::InitGoogleLogging(argv[0]);
139  ::google::InstallFailureSignalHandler();
140  }
141  // If caffe2_log_level is set and is lower than the min log level by glog,
142  // we will transfer the caffe2_log_level setting to glog to override that.
143  FLAGS_minloglevel = std::min(FLAGS_caffe2_log_level, FLAGS_minloglevel);
144  // If caffe2_log_level is explicitly set, let's also turn on logtostderr.
145  if (FLAGS_caffe2_log_level < google::ERROR) {
146  FLAGS_logtostderr = 1;
147  }
148  // Also, transfer the caffe2_log_level verbose setting to glog.
149  if (FLAGS_caffe2_log_level < 0) {
150  FLAGS_v = std::min(FLAGS_v, -FLAGS_caffe2_log_level);
151  }
152  return true;
153 }
154 } // namespace caffe2
155 
156 #else // !CAFFE2_USE_GOOGLE_GLOG
157 
158 #ifdef ANDROID
159 #include <android/log.h>
160 #endif // ANDROID
161 
162 CAFFE2_DEFINE_int(caffe2_log_level, ERROR,
163  "The minimum log level that caffe2 will output.");
164 
165 namespace caffe2 {
166 bool InitCaffeLogging(int* argc, char** argv) {
167  // When doing InitCaffeLogging, we will assume that caffe's flag paser has
168  // already finished.
169  if (*argc == 0) return true;
171  std::cerr << "InitCaffeLogging() has to be called after "
172  "ParseCaffeCommandLineFlags. Modify your program to make sure "
173  "of this." << std::endl;
174  return false;
175  }
176  if (FLAGS_caffe2_log_level > FATAL) {
177  std::cerr << "The log level of Caffe2 has to be no larger than FATAL("
178  << FATAL << "). Capping it to FATAL." << std::endl;
179  FLAGS_caffe2_log_level = FATAL;
180  }
181  return true;
182 }
183 
184 MessageLogger::MessageLogger(const char *file, int line, int severity)
185  : severity_(severity) {
186  if (severity_ < FLAGS_caffe2_log_level) {
187  // Nothing needs to be logged.
188  return;
189  }
190 #ifdef ANDROID
191  tag_ = "native";
192 #else // !ANDROID
193  tag_ = "";
194 #endif // ANDROID
195  /*
196  time_t rawtime;
197  struct tm * timeinfo;
198  time(&rawtime);
199  timeinfo = localtime(&rawtime);
200  std::chrono::nanoseconds ns =
201  std::chrono::duration_cast<std::chrono::nanoseconds>(
202  std::chrono::high_resolution_clock::now().time_since_epoch());
203  */
204  stream_ << "[" << CAFFE2_SEVERITY_PREFIX[std::min(4, FATAL - severity_)]
205  //<< (timeinfo->tm_mon + 1) * 100 + timeinfo->tm_mday
206  //<< std::setfill('0')
207  //<< " " << std::setw(2) << timeinfo->tm_hour
208  //<< ":" << std::setw(2) << timeinfo->tm_min
209  //<< ":" << std::setw(2) << timeinfo->tm_sec
210  //<< "." << std::setw(9) << ns.count() % 1000000000
211  << " " << StripBasename(std::string(file)) << ":" << line << "] ";
212 }
213 
214 // Output the contents of the stream to the proper channel on destruction.
215 MessageLogger::~MessageLogger() {
216  if (severity_ < FLAGS_caffe2_log_level) {
217  // Nothing needs to be logged.
218  return;
219  }
220  stream_ << "\n";
221 #ifdef ANDROID
222  static const int android_log_levels[] = {
223  ANDROID_LOG_FATAL, // LOG_FATAL
224  ANDROID_LOG_ERROR, // LOG_ERROR
225  ANDROID_LOG_WARN, // LOG_WARNING
226  ANDROID_LOG_INFO, // LOG_INFO
227  ANDROID_LOG_DEBUG, // VLOG(1)
228  ANDROID_LOG_VERBOSE, // VLOG(2) .. VLOG(N)
229  };
230  int android_level_index = FATAL - std::min(FATAL, severity_);
231  int level = android_log_levels[std::min(android_level_index, 5)];
232  // Output the log string the Android log at the appropriate level.
233  __android_log_print(level, tag_, "%s", stream_.str().c_str());
234  // Indicate termination if needed.
235  if (severity_ == FATAL) {
236  __android_log_print(ANDROID_LOG_FATAL, tag_, "terminating.\n");
237  }
238 #else // !ANDROID
239  if (severity_ >= FLAGS_caffe2_log_level) {
240  // If not building on Android, log all output to std::cerr.
241  std::cerr << stream_.str();
242  }
243 #endif // ANDROID
244  if (severity_ == FATAL) {
245  DealWithFatal();
246  }
247 }
248 
249 } // namespace caffe2
250 
251 #endif // !CAFFE2_USE_GOOGLE_GLOG
Simple registry implementation in Caffe2 that uses static variables to register object creators durin...
Commandline flags support for Caffe2.
bool CommandLineFlagsHasBeenParsed()
Checks if the commandline flags has already been passed.
Definition: flags.cc:139