userver: userver/error_injection/hook.hpp Source File
Loading...
Searching...
No Matches
hook.hpp
1#pragma once
2
3#include <userver/engine/deadline.hpp>
4#include <userver/engine/sleep.hpp>
5#include <userver/error_injection/settings.hpp>
6#include <userver/logging/log.hpp>
7#include <userver/tracing/span.hpp>
8
9USERVER_NAMESPACE_BEGIN
10
11/// Artificial errors injection framework
12namespace error_injection {
13
14/// Single operation error injection process. Create on the stack,
15/// call PreHook(), do operation, call PostHook().
16class Hook final {
17 public:
18 explicit Hook(const Settings& settings, engine::Deadline deadline);
19
20 /// Must be called just before actual operation. May sleep for some time,
21 /// throw an exception, or do nothing.
22 /// @throws TimeoutException in case of artificial timeout
23 /// @throws ErrorException in case of artificial error
24 template <typename TimeoutException, typename ErrorException>
25 void PreHook() {
26 if (verdict_ == Verdict::Skip) {
27 // fast path
28 return;
29 }
30
31 switch (verdict_) {
32 case Verdict::Error:
33 LOG_ERROR() << "Error injection hook triggered verdict: error";
34 throw ErrorException{"error injection"};
35
37 LOG_ERROR() << "Error injection hook triggered verdict: timeout";
38 {
39 auto scope_time = tracing::Span::CurrentSpan().CreateScopeTime(
40 "error_injection_timeout");
41 engine::InterruptibleSleepUntil(deadline_);
42 }
43 throw TimeoutException{"error injection"};
44
47 case Verdict::Skip:
48 // pass
49 ;
50 }
51 }
52
53 /// Must be called just after operation. May sleep for some time,
54 /// or do nothing.
55 void PostHook() {
56 if (verdict_ == Verdict::Skip) {
57 // fast path
58 return;
59 }
60
61 engine::Deadline deadline = CalcPostHookDeadline();
62 if (deadline.IsReached()) return;
63
64 LOG_ERROR()
65 << "Error injection hook triggered verdict: max-delay / random-delay";
66 auto scope_time =
67 tracing::Span::CurrentSpan().CreateScopeTime("error_injection_delay");
68 engine::InterruptibleSleepUntil(deadline);
69 }
70
71 private:
72 engine::Deadline CalcPostHookDeadline();
73
74 static Verdict ReturnVerdict(const Settings& settings);
75
76 const Verdict verdict_;
77 const engine::Deadline deadline_;
78};
79
80} // namespace error_injection
81
82USERVER_NAMESPACE_END