lwprobe.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #pragma once
  2. #include "control.h"
  3. #include "probe.h"
  4. #include <ctype.h>
  5. namespace NLWTrace {
  6. #ifndef LWTRACE_DISABLE
  7. // Box that holds dynamically created probe
  8. // NOTE: must be allocated on heap
  9. template <LWTRACE_TEMPLATE_PARAMS>
  10. class TLWProbe: public IBox, public TUserProbe<LWTRACE_TEMPLATE_ARGS> {
  11. private:
  12. // Storage for strings referenced by TEvent
  13. TString Name;
  14. TString Provider;
  15. TVector<TString> Groups;
  16. TVector<TString> Params;
  17. TVector<TProbeRegistry*> Registries; // Note that we assume that registry lives longer than probe
  18. public:
  19. TLWProbe(const TString& provider, const TString& name, const TVector<TString>& groups, const TVector<TString>& params)
  20. : IBox(true)
  21. , Name(name)
  22. , Provider(provider)
  23. , Groups(groups)
  24. , Params(params)
  25. {
  26. // initialize TProbe
  27. TProbe& probe = this->Probe;
  28. probe.Init();
  29. // initialize TEvent
  30. Y_ABORT_UNLESS(IsCppIdentifier(Name), "probe '%s' is not C++ identifier", Name.data());
  31. Y_ABORT_UNLESS(IsCppIdentifier(Provider), "provider '%s' is not C++ identifier in probe %s", Provider.data(), Name.data());
  32. probe.Event.Name = Name.c_str();
  33. Zero(probe.Event.Groups);
  34. probe.Event.Groups[0] = Provider.c_str();
  35. auto i = Groups.begin(), ie = Groups.end();
  36. Y_ABORT_UNLESS(Groups.size() < LWTRACE_MAX_GROUPS, "too many groups in probe %s", Name.data());
  37. for (size_t n = 1; n < LWTRACE_MAX_GROUPS && i != ie; n++, ++i) {
  38. Y_ABORT_UNLESS(IsCppIdentifier(*i), "group '%s' is not C++ identifier in probe %s", i->data(), Name.data());
  39. probe.Event.Groups[n] = i->c_str();
  40. }
  41. // initialize TSignature
  42. using TUsrSign = TUserSignature<LWTRACE_TEMPLATE_ARGS>;
  43. Y_ABORT_UNLESS(TUsrSign::ParamCount == (int)Params.size(), "param count mismatch in probe %s: %d != %d",
  44. Name.data(), int(Params.size()), TUsrSign::ParamCount);
  45. TSignature& signature = probe.Event.Signature;
  46. signature.ParamTypes = TUsrSign::ParamTypes;
  47. Zero(signature.ParamNames);
  48. auto j = Params.begin(), je = Params.end();
  49. for (size_t n = 0; n < LWTRACE_MAX_PARAMS && j != je; n++, ++j) {
  50. Y_ABORT_UNLESS(IsCppIdentifier(*j), "param '%s' is not C++ identifier in probe %s", j->data(), Name.data());
  51. signature.ParamNames[n] = j->c_str();
  52. }
  53. signature.ParamCount = TUsrSign::ParamCount;
  54. signature.SerializeParamsFunc = &TUsrSign::SerializeParams;
  55. signature.CloneParamsFunc = &TUsrSign::CloneParams;
  56. signature.DestroyParamsFunc = &TUsrSign::DestroyParams;
  57. signature.SerializeToPbFunc = &TUsrSign::SerializeToPb;
  58. signature.DeserializeFromPbFunc = &TUsrSign::DeserializeFromPb;
  59. // register probe in global registry
  60. Register(*Singleton<NLWTrace::TProbeRegistry>());
  61. }
  62. ~TLWProbe() {
  63. Unregister();
  64. }
  65. void Register(TProbeRegistry& reg) {
  66. Registries.push_back(&reg);
  67. reg.AddProbe(TBoxPtr(this)); // NOTE: implied `this' object is created with new operator
  68. }
  69. void Unregister() {
  70. // TODO[serxa]: make sure registry never dies before probe it contain
  71. // TODO[serxa]: make sure probe never dies before TSession that uses it
  72. for (TProbeRegistry* reg : Registries) {
  73. reg->RemoveProbe(&this->Probe);
  74. }
  75. }
  76. TProbe* GetProbe() override {
  77. return &this->Probe;
  78. }
  79. private:
  80. static bool IsCppIdentifier(const TString& str) {
  81. bool first = true;
  82. for (char c : str) {
  83. if (first) {
  84. first = false;
  85. if (!(isalpha(c) || c == '_')) {
  86. return false;
  87. }
  88. } else if (!(isalnum(c) || c == '_')) {
  89. return false;
  90. }
  91. }
  92. return true;
  93. }
  94. };
  95. #endif
  96. }