All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
diagnosticMgr.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_DIAGNOSTIC_MGR_H
8#define PXR_BASE_TF_DIAGNOSTIC_MGR_H
9
11
12#include "pxr/pxr.h"
14#include "pxr/base/tf/debug.h"
16#include "pxr/base/tf/error.h"
18#include "pxr/base/tf/status.h"
20#include "pxr/base/tf/warning.h"
21#include "pxr/base/tf/weakPtr.h"
22#include "pxr/base/tf/enum.h"
23#include "pxr/base/tf/api.h"
24
28
29#include <tbb/enumerable_thread_specific.h>
30#include <tbb/spin_rw_mutex.h>
31
32#include <atomic>
33#include <cstdarg>
34#include <list>
35#include <string>
36#include <vector>
37
38PXR_NAMESPACE_OPEN_SCOPE
39
41 TF_LOG_STACK_TRACE_ON_ERROR,
42 TF_LOG_STACK_TRACE_ON_WARNING,
43 TF_ERROR_MARK_TRACKING,
44 TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR
45 );
46
47class TfError;
48class TfErrorMark;
49
55public:
56
57 typedef TfDiagnosticMgr This;
58
59 typedef std::list<TfError> ErrorList;
60
79 typedef ErrorList::iterator ErrorIterator;
80
82 TF_API
83 static std::string GetCodeName(const TfEnum &code);
84
89 TF_API
90 static std::string FormatDiagnostic(const TfEnum &code,
91 const TfCallContext &context, const std::string &msg,
92 const TfDiagnosticInfo &info);
93
111 class Delegate {
112 public:
113 TF_API
114 virtual ~Delegate() = 0;
115
117 virtual void IssueError(TfError const &err) = 0;
118
121 virtual void IssueFatalError(TfCallContext const &context,
122 std::string const &msg) = 0;
123
125 virtual void IssueStatus(TfStatus const &status) = 0;
126
128 virtual void IssueWarning(TfWarning const &warning) = 0;
129
130 protected:
134 TF_API
135 void _UnhandledAbort() const;
136 };
137
139 TF_API static This &GetInstance() {
141 }
142
150 TF_API
151 void AddDelegate(Delegate* delegate);
152
156 TF_API
157 void RemoveDelegate(Delegate* delegate);
158
161 TF_API
162 void SetQuiet(bool quiet) { _quiet = quiet; }
163
165 ErrorIterator GetErrorBegin() { return _errorList.local().begin(); }
166
168 ErrorIterator GetErrorEnd() { return _errorList.local().end(); }
169
172 TF_API
174
178 TF_API
180
185 TF_API
186 void AppendError(TfError const &e);
187
193 TF_API
194 void PostError(TfEnum errorCode, const char* errorCodeString,
195 TfCallContext const &context,
196 const std::string& commentary, TfDiagnosticInfo info,
197 bool quiet);
198
204 TF_API
205 void PostError(const TfDiagnosticBase& diagnostic);
206
211 TF_API
212 void PostWarning(TfEnum warningCode, const char *warningCodeString,
213 TfCallContext const &context, std::string const &commentary,
214 TfDiagnosticInfo info, bool quiet) const;
215
220 TF_API
221 void PostWarning(const TfDiagnosticBase& diagnostic) const;
222
227 TF_API
228 void PostStatus(TfEnum statusCode, const char *statusCodeString,
229 TfCallContext const &context, std::string const &commentary,
230 TfDiagnosticInfo info, bool quiet) const;
231
236 TF_API
237 void PostStatus(const TfDiagnosticBase& diagnostic) const;
238
243 [[noreturn]]
244 TF_API
245 void PostFatal(TfCallContext const &context, TfEnum statusCode,
246 std::string const &msg) const;
247
250 bool HasActiveErrorMark() { return _errorMarkCounts.local() > 0; }
251
252#if !defined(doxygen)
253 //
254 // Public, but *only* meant to be used by the TF_ERROR() macro.
255 //
257 class ErrorHelper {
258 public:
259 ErrorHelper(TfCallContext const &context, TfEnum errorCode,
260 const char* errorCodeString)
261 : _context(context), _errorCode(errorCode),
262 _errorCodeString(errorCodeString)
263 {
264 }
265
266 TF_API
267 void Post(const char* fmt, ...) const
269
270 TF_API
271 void PostQuietly(const char* fmt, ...) const
273
274 TF_API
275 void Post(const std::string& msg) const;
276
277 TF_API
278 void PostWithInfo(
279 const std::string& msg,
280 TfDiagnosticInfo info = TfDiagnosticInfo()) const;
281
282 TF_API
283 void PostQuietly(const std::string& msg,
284 TfDiagnosticInfo info = TfDiagnosticInfo()) const;
285
286 private:
287 TfCallContext _context;
288 TfEnum _errorCode;
289 const char *_errorCodeString;
290 };
291
292 struct WarningHelper {
293 WarningHelper(TfCallContext const &context, TfEnum warningCode,
294 const char *warningCodeString)
295 : _context(context), _warningCode(warningCode),
296 _warningCodeString(warningCodeString)
297 {
298 }
299
300 TF_API
301 void Post(const char* fmt, ...) const
303
304 TF_API
305 void PostQuietly(const char* fmt, ...) const
307
308 TF_API
309 void Post(const std::string &str) const;
310
311 TF_API
312 void PostWithInfo(
313 const std::string& msg,
314 TfDiagnosticInfo info = TfDiagnosticInfo()) const;
315
316 TF_API
317 void PostQuietly(const std::string& msg) const;
318
319 private:
320 TfCallContext _context;
321 TfEnum _warningCode;
322 const char *_warningCodeString;
323 };
324
325 struct StatusHelper {
326 StatusHelper(TfCallContext const &context, TfEnum statusCode,
327 const char *statusCodeString)
328 : _context(context), _statusCode(statusCode),
329 _statusCodeString(statusCodeString)
330 {
331 }
332
333 TF_API
334 void Post(const char* fmt, ...) const
336
337 TF_API
338 void PostQuietly(const char* fmt, ...) const
340
341 TF_API
342 void Post(const std::string &str) const;
343
344 TF_API
345 void PostWithInfo(
346 const std::string& msg,
347 TfDiagnosticInfo info = TfDiagnosticInfo()) const;
348
349 TF_API
350 void PostQuietly(const std::string& msg) const;
351
352 private:
353 TfCallContext _context;
354 TfEnum _statusCode;
355 const char *_statusCodeString;
356 };
357
358 struct FatalHelper {
359 FatalHelper(TfCallContext const &context, TfEnum statusCode)
360 : _context(context),
361 _statusCode(statusCode)
362 {
363 }
364 [[noreturn]]
365 void Post(const std::string &str) const {
366 This::GetInstance().PostFatal(_context, _statusCode, str);
367 }
368 private:
369 TfCallContext _context;
370 TfEnum _statusCode;
371 };
372
373#endif
374
375private:
376
378 virtual ~TfDiagnosticMgr();
379 friend class TfSingleton<This>;
380
381 // Return an iterator to the first error with serial number >= mark, or the
382 // past-the-end iterator, if no such errors exist.
383 TF_API
384 ErrorIterator _GetErrorMarkBegin(size_t mark, size_t *nErrors);
385
386 // Invoked by ErrorMark ctor.
387 inline void _CreateErrorMark() { ++_errorMarkCounts.local(); }
388
389 // Invoked by ErrorMark dtor.
390 inline bool _DestroyErrorMark() { return --_errorMarkCounts.local() == 0; }
391
392 // Report an error, either via delegate or print to stderr, and issue a
393 // notice if this thread of execution is the main thread.
394 void _ReportError(const TfError &err);
395
396 // Splice the errors in src into this thread's local list. Also reassign
397 // serial numbers to all the spliced errors to ensure they work correctly
398 // with local error marks.
399 void _SpliceErrors(ErrorList &src);
400
401 // Helper to append pending error messages to the crash log.
402 void _AppendErrorsToLogText(ErrorIterator i);
403
404 // Helper to fully rebuild the crash log error text when errors are erased
405 // from the middle.
406 void _RebuildErrorLogText();
407
408 // Helper to actually publish log text into the Arch crash handler.
409 void _SetLogInfoForErrors(std::vector<std::string> const &logText) const;
410
411 // A guard used to protect reentrency when adding/removing
412 // delegates as well as posting errors/warnings/statuses
413 mutable tbb::enumerable_thread_specific<bool> _reentrantGuard;
414
415 // The registered delegates.
416 std::vector<Delegate*> _delegates;
417
418 mutable tbb::spin_rw_mutex _delegatesMutex;
419
420 // Global serial number for sorting.
421 std::atomic<size_t> _nextSerial;
422
423 // Thread-specific error list.
424 tbb::enumerable_thread_specific<ErrorList> _errorList;
425
426 // Thread-specific diagnostic log text for pending errors.
427 struct _LogText {
428 void AppendAndPublish(ErrorIterator i, ErrorIterator end);
429 void RebuildAndPublish(ErrorIterator i, ErrorIterator end);
430
431 std::pair<std::vector<std::string>,
432 std::vector<std::string>> texts;
433 bool parity = false;
434 private:
435 void _AppendAndPublishImpl(bool clear,
436 ErrorIterator i, ErrorIterator end);
437 };
438 tbb::enumerable_thread_specific<_LogText> _logText;
439
440 // Thread-specific error mark counts. Use a native key for best performance
441 // here.
442 tbb::enumerable_thread_specific<
443 size_t, tbb::cache_aligned_allocator<size_t>,
444 tbb::ets_key_per_instance> _errorMarkCounts;
445
446 bool _quiet;
447
448 friend class TfError;
449 friend class TfErrorTransport;
450 friend class TfErrorMark;
451};
452
453TF_API_TEMPLATE_CLASS(TfSingleton<TfDiagnosticMgr>);
454
455PXR_NAMESPACE_CLOSE_SCOPE
456
457#endif // PXR_BASE_TF_DIAGNOSTIC_MGR_H
Define function attributes.
#define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
Macro used to indicate a function takes a printf-like specification.
Definition: attributes.h:34
Provide facilities for error handling in script.
Functions for recording call locations.
Represents the base class of an object representing a diagnostic message.
One may set a delegate with the TfDiagnosticMgr which will be called to respond to errors and diagnos...
virtual void IssueStatus(TfStatus const &status)=0
Called when a TF_STATUS() is issued.
virtual void IssueError(TfError const &err)=0
Called when a TfError is posted.
TF_API void _UnhandledAbort() const
Abort the program, but avoid the session logging mechanism.
virtual void IssueWarning(TfWarning const &warning)=0
Called when a TF_WARNING() is issued.
virtual void IssueFatalError(TfCallContext const &context, std::string const &msg)=0
Called when a TF_FATAL_ERROR is issued (or a failed TF_AXIOM).
Singleton class through which all errors and diagnostics pass.
Definition: diagnosticMgr.h:54
TF_API void RemoveDelegate(Delegate *delegate)
Removes all delegates equal to delegate from the current delegates.
TF_API void PostError(const TfDiagnosticBase &diagnostic)
This method will create a TfError, append it to the error list, and pass it to all delegates.
TF_API void AddDelegate(Delegate *delegate)
Add the delegate delegate to the list of current delegates.
TF_API void SetQuiet(bool quiet)
Set whether errors, warnings and status messages should be printed out to the terminal.
TF_API void PostError(TfEnum errorCode, const char *errorCodeString, TfCallContext const &context, const std::string &commentary, TfDiagnosticInfo info, bool quiet)
This method will create a TfError, append it to the error list, and pass it to all delegates.
TF_API ErrorIterator EraseError(ErrorIterator i)
Remove error specified by iterator i.
static TF_API This & GetInstance()
Return the singleton instance.
TF_API void PostFatal(TfCallContext const &context, TfEnum statusCode, std::string const &msg) const
This method will issue a fatal error to all delegates.
ErrorIterator GetErrorEnd()
Return an iterator to the end of this thread's error list.
TF_API void PostWarning(TfEnum warningCode, const char *warningCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const
This method will create a TfWarning and pass it to all delegates.
TF_API void PostStatus(const TfDiagnosticBase &diagnostic) const
This method will create a TfStatus and pass it to all delegates.
TF_API void AppendError(TfError const &e)
Append an error to the list of active errors.
TF_API ErrorIterator EraseRange(ErrorIterator first, ErrorIterator last)
Remove all the errors in [first, last) from this thread's error stream.
bool HasActiveErrorMark()
Return true if an instance of TfErrorMark exists in the current thread of execution,...
TF_API void PostWarning(const TfDiagnosticBase &diagnostic) const
This method will create a TfWarning and pass it to all delegates.
TF_API void PostStatus(TfEnum statusCode, const char *statusCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const
This method will create a TfStatus and pass it to all delegates.
ErrorList::iterator ErrorIterator
Synonym for standard STL iterator to traverse the error list.
Definition: diagnosticMgr.h:79
static TF_API std::string FormatDiagnostic(const TfEnum &code, const TfCallContext &context, const std::string &msg, const TfDiagnosticInfo &info)
Return a human-readable diagnostic message.
ErrorIterator GetErrorBegin()
Return an iterator to the beginning of this thread's error list.
static TF_API std::string GetCodeName(const TfEnum &code)
Returns the name of the given diagnostic code.
An enum class that records both enum type and enum value.
Definition: enum.h:120
Represents an object that contains error information.
Definition: error.h:32
Class used to record the end of the error-list.
Definition: errorMark.h:48
A facility for transporting errors from thread to thread.
Manage a single instance of an object (see.
Definition: singleton.h:105
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
Definition: singleton.h:120
Represents an object that contains information about a status message.
Definition: status.h:28
Represents an object that contains information about a warning.
Definition: warning.h:28
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124
Conditional debugging output class and macros.
Stripped down version of diagnostic.h that doesn't define std::string.
Define preprocessor function name macros.
#define TF_DEBUG_CODES(...)
Define debugging symbols.
Definition: debug.h:376
Define integral types.
STL namespace.
Manage a single instance of an object.
Definitions of basic string utilities in tf.
Pointer storage with deletion detection.