aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/error/origin_attributes.cpp
blob: 5ff0b039339a4be87b1150fa8f71802fc355d14c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "origin_attributes.h"

#include <library/cpp/yt/assert/assert.h>

#include <library/cpp/yt/misc/thread_name.h>
#include <library/cpp/yt/misc/tls.h>

#include <library/cpp/yt/string/format.h>

#include <util/system/thread.h>

namespace NYT {

////////////////////////////////////////////////////////////////////////////////

YT_DEFINE_THREAD_LOCAL(bool, ErrorSanitizerEnabled, false);
YT_DEFINE_THREAD_LOCAL(TInstant, ErrorSanitizerDatetimeOverride);
YT_DEFINE_THREAD_LOCAL(TSharedRef, ErrorSanitizerLocalHostNameOverride);

TErrorSanitizerGuard::TErrorSanitizerGuard(TInstant datetimeOverride, TSharedRef localHostNameOverride)
    : SavedEnabled_(ErrorSanitizerEnabled())
    , SavedDatetimeOverride_(ErrorSanitizerDatetimeOverride())
    , SavedLocalHostNameOverride_(ErrorSanitizerLocalHostNameOverride())
{
    ErrorSanitizerEnabled() = true;
    ErrorSanitizerDatetimeOverride() = datetimeOverride;
    ErrorSanitizerLocalHostNameOverride() = std::move(localHostNameOverride);
}

TErrorSanitizerGuard::~TErrorSanitizerGuard()
{
    YT_ASSERT(ErrorSanitizerEnabled());

    ErrorSanitizerEnabled() = SavedEnabled_;
    ErrorSanitizerDatetimeOverride() = SavedDatetimeOverride_;
    ErrorSanitizerLocalHostNameOverride() = std::move(SavedLocalHostNameOverride_);
}

bool IsErrorSanitizerEnabled() noexcept
{
    return ErrorSanitizerEnabled();
}

////////////////////////////////////////////////////////////////////////////////

bool TOriginAttributes::operator==(const TOriginAttributes& other) const noexcept
{
    return
        Host == other.Host &&
        Datetime == other.Datetime &&
        Pid == other.Pid &&
        Tid == other.Tid &&
        ExtensionData == other.ExtensionData;
}

void TOriginAttributes::Capture()
{
    if (ErrorSanitizerEnabled()) {
        Datetime = ErrorSanitizerDatetimeOverride();
        HostHolder = ErrorSanitizerLocalHostNameOverride();
        Host = HostHolder.empty() ? TStringBuf() : TStringBuf(HostHolder.Begin(), HostHolder.End());
        return;
    }

    Datetime = TInstant::Now();
    Pid = GetPID();
    Tid = TThread::CurrentThreadId();
    ThreadName = GetCurrentThreadName();
    ExtensionData = NDetail::GetExtensionData();
}

////////////////////////////////////////////////////////////////////////////////

namespace NDetail {

std::optional<TOriginAttributes::TErasedExtensionData> GetExtensionData()
{
    using TFunctor = TOriginAttributes::TErasedExtensionData(*)();

    if (auto strong = NGlobal::GetErasedVariable(GetExtensionDataTag)) {
        return strong->AsConcrete<TFunctor>()();
    }
    return std::nullopt;
}

TString FormatOrigin(const TOriginAttributes& attributes)
{
    using TFunctor = TString(*)(const TOriginAttributes&);

    if (auto strong = NGlobal::GetErasedVariable(FormatOriginTag)) {
        return strong->AsConcrete<TFunctor>()(attributes);
    }

    return Format(
        "%v (pid %v, thread %v)",
        attributes.Host,
        attributes.Pid,
        MakeFormatterWrapper([&] (auto* builder) {
            auto threadName = attributes.ThreadName.ToStringBuf();
            if (threadName.empty()) {
                FormatValue(builder, attributes.Tid, "v");
                return;
            }
            FormatValue(builder, threadName, "v");
        }));
}

} // namespace NDetail

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT