log_settings.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #pragma once
  2. #include "log_iface.h"
  3. #include <util/generic/vector.h>
  4. #include <util/digest/murmur.h>
  5. #include <util/random/easy.h>
  6. namespace NActors {
  7. namespace NLog {
  8. inline const char* PriorityToString(EPrio priority) {
  9. switch (priority) {
  10. case EPrio::Emerg:
  11. return "EMERG";
  12. case EPrio::Alert:
  13. return "ALERT";
  14. case EPrio::Crit:
  15. return "CRIT";
  16. case EPrio::Error:
  17. return "ERROR";
  18. case EPrio::Warn:
  19. return "WARN";
  20. case EPrio::Notice:
  21. return "NOTICE";
  22. case EPrio::Info:
  23. return "INFO";
  24. case EPrio::Debug:
  25. return "DEBUG";
  26. case EPrio::Trace:
  27. return "TRACE";
  28. default:
  29. return "UNKNOWN";
  30. }
  31. }
  32. // You can structure your program to have multiple logical components.
  33. // In this case you can set different log priorities for different
  34. // components. And you can change component's priority while system
  35. // is running. Suspect a component has a bug? Turn DEBUG priority level on
  36. // for this component.
  37. static const int InvalidComponent = -1;
  38. // Functions converts EComponent id to string
  39. using EComponentToStringFunc = std::function<const TString&(EComponent)>;
  40. // Log settings
  41. struct TComponentSettings {
  42. union {
  43. struct {
  44. ui32 SamplingRate;
  45. ui8 SamplingLevel;
  46. ui8 Level;
  47. } X;
  48. ui64 Data;
  49. } Raw;
  50. TComponentSettings(TAtomicBase data) {
  51. Raw.Data = (ui64)data;
  52. }
  53. TComponentSettings(ui8 level, ui8 samplingLevel, ui32 samplingRate) {
  54. Raw.X.Level = level;
  55. Raw.X.SamplingLevel = samplingLevel;
  56. Raw.X.SamplingRate = samplingRate;
  57. }
  58. };
  59. struct TSettings: public TThrRefBase {
  60. public:
  61. TActorId LoggerActorId;
  62. EComponent LoggerComponent;
  63. ui64 TimeThresholdMs;
  64. ui64 BufferSizeLimitBytes;
  65. bool AllowDrop;
  66. TDuration ThrottleDelay;
  67. TArrayHolder<TAtomic> ComponentInfo;
  68. TVector<TString> ComponentNames;
  69. EComponent MinVal;
  70. EComponent MaxVal;
  71. EComponent Mask;
  72. EPriority DefPriority;
  73. EPriority DefSamplingPriority;
  74. ui32 DefSamplingRate;
  75. bool UseLocalTimestamps;
  76. enum ELogFormat {
  77. PLAIN_FULL_FORMAT,
  78. PLAIN_SHORT_FORMAT,
  79. JSON_FORMAT
  80. };
  81. ELogFormat Format;
  82. TString ShortHostName;
  83. TString ClusterName;
  84. TString MessagePrefix;
  85. // The best way to provide minVal, maxVal and func is to have
  86. // protobuf enumeration of components. In this case protoc
  87. // automatically generates YOURTYPE_MIN, YOURTYPE_MAX and
  88. // YOURTYPE_Name for you.
  89. TSettings(const TActorId& loggerActorId, const EComponent loggerComponent,
  90. EComponent minVal, EComponent maxVal, EComponentToStringFunc func,
  91. EPriority defPriority, EPriority defSamplingPriority = PRI_DEBUG,
  92. ui32 defSamplingRate = 0, ui64 timeThresholdMs = 1000, ui64 bufferSizeLimitBytes = 1024 * 1024 * 300);
  93. TSettings(const TActorId& loggerActorId, const EComponent loggerComponent,
  94. EPriority defPriority, EPriority defSamplingPriority = PRI_DEBUG,
  95. ui32 defSamplingRate = 0, ui64 timeThresholdMs = 1000, ui64 bufferSizeLimitBytes = 1024 * 1024 * 300);
  96. void Append(EComponent minVal, EComponent maxVal, EComponentToStringFunc func);
  97. template <typename T>
  98. void Append(T minVal, T maxVal, const TString& (*func)(T)) {
  99. Append(
  100. static_cast<EComponent>(minVal),
  101. static_cast<EComponent>(maxVal),
  102. [func](EComponent c) -> const TString& {
  103. return func(static_cast<T>(c));
  104. }
  105. );
  106. }
  107. inline bool Satisfies(EPriority priority, EComponent component, ui64 sampleBy = 0) const {
  108. // by using Mask we don't get outside of array boundaries
  109. TComponentSettings settings = GetComponentSettings(component);
  110. if (priority > settings.Raw.X.Level) {
  111. if (priority > settings.Raw.X.SamplingLevel) {
  112. return false; // priority > both levels ==> do not log
  113. }
  114. // priority <= sampling level ==> apply sampling
  115. ui32 samplingRate = settings.Raw.X.SamplingRate;
  116. if (samplingRate) {
  117. ui32 samplingValue = sampleBy ? MurmurHash<ui32>((const char*)&sampleBy, sizeof(sampleBy))
  118. : samplingRate != 1 ? RandomNumber<ui32>() : 0;
  119. return (samplingValue % samplingRate == 0);
  120. } else {
  121. // sampling rate not set ==> do not log
  122. return false;
  123. }
  124. } else {
  125. // priority <= log level ==> log
  126. return true;
  127. }
  128. }
  129. inline TComponentSettings GetComponentSettings(EComponent component) const {
  130. Y_DEBUG_ABORT_UNLESS((component & Mask) == component);
  131. // by using Mask we don't get outside of array boundaries
  132. return TComponentSettings(AtomicGet(ComponentInfo[component & Mask]));
  133. }
  134. const char* ComponentName(EComponent component) const {
  135. Y_DEBUG_ABORT_UNLESS((component & Mask) == component);
  136. return ComponentNames[component & Mask].data();
  137. }
  138. int SetLevel(EPriority priority, EComponent component, TString& explanation);
  139. int SetSamplingLevel(EPriority priority, EComponent component, TString& explanation);
  140. int SetSamplingRate(ui32 sampling, EComponent component, TString& explanation);
  141. EComponent FindComponent(const TStringBuf& componentName) const;
  142. static int PowerOf2Mask(int val);
  143. static bool IsValidPriority(EPriority priority);
  144. bool IsValidComponent(EComponent component);
  145. void SetAllowDrop(bool val);
  146. void SetThrottleDelay(TDuration value);
  147. void SetUseLocalTimestamps(bool value);
  148. private:
  149. int SetLevelImpl(
  150. const TString& name, bool isSampling,
  151. EPriority priority, EComponent component, TString& explanation);
  152. };
  153. }
  154. }