#pragma once #include <util/stream/output.h> #include <util/system/defaults.h> #define WITH_SCOPED(var, value) WITH_SCOPED_I(var, value, Y_GENERATE_UNIQUE_ID(WITH_SCOPED_LABEL_)) #define WITH_SCOPED_I(var, value, label) \ if (auto var = (value)) { \ Y_UNUSED(var); \ goto label; \ } else \ label \ : #define TAG(name) WITH_SCOPED(tmp, ::NMonitoring::name(__stream)) #define TAG_CLASS(name, cls) WITH_SCOPED(tmp, ::NMonitoring::name(__stream, cls)) #define TAG_CLASS_STYLE(name, cls, style) WITH_SCOPED(tmp, ::NMonitoring::name(__stream, {{"class", cls}, {"style", style}})) #define TAG_CLASS_ID(name, cls, id) WITH_SCOPED(tmp, ::NMonitoring::name(__stream, cls, "", id)) #define TAG_CLASS_FOR(name, cls, for0) WITH_SCOPED(tmp, ::NMonitoring::name(__stream, cls, for0)) #define TAG_ATTRS(name, ...) WITH_SCOPED(tmp, ::NMonitoring::name(__stream, ##__VA_ARGS__)) #define HTML(str) WITH_SCOPED(__stream, ::NMonitoring::TOutputStreamRef(str)) #define HEAD() TAG(THead) #define BODY() TAG(TBody) #define HTML_TAG() TAG(THtml) #define DIV() TAG(TDiv) #define DIV_CLASS(cls) TAG_CLASS(TDiv, cls) #define DIV_CLASS_ID(cls, id) TAG_CLASS_ID(TDiv, cls, id) #define PRE() TAG(TPre) #define TABLE() TAG(TTable) #define TABLE_CLASS(cls) TAG_CLASS(TTable, cls) #define TABLE_SORTABLE() TABLE_CLASS("table-sortable") #define TABLE_SORTABLE_CLASS(cls) TABLE_CLASS(cls " table-sortable") #define TABLEHEAD() TAG(TTableHead) #define TABLEHEAD_CLASS(cls) TAG_CLASS(TTableHead, cls) #define TABLEBODY() TAG(TTableBody) #define TABLEBODY_CLASS(cls) TAG_CLASS(TTableBody, cls) #define TABLER() TAG(TTableR) #define TABLER_CLASS(cls) TAG_CLASS(TTableR, cls) #define TABLED() TAG(TTableD) #define TABLED_CLASS(cls) TAG_CLASS(TTableD, cls) #define TABLED_ATTRS(...) TAG_ATTRS(TTableD, ##__VA_ARGS__) #define TABLEH() TAG(TTableH) #define TABLEH_CLASS(cls) TAG_CLASS(TTableH, cls) #define FORM() TAG(TFormC) #define FORM_CLASS(cls) TAG_CLASS(TFormC, cls) #define LABEL() TAG(TLabelC) #define LABEL_CLASS(cls) TAG_CLASS(TLabelC, cls) #define LABEL_CLASS_FOR(cls, for0) TAG_CLASS_FOR(TLabelC, cls, for0) #define SPAN_CLASS(cls) TAG_CLASS(TSpanC, cls) #define SPAN_CLASS_STYLE(cls, style) TAG_CLASS_STYLE(TSpanC, cls, style) #define PARA() TAG(TPara) #define PARA_CLASS(cls) TAG_CLASS(TPara, cls) #define H1_CLASS(cls) TAG_CLASS(TH1, cls) #define H2_CLASS(cls) TAG_CLASS(TH2, cls) #define H3_CLASS(cls) TAG_CLASS(TH3, cls) #define H4_CLASS(cls) TAG_CLASS(TH4, cls) #define H5_CLASS(cls) TAG_CLASS(TH5, cls) #define H6_CLASS(cls) TAG_CLASS(TH6, cls) #define SMALL() TAG(TSMALL) #define STRONG() TAG(TSTRONG) #define LI() TAG(TLIST) #define LI_CLASS(cls) TAG_CLASS(TLIST, cls) #define UL() TAG(TULIST) #define UL_CLASS(cls) TAG_CLASS(TULIST, cls) #define OL() TAG(TOLIST) #define OL_CLASS(cls) TAG_CLASS(TOLIST, cls) #define DL() TAG(DLIST) #define DL_CLASS(cls) TAG_CLASS(DLIST, cls) #define DT() TAG(DTERM) #define DT_CLASS(cls) TAG_CLASS(DTERM, cls) #define DD() TAG(DDESC) #define DD_CLASS(cls) TAG_CLASS(DDESC, cls) #define CAPTION() TAG(TCaption) #define CAPTION_CLASS(cls) CAPTION_CLASS(TCaption, cls) #define HTML_OUTPUT_PARAM(str, param) str << #param << ": " << param << "<br/>" #define HTML_OUTPUT_TIME_PARAM(str, param) str << #param << ": " << ToStringLocalTimeUpToSeconds(param) << "<br/>" #define COLLAPSED_BUTTON_CONTENT(targetId, buttonText) \ WITH_SCOPED(tmp, ::NMonitoring::TCollapsedButton(__stream, targetId, buttonText)) #define HREF(path) \ WITH_SCOPED(tmp, ::NMonitoring::THref(__stream, path)) namespace NMonitoring { struct THref { THref(IOutputStream& str, TStringBuf path) : Str(str) { Str << "<a href="<< path << '>'; } ~THref() { Str << "</a>"; } explicit inline operator bool() const noexcept { return true; // just to work with WITH_SCOPED } IOutputStream& Str; }; template <const char* tag> struct TTag { TTag(IOutputStream& str, TStringBuf cls = "", TStringBuf for0 = "", TStringBuf id = "") : Str(str) { Str << "<" << tag; if (!cls.empty()) { Str << " class=\"" << cls << "\""; } if (!for0.empty()) { Str << " for=\"" << for0 << "\""; } if (!id.empty()) { Str << "id=\"" << id << "\""; } Str << ">"; } TTag(IOutputStream& str, std::initializer_list<std::pair<TStringBuf, TStringBuf>> attributes) : Str(str) { Str << "<" << tag; for (const std::pair<TStringBuf, TStringBuf>& attr : attributes) { if (!attr.second.empty()) { Str << ' ' << attr.first << "=\"" << attr.second << "\""; } } Str << ">"; } ~TTag() { try { Str << "</" << tag << ">"; } catch (...) { } } explicit inline operator bool() const noexcept { return true; // just to work with WITH_SCOPED } IOutputStream& Str; }; // a nice class for creating collapsable regions of html output struct TCollapsedButton { TCollapsedButton(IOutputStream& str, const TString& targetId, const TString& buttonText) : Str(str) { Str << "<button type='button' class='btn' data-toggle='collapse' data-target='#" << targetId << "'>" << buttonText << "</button>"; Str << "<div id='" << targetId << "' class='collapse'>"; } ~TCollapsedButton() { try { Str << "</div>"; } catch (...) { } } explicit inline operator bool() const noexcept { return true; // just to work with WITH_SCOPED } IOutputStream& Str; }; struct TOutputStreamRef { TOutputStreamRef(IOutputStream& str) : Str(str) { } inline operator IOutputStream&() noexcept { return Str; } explicit inline operator bool() const noexcept { return true; // just to work with WITH_SCOPED } IOutputStream& Str; }; extern const char HtmlTag[5]; extern const char HeadTag[5]; extern const char BodyTag[5]; extern const char DivTag[4]; extern const char TableTag[6]; extern const char TableHeadTag[6]; extern const char TableBodyTag[6]; extern const char TableRTag[3]; extern const char TableDTag[3]; extern const char TableHTag[3]; extern const char FormTag[5]; extern const char LabelTag[6]; extern const char SpanTag[5]; extern const char CaptionTag[8]; extern const char PreTag[4]; extern const char ParaTag[2]; extern const char H1Tag[3]; extern const char H2Tag[3]; extern const char H3Tag[3]; extern const char H4Tag[3]; extern const char H5Tag[3]; extern const char H6Tag[3]; extern const char SmallTag[6]; extern const char StrongTag[7]; extern const char ListTag[3]; extern const char UListTag[3]; extern const char OListTag[3]; extern const char DListTag[3]; extern const char DTermTag[3]; extern const char DDescTag[3]; typedef TTag<HtmlTag> THtml; typedef TTag<HeadTag> THead; typedef TTag<BodyTag> TBody; typedef TTag<DivTag> TDiv; typedef TTag<TableTag> TTable; typedef TTag<TableHeadTag> TTableHead; typedef TTag<TableBodyTag> TTableBody; typedef TTag<TableRTag> TTableR; typedef TTag<TableDTag> TTableD; typedef TTag<TableHTag> TTableH; typedef TTag<FormTag> TFormC; typedef TTag<LabelTag> TLabelC; typedef TTag<SpanTag> TSpanC; typedef TTag<CaptionTag> TCaption; typedef TTag<PreTag> TPre; typedef TTag<ParaTag> TPara; typedef TTag<H1Tag> TH1; typedef TTag<H2Tag> TH2; typedef TTag<H3Tag> TH3; typedef TTag<H4Tag> TH4; typedef TTag<H5Tag> TH5; typedef TTag<H6Tag> TH6; typedef TTag<SmallTag> TSMALL; typedef TTag<StrongTag> TSTRONG; typedef TTag<ListTag> TLIST; typedef TTag<UListTag> TULIST; typedef TTag<OListTag> TOLIST; typedef TTag<DListTag> DLIST; typedef TTag<DTermTag> DTERM; typedef TTag<DDescTag> DDESC; }