aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/monlib/dynamic_counters/page.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/monlib/dynamic_counters/page.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/monlib/dynamic_counters/page.cpp')
-rw-r--r--library/cpp/monlib/dynamic_counters/page.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/library/cpp/monlib/dynamic_counters/page.cpp b/library/cpp/monlib/dynamic_counters/page.cpp
new file mode 100644
index 0000000000..5124a47bb3
--- /dev/null
+++ b/library/cpp/monlib/dynamic_counters/page.cpp
@@ -0,0 +1,141 @@
+#include "page.h"
+#include "encode.h"
+
+#include <library/cpp/monlib/service/pages/templates.h>
+#include <library/cpp/string_utils/quote/quote.h>
+
+#include <util/string/split.h>
+#include <util/system/tls.h>
+
+using namespace NMonitoring;
+
+namespace {
+ Y_POD_STATIC_THREAD(TDynamicCounters*)
+ currentCounters(nullptr);
+}
+
+TMaybe<EFormat> ParseFormat(TStringBuf str) {
+ if (str == TStringBuf("json")) {
+ return EFormat::JSON;
+ } else if (str == TStringBuf("spack")) {
+ return EFormat::SPACK;
+ } else if (str == TStringBuf("prometheus")) {
+ return EFormat::PROMETHEUS;
+ } else {
+ return Nothing();
+ }
+}
+
+void TDynamicCountersPage::Output(NMonitoring::IMonHttpRequest& request) {
+ if (OutputCallback) {
+ OutputCallback();
+ }
+
+ TCountableBase::EVisibility visibility{
+ TCountableBase::EVisibility::Public
+ };
+
+ TVector<TStringBuf> parts;
+ StringSplitter(request.GetPathInfo())
+ .Split('/')
+ .SkipEmpty()
+ .Collect(&parts);
+
+ TMaybe<EFormat> format = !parts.empty() ? ParseFormat(parts.back()) : Nothing();
+ if (format) {
+ parts.pop_back();
+ }
+
+ if (!parts.empty() && parts.back() == TStringBuf("private")) {
+ visibility = TCountableBase::EVisibility::Private;
+ parts.pop_back();
+ }
+
+ auto counters = Counters;
+
+ for (const auto& escaped : parts) {
+ const auto part = CGIUnescapeRet(escaped);
+
+ TVector<TString> labels;
+ StringSplitter(part).Split('=').SkipEmpty().Collect(&labels);
+
+ if (labels.size() != 2U)
+ return NotFound(request);
+
+ if (const auto child = counters->FindSubgroup(
+ labels.front(),
+ labels.back())) {
+
+ counters = child;
+ } else {
+ return HandleAbsentSubgroup(request);
+ }
+ }
+
+ if (!format) {
+ currentCounters = counters.Get();
+ THtmlMonPage::Output(request);
+ currentCounters = nullptr;
+ return;
+ }
+
+ IOutputStream& out = request.Output();
+ if (*format == EFormat::JSON) {
+ out << HTTPOKJSON;
+ } else if (*format == EFormat::SPACK) {
+ out << HTTPOKSPACK;
+ } else if (*format == EFormat::PROMETHEUS) {
+ out << HTTPOKPROMETHEUS;
+ } else {
+ ythrow yexception() << "unsupported metric encoding format: " << *format;
+ }
+
+ auto encoder = CreateEncoder(&out, *format, visibility);
+ counters->Accept(TString(), TString(), *encoder);
+ out.Flush();
+}
+
+void TDynamicCountersPage::HandleAbsentSubgroup(IMonHttpRequest& request) {
+ if (UnknownGroupPolicy == EUnknownGroupPolicy::Error) {
+ NotFound(request);
+ } else if (UnknownGroupPolicy == EUnknownGroupPolicy::Ignore) {
+ NoContent(request);
+ } else {
+ Y_FAIL("Unsupported policy set");
+ }
+}
+
+void TDynamicCountersPage::BeforePre(IMonHttpRequest& request) {
+ IOutputStream& out = request.Output();
+ HTML(out) {
+ DIV() {
+ out << "<a href='" << request.GetPath() << "/json'>Counters as JSON</a>";
+ out << " for <a href='https://wiki.yandex-team.ru/solomon/'>Solomon</a>";
+ }
+
+ H5() {
+ out << "Counters subgroups";
+ }
+ UL() {
+ currentCounters->EnumerateSubgroups([&](const TString& name, const TString& value) {
+ LI() {
+ TString pathPart = name + "=" + value;
+ Quote(pathPart, "");
+ out << "\n<a href='" << request.GetPath() << "/" << pathPart << "'>" << name << " " << value << "</a>";
+ }
+ });
+ }
+
+ H4() {
+ out << "Counters as text";
+ }
+ }
+}
+
+void TDynamicCountersPage::OutputText(IOutputStream& out, IMonHttpRequest&) {
+ currentCounters->OutputPlainText(out);
+}
+
+void TDynamicCountersPage::SetUnknownGroupPolicy(EUnknownGroupPolicy value) {
+ UnknownGroupPolicy = value;
+}