xref: /aosp_15_r20/external/tensorflow/tensorflow/compiler/xla/status_macros.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/compiler/xla/status_macros.h"
17 
18 #include <algorithm>
19 
20 #include "absl/strings/str_cat.h"
21 #include "tensorflow/compiler/xla/types.h"
22 #include "tensorflow/core/platform/logging.h"
23 #include "tensorflow/core/platform/stacktrace.h"
24 
25 namespace xla {
26 namespace status_macros {
27 
28 ABSL_CONST_INIT const char kPossibleAutoJitAlternative[] =
29     "This error might be occurring with the use of xla.compile. If it is not "
30     "necessary that every Op be compiled with XLA, an alternative is to use "
31     "auto_jit with OptimizerOptions.global_jit_level = ON_2 or the environment "
32     "variable TF_XLA_FLAGS=\"tf_xla_auto_jit=2\" which will attempt to use xla "
33     "to compile as much of the graph as the compiler is able to.";
34 
MakeStatus(tensorflow::error::Code code,const std::string & message)35 static Status MakeStatus(tensorflow::error::Code code,
36                          const std::string& message) {
37   return Status(code, message);
38 }
39 
40 // Log the error at the given severity, optionally with a stack trace.
41 // If log_severity is NUM_SEVERITIES, nothing is logged.
LogError(const Status & status,const char * filename,int line,int log_severity,bool should_log_stack_trace)42 static void LogError(const Status& status, const char* filename, int line,
43                      int log_severity, bool should_log_stack_trace) {
44   if (ABSL_PREDICT_TRUE(log_severity != tensorflow::NUM_SEVERITIES)) {
45     std::string stack_trace;
46     if (should_log_stack_trace) {
47       stack_trace = absl::StrCat("\n", tensorflow::CurrentStackTrace());
48     }
49     switch (log_severity) {
50       case tensorflow::INFO:
51         LOG(INFO) << status << stack_trace;
52         break;
53       case tensorflow::WARNING:
54         LOG(WARNING) << status << stack_trace;
55         break;
56       case tensorflow::ERROR:
57         LOG(ERROR) << status << stack_trace;
58         break;
59       case tensorflow::FATAL:
60         LOG(FATAL) << status << stack_trace;
61         break;
62       case tensorflow::NUM_SEVERITIES:
63         break;
64       default:
65         LOG(FATAL) << "Unknown LOG severity " << log_severity;
66     }
67   }
68 }
69 
70 // Make a Status with a code, error message and payload,
71 // and also send it to LOG(<log_severity>) using the given filename
72 // and line (unless should_log is false, or log_severity is
73 // NUM_SEVERITIES).  If should_log_stack_trace is true, the stack
74 // trace is included in the log message (ignored if should_log is
75 // false).
MakeError(const char * filename,int line,tensorflow::error::Code code,const std::string & message,bool should_log,int log_severity,bool should_log_stack_trace)76 static Status MakeError(const char* filename, int line,
77                         tensorflow::error::Code code,
78                         const std::string& message, bool should_log,
79                         int log_severity, bool should_log_stack_trace) {
80   if (ABSL_PREDICT_FALSE(code == tensorflow::error::OK)) {
81     LOG(ERROR) << "Cannot create error with status OK";
82     code = tensorflow::error::UNKNOWN;
83   }
84   const Status status = MakeStatus(code, message);
85   if (ABSL_PREDICT_TRUE(should_log)) {
86     LogError(status, filename, line, log_severity, should_log_stack_trace);
87   }
88   return status;
89 }
90 
91 // This method is written out-of-line rather than in the header to avoid
92 // generating a lot of inline code for error cases in all callers.
CheckNotDone() const93 void MakeErrorStream::CheckNotDone() const { impl_->CheckNotDone(); }
94 
Impl(const char * file,int line,tensorflow::error::Code code,MakeErrorStream * error_stream,bool is_logged_by_default)95 MakeErrorStream::Impl::Impl(const char* file, int line,
96                             tensorflow::error::Code code,
97                             MakeErrorStream* error_stream,
98                             bool is_logged_by_default)
99     : file_(file),
100       line_(line),
101       code_(code),
102       is_done_(false),
103       should_log_(is_logged_by_default),
104       log_severity_(tensorflow::ERROR),
105       should_log_stack_trace_(false),
106       make_error_stream_with_output_wrapper_(error_stream) {}
107 
Impl(const Status & status,PriorMessageHandling prior_message_handling,const char * file,int line,MakeErrorStream * error_stream)108 MakeErrorStream::Impl::Impl(const Status& status,
109                             PriorMessageHandling prior_message_handling,
110                             const char* file, int line,
111                             MakeErrorStream* error_stream)
112     : file_(file),
113       line_(line),
114       // Make sure we show some error, even if the call is incorrect.
115       code_(!status.ok() ? status.code() : tensorflow::error::UNKNOWN),
116       prior_message_handling_(prior_message_handling),
117       prior_message_(status.error_message()),
118       is_done_(false),
119       // Error code type is not visible here, so we can't call
120       // IsLoggedByDefault.
121       should_log_(true),
122       log_severity_(tensorflow::ERROR),
123       should_log_stack_trace_(false),
124       make_error_stream_with_output_wrapper_(error_stream) {
125   DCHECK(!status.ok()) << "Attempted to append/prepend error text to status OK";
126 }
127 
~Impl()128 MakeErrorStream::Impl::~Impl() {
129   // Note: error messages refer to the public MakeErrorStream class.
130 
131   if (!is_done_) {
132     LOG(ERROR) << "MakeErrorStream destructed without getting Status: " << file_
133                << ":" << line_ << " " << stream_.str();
134   }
135 }
136 
GetStatus()137 Status MakeErrorStream::Impl::GetStatus() {
138   // Note: error messages refer to the public MakeErrorStream class.
139 
140   // Getting a Status object out more than once is not harmful, but
141   // it doesn't match the expected pattern, where the stream is constructed
142   // as a temporary, loaded with a message, and then casted to Status.
143   if (is_done_) {
144     LOG(ERROR) << "MakeErrorStream got Status more than once: " << file_ << ":"
145                << line_ << " " << stream_.str();
146   }
147 
148   is_done_ = true;
149 
150   const std::string& stream_str = stream_.str();
151   const std::string str = prior_message_handling_ == kAppendToPriorMessage
152                               ? absl::StrCat(prior_message_, stream_str)
153                               : absl::StrCat(stream_str, prior_message_);
154   if (ABSL_PREDICT_FALSE(str.empty())) {
155     return MakeError(
156         file_, line_, code_,
157         absl::StrCat(str, "Error without message at ", file_, ":", line_),
158         true /* should_log */, tensorflow::ERROR /* log_severity */,
159         should_log_stack_trace_);
160   } else {
161     return MakeError(file_, line_, code_, str, should_log_, log_severity_,
162                      should_log_stack_trace_);
163   }
164 }
165 
CheckNotDone() const166 void MakeErrorStream::Impl::CheckNotDone() const {
167   if (is_done_) {
168     LOG(ERROR) << "MakeErrorStream shift called after getting Status: " << file_
169                << ":" << line_ << " " << stream_.str();
170   }
171 }
172 
173 }  // namespace status_macros
174 }  // namespace xla
175