Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
logging.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef ORTOOLS_UTIL_LOGGING_H_
15#define ORTOOLS_UTIL_LOGGING_H_
16
17#include <cstdint>
18#include <functional>
19#include <string>
20#include <vector>
21
22#include "absl/strings/str_cat.h" // IWYU pragma: export
23#include "ortools/base/timer.h"
25
26namespace operations_research {
27
28// Prints a positive number with separators for easier reading (ex: 1'348'065).
29std::string FormatCounter(int64_t num);
30
31// Custom logger class. It allows passing callbacks to process log messages.
32//
33// If no callbacks have been added, all logging will use the standard logging
34// facilities. As soon as one callback is added, it is disabled. Unless
35// ForceStandardLogging() has been called.
36//
37// Note that the callbacks will get the message unchanged. No '\n' will be
38// added.
39//
40// Important: This class is currently not thread-safe, it is easy to add a mutex
41// if needed. In CP-SAT, we currently make sure all access to this class do not
42// happen concurrently.
44 public:
46
47 // Enables all logging.
48 //
49 // Note that this is used by the logging macro, but it actually do not
50 // disable logging if LogInfo() is called directly.
51 void EnableLogging(bool enable) { is_enabled_ = enable; }
52
53 // Returns true iff logging is enabled.
54 bool LoggingIsEnabled() const { return is_enabled_; }
55
56 // Should all messages be displayed on stdout ?
57 void SetLogToStdOut(bool enable) { log_to_stdout_ = enable; }
58
59 // Add a callback listening to all information messages.
60 //
61 // They will be run synchronously when LogInfo() is called.
63 std::function<void(const std::string& message)> callback);
64
65 // Removes all callbacks registered via AddInfoLoggingCallback().
67
68 // Returns the number of registered callbacks.
69 int NumInfoLoggingCallbacks() const { return info_callbacks_.size(); }
70
71 // Logs a given information message and dispatch it to all callbacks.
72 void LogInfo(const char* source_filename, int source_line,
73 const std::string& message);
74
75 // Facility to avoid having multi megabytes logs when it brings little
76 // benefits. Logs with the same id will be kept under an average of
77 // throttling_rate_ logs per second.
79 void ThrottledLog(int id, const std::string& message);
80
81 // To not loose the last message of a throttled log, we keep it in memory and
82 // when this function is called we flush logs whose rate is now under the
83 // limit.
84 void FlushPendingThrottledLogs(bool ignore_rates = false);
85
86 private:
87 struct ThrottlingData {
88 int64_t num_displayed_logs = 0;
89 int64_t num_last_skipped_logs = 0;
90 std::string last_skipped_message;
91
92 void UpdateWhenDisplayed() {
93 num_displayed_logs++;
94 num_last_skipped_logs = 0;
95 last_skipped_message = "";
96 }
97 };
98 bool RateIsOk(const ThrottlingData& data);
99
100 bool is_enabled_ = false;
101 bool log_to_stdout_ = false;
102 std::vector<std::function<void(const std::string& message)>> info_callbacks_;
103
104 // TODO(user): Expose? for now we never change this. We start throttling after
105 // throttling_threshold_ logs of a given id, and we enforce a fixed logging
106 // rate afterwards, so that latter burst can still be seen.
107 const int throttling_threshold_ = 20;
108 const double throttling_rate_ = 1.0;
109
110 WallTimer timer_;
111 std::vector<ThrottlingData> id_to_throttling_data_;
112};
113
114#define SOLVER_LOG(logger, ...) \
115 if ((logger)->LoggingIsEnabled()) \
116 (logger)->LogInfo(__FILE__, __LINE__, absl::StrCat(__VA_ARGS__))
117
118#define FORCED_SOLVER_LOG(logger, ...) \
119 (logger)->LogInfo(__FILE__, __LINE__, absl::StrCat(__VA_ARGS__))
120
121// Simple helper class to:
122// - log in an uniform way a "time-consuming" presolve operation.
123// - track a deterministic work limit.
124// - update the deterministic time on finish.
125//
126// TODO(user): this is not presolve specific. Rename.
128 public:
129 PresolveTimer(std::string name, SolverLogger* logger, TimeLimit* time_limit)
130 : name_(std::move(name)),
131 dtime_at_start_(time_limit->GetElapsedDeterministicTime()),
132 logger_(logger),
133 time_limit_(time_limit) {
134 timer_.Start();
135 }
136
137 // Track the work done (which is also the deterministic time).
138 // By default we want a limit of around 1 deterministic seconds.
139 void AddToWork(double dtime) { work_ += dtime; }
140 void TrackSimpleLoop(int size) { work_ += 5e-9 * size; }
141 void TrackHashLookups(int size) { work_ += 5e-8 * size; }
142 void TrackFastLoop(int size) { work_ += 1e-9 * size; }
143 bool WorkLimitIsReached() const { return work_ >= 1.0; }
144
145 // Extra stats=value to display at the end.
146 // We filter value of zero to have less clutter.
147 void AddCounter(std::string name, int64_t count) {
148 if (count == 0) return;
149 counters_.emplace_back(std::move(name), count);
150 }
151
152 // Extra info at the end of the log line.
153 void AddMessage(std::string name) { extra_infos_.push_back(std::move(name)); }
154
155 // Updates dtime and log operation summary.
157
158 // Can be used to bypass logger_->LoggingIsEnabled() to either always disable
159 // in some code path or to always log when debugging.
160 void OverrideLogging(bool value) {
161 override_logging_ = true;
162 log_when_override_ = value;
163 };
164
165 double deterministic_time() const { return work_; }
166 double wtime() const { return timer_.Get(); }
167
168 private:
169 const std::string name_;
170 const double dtime_at_start_;
171
172 WallTimer timer_;
173 SolverLogger* logger_;
174 TimeLimit* time_limit_;
175
176 bool override_logging_ = false;
177 bool log_when_override_ = false;
178 double work_ = 0.0;
179 std::vector<std::pair<std::string, int64_t>> counters_;
180 std::vector<std::string> extra_infos_;
181};
182
183} // namespace operations_research
184
185#endif // ORTOOLS_UTIL_LOGGING_H_
void AddMessage(std::string name)
Definition logging.h:153
void OverrideLogging(bool value)
Definition logging.h:160
void AddCounter(std::string name, int64_t count)
Definition logging.h:147
void AddToWork(double dtime)
Definition logging.h:139
PresolveTimer(std::string name, SolverLogger *logger, TimeLimit *time_limit)
Definition logging.h:129
void EnableLogging(bool enable)
Definition logging.h:51
void ThrottledLog(int id, const std::string &message)
Definition logging.cc:77
void SetLogToStdOut(bool enable)
Definition logging.h:57
void FlushPendingThrottledLogs(bool ignore_rates=false)
Definition logging.cc:95
void AddInfoLoggingCallback(std::function< void(const std::string &message)> callback)
Definition logging.cc:45
void LogInfo(const char *source_filename, int source_line, const std::string &message)
Definition logging.cc:52
OR-Tools root namespace.
std::string FormatCounter(int64_t num)
Definition logging.cc:30
STL namespace.