[CODE HEALTH] Fix clang-tidy bugprone-exception-escape warnings in API#3964
[CODE HEALTH] Fix clang-tidy bugprone-exception-escape warnings in API#3964dbarker wants to merge 14 commits intoopen-telemetry:mainfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3964 +/- ##
==========================================
- Coverage 90.18% 90.06% -0.11%
==========================================
Files 230 230
Lines 7299 7312 +13
==========================================
+ Hits 6582 6585 +3
- Misses 717 727 +10
🚀 New features to boost your workflow:
|
…scape warning in string_util, Address review feedback.
…string utils test.
marcalff
left a comment
There was a problem hiding this comment.
The change to replace nostd::holds_alternative with nostd::get_if is clean and a no brainer.
Please prepare a separate patch to fix all nostd::holds_alternative so this part can be merged out of the way.
This PR can then focus on the try/catch code alone, as it will be more tricky to resolve.
Thanks @marcalff. I've split this up. The nostd::variant access changes are now in #3965. Interested in feedback on the try/catch/unreachable macros given our need to support noexcept builds and analyzers. |
|
Thanks for working on this, this is a delicate topic in opentelemetry-cpp. Some background information, as I understand the history, to help designing the proper fix, and some general comments below. 1. Otel Instrumentation should not kill the applicationWhen an application is instrumented with otel, it makes API calls to otel-cpp. Whatever happens within otel-cpp should not put the application at risk, which is why every API entry point is designed to be 2. The application code can not be trusted to be robustEvery API that returns a pointer (say, a span) can never return a null pointer, because we can not expect the application code to systematically check for null pointer conditions on every single line instrumented. Constantly checking pointers would be very tedious on the application side, and unsafe, possibly causing crashes if a check is missing. For this reason, otel-cpp will never return a null pointer, but will return a "no-op" object instead, that the instrumented code can call without precautions. In other words, we don't want to impose a defensive programming style on the application, when adding opentelemetry instrumentation. 3. Memory allocation and noexceptPoints 1 and 2 are already causing severe constraints, and I am not ever sure it is possible to safely return a pointer on a noop object while not raising exceptions at the same time. When an API returns a Putting aside exceptions caused by Out Of Memory, at least we should make an effort to not raise any other exceptions then. 4. Different build flavorsApplications can be built with, or without, exception support, and we need to accommodate both. Given that we support many compilers/platforms as well, hiding all the details behind 5. Places that need a try-catch blockThere should be very few places handling exceptions in the API itself. Most of the time, the API consist of virtual methods implemented by the SDK, so there is no code. When code is actually provided in-lined in the API, this is for very specific places, like:
so I would expect only a very few try-catch blocks in the whole API. 6. try-catch block styleInstead of hiding all the details behind macros for the try, and more importantly the catch block, we can have more explicit code. For example: This will avoid confusing the compiler, clang-tidy, cpp-check, and avoid complaints that a return code path is missing, code is not reachable, etc, when building with/without exceptions. Given (4) with very few try-catch blocks needed, I think this will work better. 7. What to do when an exception is seen ?Nothing. Do not try to log it, do not call abort, nothing. We can not log anything from the API (the SDK may not even be present), and we definitively can not take the application down with an abort. The worst case is that opentelemetry-cpp will behave like a noop brick if it fails internally. We can have an assert in debug or in maintainer mode to catch failures in CI, but can not do more than that. 8. Internal supporting code does not need to be noexceptCode in the actual API surface, used by the application, needs to be Supporting code, like Because of this, I think we can relax internal helpers to not be |
|
Thanks for the feedback @marcalff. The points makes sense. I'll remove the macros in the PR and we can follow up in a SIG meeting on next steps more broadly for error handling. 1. Otel Instrumentation should not kill the application Your point is focused on instrumentation (using the API) and makes sense. The spec does a good job of highlighting this, and allows cases where the API/SDK may terminate the application on initialization (See error handling)
Failing fast on initialization and perhaps user configurable error response (fail loud or silently) does seem desirable (see last point below). 3. Memory allocation and noexcept Memory allocation is an area for discussion and the codebase is mixed. In most cases memory is allocated with 4. Different build flavors
Is building without exception support a requirement just for the API or to include the SDK, exporters, and detectors? Given the dependencies the project has we may not be able to provide an exception free build of all components that meets the requirements of point 1. The bazel noexept build doesn't include all components currently. 7. What to do when an exception is seen ?
This makes sense and I think should be a requirement for the project (ci should fail on error that would be ignored in production, a maintainer mode flag is a great idea). The spec gives some guidance that extends this to users who may also want a clear signal that something is going wrong.
|
| class StringUtil | ||
| { | ||
| public: | ||
| static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right) noexcept |
There was a problem hiding this comment.
@marcalff this is a good example of a method that may be considered an implementation detail for the API but is currently public. Would removing noexcept from this method be acceptable?
Fixes #3981
Contributes to #2053, #3013
Changes
bugprone-exception-escape (4 warnings)
opentelemetry-cpp/api/include/opentelemetry/trace/trace_state.hopentelemetry-cpp/api/include/opentelemetry/trace/trace_state.hopentelemetry-cpp/api/include/opentelemetry/trace/trace_state.hopentelemetry-cpp/api/include/opentelemetry/trace/trace_state.hFor significant contributions please make sure you have completed the following items:
CHANGELOG.mdupdated for non-trivial changes