diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/lwtrace/lwprobe.h |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/lwtrace/lwprobe.h')
-rw-r--r-- | library/cpp/lwtrace/lwprobe.h | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/library/cpp/lwtrace/lwprobe.h b/library/cpp/lwtrace/lwprobe.h new file mode 100644 index 00000000000..801fc3861b2 --- /dev/null +++ b/library/cpp/lwtrace/lwprobe.h @@ -0,0 +1,110 @@ +#pragma once + +#include "control.h" +#include "probe.h" + +#include <ctype.h> + +namespace NLWTrace { +#ifndef LWTRACE_DISABLE + + // Box that holds dynamically created probe + // NOTE: must be allocated on heap + template <LWTRACE_TEMPLATE_PARAMS> + class TLWProbe: public IBox, public TUserProbe<LWTRACE_TEMPLATE_ARGS> { + private: + // Storage for strings referenced by TEvent + TString Name; + TString Provider; + TVector<TString> Groups; + TVector<TString> Params; + TVector<TProbeRegistry*> Registries; // Note that we assume that registry lives longer than probe + + public: + TLWProbe(const TString& provider, const TString& name, const TVector<TString>& groups, const TVector<TString>& params) + : IBox(true) + , Name(name) + , Provider(provider) + , Groups(groups) + , Params(params) + { + // initialize TProbe + TProbe& probe = this->Probe; + probe.Init(); + + // initialize TEvent + Y_VERIFY(IsCppIdentifier(Name), "probe '%s' is not C++ identifier", Name.data()); + Y_VERIFY(IsCppIdentifier(Provider), "provider '%s' is not C++ identifier in probe %s", Provider.data(), Name.data()); + probe.Event.Name = Name.c_str(); + Zero(probe.Event.Groups); + probe.Event.Groups[0] = Provider.c_str(); + auto i = Groups.begin(), ie = Groups.end(); + Y_VERIFY(Groups.size() < LWTRACE_MAX_GROUPS, "too many groups in probe %s", Name.data()); + for (size_t n = 1; n < LWTRACE_MAX_GROUPS && i != ie; n++, ++i) { + Y_VERIFY(IsCppIdentifier(*i), "group '%s' is not C++ identifier in probe %s", i->data(), Name.data()); + probe.Event.Groups[n] = i->c_str(); + } + + // initialize TSignature + using TUsrSign = TUserSignature<LWTRACE_TEMPLATE_ARGS>; + Y_VERIFY(TUsrSign::ParamCount == (int)Params.size(), "param count mismatch in probe %s: %d != %d", + Name.data(), int(Params.size()), TUsrSign::ParamCount); + TSignature& signature = probe.Event.Signature; + signature.ParamTypes = TUsrSign::ParamTypes; + Zero(signature.ParamNames); + auto j = Params.begin(), je = Params.end(); + for (size_t n = 0; n < LWTRACE_MAX_PARAMS && j != je; n++, ++j) { + Y_VERIFY(IsCppIdentifier(*j), "param '%s' is not C++ identifier in probe %s", j->data(), Name.data()); + signature.ParamNames[n] = j->c_str(); + } + signature.ParamCount = TUsrSign::ParamCount; + signature.SerializeParamsFunc = &TUsrSign::SerializeParams; + signature.CloneParamsFunc = &TUsrSign::CloneParams; + signature.DestroyParamsFunc = &TUsrSign::DestroyParams; + signature.SerializeToPbFunc = &TUsrSign::SerializeToPb; + signature.DeserializeFromPbFunc = &TUsrSign::DeserializeFromPb; + + // register probe in global registry + Register(*Singleton<NLWTrace::TProbeRegistry>()); + } + + ~TLWProbe() { + Unregister(); + } + + void Register(TProbeRegistry& reg) { + Registries.push_back(®); + reg.AddProbe(TBoxPtr(this)); // NOTE: implied `this' object is created with new operator + } + + void Unregister() { + // TODO[serxa]: make sure registry never dies before probe it contain + // TODO[serxa]: make sure probe never dies before TSession that uses it + for (TProbeRegistry* reg : Registries) { + reg->RemoveProbe(&this->Probe); + } + } + + TProbe* GetProbe() override { + return &this->Probe; + } + + private: + static bool IsCppIdentifier(const TString& str) { + bool first = true; + for (char c : str) { + if (first) { + first = false; + if (!(isalpha(c) || c == '_')) { + return false; + } + } else if (!(isalnum(c) || c == '_')) { + return false; + } + } + return true; + } + }; + +#endif +} |