This document is for a version of USD that is under development. See this page for the current release.
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
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.
Provide facilities for error handling in script.
Pointer storage with deletion detection.