i)?-1:1})):e}),[h,t,s,u,o]),v=(0,r.useMemo)((()=>f.some((e=>e.copyValue))),[f]),g=e=>()=>{(e=>{d((t=>"asc"===t&&s===e?"desc":"asc")),c(e)})(e)};return f.length?Ct("div",{className:xr()({"vm-table-view":!0,"vm-table-view_mobile":i}),children:Ct("table",{className:"vm-table",ref:l,children:[Ct("thead",{className:"vm-table-header",children:Ct("tr",{className:"vm-table__row vm-table__row_header",children:[h.map(((e,t)=>Ct("td",{className:"vm-table-cell vm-table-cell_header vm-table-cell_sort",onClick:g(e.key),children:Ct("div",{className:"vm-table-cell__content",children:[e.key,Ct("div",{className:xr()({"vm-table__sort-icon":!0,"vm-table__sort-icon_active":s===e.key,"vm-table__sort-icon_desc":"desc"===u&&s===e.key}),children:Ct(Vn,{})})]})},t))),Ct("td",{className:"vm-table-cell vm-table-cell_header vm-table-cell_right vm-table-cell_sort",onClick:g("Value"),children:Ct("div",{className:"vm-table-cell__content",children:[Ct("div",{className:xr()({"vm-table__sort-icon":!0,"vm-table__sort-icon_active":"Value"===s,"vm-table__sort-icon_desc":"desc"===u}),children:Ct(Vn,{})}),"Value"]})}),v&&Ct("td",{className:"vm-table-cell vm-table-cell_header"})]})}),Ct("tbody",{className:"vm-table-body",children:f.map(((e,t)=>{return Ct("tr",{className:"vm-table__row",children:[e.metadata.map(((e,n)=>Ct("td",{className:xr()({"vm-table-cell vm-table-cell_no-wrap":!0,"vm-table-cell_gray":f[t-1]&&f[t-1].metadata[n]===e}),children:e},n))),Ct("td",{className:"vm-table-cell vm-table-cell_right vm-table-cell_no-wrap",children:e.values.length?e.values.map((e=>Ct("p",{children:e},e))):e.value}),v&&Ct("td",{className:"vm-table-cell vm-table-cell_right",children:e.copyValue&&Ct("div",{className:"vm-table-cell__content",children:Ct(fa,{title:"Copy row",children:Ct(aa,{variant:"text",color:"gray",size:"small",startIcon:Ct(ar,{}),onClick:(n=e.copyValue,async()=>{await a(n,"Row has been copied")}),ariaLabel:"copy row"})})})})]},t);var n}))})]})}):Ct(Qr,{variant:"warning",children:"No data to show"})},kh=e=>{let{checked:t=!1,disabled:n=!1,label:r,color:a="secondary",onChange:i}=e;return Ct("div",{className:xr()({"vm-checkbox":!0,"vm-checkbox_disabled":n,"vm-checkbox_active":t,["vm-checkbox_".concat(a,"_active")]:t,["vm-checkbox_".concat(a)]:a}),onClick:()=>{n||i(!t)},children:[Ct("div",{className:"vm-checkbox-track",children:Ct("div",{className:"vm-checkbox-track__thumb",children:Ct(er,{})})}),r&&Ct("span",{className:"vm-checkbox__label",children:r})]})},xh="Table settings",Sh=e=>{let{columns:t,defaultColumns:n=[],tableCompact:a,onChangeColumns:i,toggleTableCompact:o}=e;const{isMobile:l}=Wr(),s=(0,r.useRef)(null),{value:c,toggle:u,setFalse:d}=oa(!1),h=(0,r.useMemo)((()=>!t.length),[t]),m=e=>()=>{(e=>{i(n.includes(e)?n.filter((t=>t!==e)):[...n,e])})(e)};return(0,r.useEffect)((()=>{$o(t,n)||i(t)}),[t]),Ct("div",{className:"vm-table-settings",children:[Ct(fa,{title:xh,children:Ct("div",{ref:s,children:Ct(aa,{variant:"text",startIcon:Ct(Pn,{}),onClick:u,disabled:h,ariaLabel:"table settings"})})}),Ct(ia,{open:c,onClose:d,placement:"bottom-right",buttonRef:s,title:xh,children:Ct("div",{className:xr()({"vm-table-settings-popper":!0,"vm-table-settings-popper_mobile":l}),children:[Ct("div",{className:"vm-table-settings-popper-list vm-table-settings-popper-list_first",children:Ct(jo,{label:"Compact view",value:a,onChange:o})}),Ct("div",{className:"vm-table-settings-popper-list",children:[Ct("div",{className:"vm-table-settings-popper-list-header",children:[Ct("h3",{className:"vm-table-settings-popper-list-header__title",children:"Display columns"}),Ct(fa,{title:"Reset to default",children:Ct(aa,{color:"primary",variant:"text",size:"small",onClick:()=>{d(),i(t)},startIcon:Ct(In,{}),ariaLabel:"reset columns"})})]}),t.map((e=>Ct("div",{className:"vm-table-settings-popper-list__item",children:Ct(kh,{checked:n.includes(e),onChange:m(e),label:e,disabled:a})},e)))]})]})})]})},Ch=e=>{let{liveData:t,controlsRef:n}=e;const{tableCompact:a}=Fr(),i=jr(),[o,l]=(0,r.useState)(),s=(0,r.useMemo)((()=>_h(t||[]).map((e=>e.key))),[t]),c=Ct(Sh,{columns:s,defaultColumns:o,onChangeColumns:l,tableCompact:a,toggleTableCompact:()=>{i({type:"TOGGLE_TABLE_COMPACT"})}});return Ct(xt.FK,{children:[n.current&&(0,r.createPortal)(c,n.current),Ct(wh,{data:t,displayColumns:o})]})},Eh=e=>{let{graphData:t,liveData:n,isHistogram:r,displayType:a,controlsRef:i}=e;return a===dt.code&&n?Ct(yh,{data:n}):a===dt.table&&n?Ct(Ch,{liveData:n,controlsRef:i}):a===dt.chart&&t?Ct(gh,{graphData:t,isHistogram:r,controlsRef:i}):null},Nh=[Ct(xt.FK,{children:[Ct("p",{children:"Filename - specify the name for your report file."}),Ct("p",{children:["Default format: ",Ct("code",{children:["vmui_report_$",It,".json"]}),"."]}),Ct("p",{children:"This name will be used when saving your report on your device."})]}),Ct(xt.FK,{children:[Ct("p",{children:"Comment (optional) - add a comment to your report."}),Ct("p",{children:"This can be any additional information that will be useful when reviewing the report later."})]}),Ct(xt.FK,{children:[Ct("p",{children:"Query trace - enable this option to include a query trace in your report."}),Ct("p",{children:"This will assist in analyzing and diagnosing the query processing."})]}),Ct(xt.FK,{children:[Ct("p",{children:"Generate Report - click this button to generate and save your report. "}),Ct("p",{children:["After creation, the report can be downloaded and examined on the ",Ct(Ie,{to:Ye.queryAnalyzer,target:"_blank",rel:"noreferrer",className:"vm-link vm-link_underlined",children:qe[Ye.queryAnalyzer].title})," page."]})]})],Ah=()=>"vmui_report_".concat(i()().utc().format(It)),Mh=e=>{let{fetchUrl:t}=e;const{query:n}=En(),[a,i]=(0,r.useState)(Ah()),[o,l]=(0,r.useState)(""),[s,c]=(0,r.useState)(!0),[u,d]=(0,r.useState)(),[h,m]=(0,r.useState)(!1),p=(0,r.useRef)(null),f=(0,r.useRef)(null),v=(0,r.useRef)(null),g=(0,r.useRef)(null),y=[p,f,v,g],[_,b]=(0,r.useState)(0),{value:w,toggle:k,setFalse:x}=oa(!1),{value:S,toggle:C,setFalse:E}=oa(!1),N=(0,r.useMemo)((()=>{if(t)return t.map(((e,t)=>{const n=new URL(e);return s?n.searchParams.set("trace","1"):n.searchParams.delete("trace"),{id:t,url:n}}))}),[t,s]),A=(0,r.useCallback)((e=>{const t=JSON.stringify(e,null,2),n=new Blob([t],{type:"application/json"}),r=URL.createObjectURL(n),i=document.createElement("a");i.href=r,i.download="".concat(a||Ah(),".json"),document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r),x()}),[a]),M=(0,r.useCallback)((async()=>{if(N){d(""),m(!0);try{const e=[];for await(const{url:t,id:n}of N){const r=await fetch(t),a=await r.json();if(r.ok)a.vmui={id:n,comment:o,params:rt().parse(new URL(t).search.replace(/^\?/,""))},e.push(a);else{const e=a.errorType?"".concat(a.errorType,"\r\n"):"";d("".concat(e).concat((null===a||void 0===a?void 0:a.error)||(null===a||void 0===a?void 0:a.message)||"unknown error"))}}e.length&&A(e)}catch(rp){rp instanceof Error&&"AbortError"!==rp.name&&d("".concat(rp.name,": ").concat(rp.message))}finally{m(!1)}}else d(ht.validQuery)}),[N,o,A,n]),T=e=>()=>{b((t=>t+e))};return(0,r.useEffect)((()=>{d(""),i(Ah()),l("")}),[w]),(0,r.useEffect)((()=>{b(0)}),[S]),Ct(xt.FK,{children:[Ct(fa,{title:"Export query",children:Ct(aa,{variant:"text",startIcon:Ct(wr,{}),onClick:k,ariaLabel:"export query"})}),w&&Ct(pa,{title:"Export query",onClose:x,isOpen:w,children:Ct("div",{className:"vm-download-report",children:[Ct("div",{className:"vm-download-report-settings",children:[Ct("div",{ref:p,children:Ct(Ha,{label:"Filename",value:a,onChange:i})}),Ct("div",{ref:f,children:Ct(Ha,{type:"textarea",label:"Comment",value:o,onChange:l})}),Ct("div",{ref:v,children:Ct(kh,{checked:s,onChange:c,label:"Include query trace"})})]}),u&&Ct(Qr,{variant:"error",children:u}),Ct("div",{className:"vm-download-report__buttons",children:[Ct(aa,{variant:"text",onClick:C,children:"Help"}),Ct("div",{ref:g,children:Ct(aa,{onClick:M,disabled:h,children:h?"Loading data...":"Generate Report"})})]}),Ct(ia,{open:S,buttonRef:y[_],placement:"top-left",variant:"dark",onClose:E,children:Ct("div",{className:"vm-download-report-helper",children:[Ct("div",{className:"vm-download-report-helper__description",children:Nh[_]}),Ct("div",{className:"vm-download-report-helper__buttons",children:[0!==_&&Ct(aa,{onClick:T(-1),size:"small",color:"white",children:"Prev"}),Ct(aa,{onClick:_===y.length-1?E:T(1),size:"small",color:"white",variant:"text",children:_===y.length-1?"Close":"Next"})]})]})})]})})]})},Th=()=>{(()=>{const{tenantId:e}=Nt(),{displayType:t}=Fr(),{query:n}=En(),{duration:a,relativeTime:i,period:{date:o,step:l}}=vn(),{customStep:s}=Ur(),[,c]=je(),u=()=>{const r={};n.forEach(((n,c)=>{var u;const d="g".concat(c);r["".concat(d,".expr")]=n,r["".concat(d,".range_input")]=a,r["".concat(d,".end_input")]=o,r["".concat(d,".tab")]=(null===(u=Tr.find((e=>e.value===t)))||void 0===u?void 0:u.prometheusCode)||0,r["".concat(d,".relative_time")]=i,r["".concat(d,".tenantID")]=e,l!==s&&s&&(r["".concat(d,".step_input")]=s)})),c(al(r))};(0,r.useEffect)(u,[e,t,n,a,i,o,l,s]),(0,r.useEffect)(u,[])})();const{isMobile:e}=Wr(),{displayType:t}=Fr(),{query:n}=En(),{customStep:a}=Ur(),i=Br(),[o,l]=(0,r.useState)([]),[s,c]=(0,r.useState)(!n[0]),[u,d]=(0,r.useState)(!1),h=(0,r.useRef)(null),{fetchUrl:m,isLoading:p,liveData:f,graphData:v,error:g,queryErrors:y,setQueryErrors:_,queryStats:b,warning:w,traces:k,isHistogram:x}=nl({visible:!0,customStep:a,hideQuery:o,showAllSeries:u}),S=!(null!==f&&void 0!==f&&f.length)&&t!==dt.chart,C=!s&&g;return Nr("popstate",(()=>window.location.reload())),(0,r.useEffect)((()=>{i({type:"SET_IS_HISTOGRAM",payload:x})}),[v]),Ct("div",{className:xr()({"vm-custom-panel":!0,"vm-custom-panel_mobile":e}),children:[Ct(Qo,{queryErrors:s?[]:y,setQueryErrors:_,setHideError:c,stats:b,onHideQuery:e=>{l(e)},onRunQuery:()=>{c(!1)}}),Ct(pl,{traces:k,displayType:t}),p&&Ct(rl,{}),C&&Ct(Qr,{variant:"error",children:g}),S&&Ct(Qr,{variant:"info",children:Ct(sl,{})}),w&&Ct(fl,{warning:w,query:n,onChange:d}),Ct("div",{className:xr()({"vm-custom-panel-body":!0,"vm-custom-panel-body_mobile":e,"vm-block":!0,"vm-block_mobile":e}),children:[Ct("div",{className:"vm-custom-panel-body-header",ref:h,children:[Ct("div",{className:"vm-custom-panel-body-header__tabs",children:Ct(Lr,{})}),(v||f)&&Ct(Mh,{fetchUrl:m})]}),Ct(Eh,{graphData:v,liveData:f,isHistogram:x,displayType:t,controlsRef:h})]})]})},Lh=e=>{let{title:t,description:n,unit:a,expr:i,showLegend:o,filename:l,alias:s}=e;const{isMobile:c}=Wr(),{period:u}=vn(),{customStep:d}=Ur(),h=gn(),m=(0,r.useRef)(null),[p,f]=(0,r.useState)(!1),[v,g]=(0,r.useState)(!1),[y,_]=(0,r.useState)({limits:{enable:!1,range:{1:[0,0]}}}),b=(0,r.useMemo)((()=>Array.isArray(i)&&i.every((e=>e))),[i]),{isLoading:w,graphData:k,error:x,warning:S}=nl({predefinedQuery:b?i:[],display:dt.chart,visible:p,customStep:d}),C=e=>{const t={...y};t.limits.range=e,_(t)};if((0,r.useEffect)((()=>{const e=new IntersectionObserver((e=>{e.forEach((e=>f(e.isIntersecting)))}),{threshold:.1});return m.current&&e.observe(m.current),()=>{m.current&&e.unobserve(m.current)}}),[m]),!b)return Ct(Qr,{variant:"error",children:[Ct("code",{children:'"expr"'})," not found. Check the configuration file ",Ct("b",{children:l}),"."]});const E=()=>Ct("div",{className:"vm-predefined-panel-header__description vm-default-styles",children:[n&&Ct(xt.FK,{children:[Ct("div",{children:[Ct("span",{children:"Description:"}),Ct("div",{dangerouslySetInnerHTML:{__html:To.parse(n)}})]}),Ct("hr",{})]}),Ct("div",{children:[Ct("span",{children:"Queries:"}),Ct("div",{children:i.map(((e,t)=>Ct("div",{children:e},"".concat(t,"_").concat(e))))})]})]});return Ct("div",{className:"vm-predefined-panel",ref:m,children:[Ct("div",{className:"vm-predefined-panel-header",children:[Ct(fa,{title:Ct(E,{}),children:Ct("div",{className:"vm-predefined-panel-header__info",children:Ct(Rn,{})})}),Ct("h3",{className:"vm-predefined-panel-header__title",children:t||""}),Ct(vh,{yaxis:y,setYaxisLimits:C,toggleEnableLimits:()=>{const e={...y};e.limits.enable=!e.limits.enable,_(e)},spanGaps:{value:v,onChange:g}})]}),Ct("div",{className:"vm-predefined-panel-body",children:[w&&Ct(rl,{}),x&&Ct(Qr,{variant:"error",children:x}),S&&Ct(Qr,{variant:"warning",children:S}),k&&Ct(hh,{data:k,period:u,customStep:d,query:i,yaxis:y,unit:a,alias:s,showLegend:o,setYaxisLimits:C,setPeriod:e=>{let{from:t,to:n}=e;h({type:"SET_PERIOD",payload:{from:t,to:n}})},fullWidth:!1,height:c?.5*window.innerHeight:500,spanGaps:v})]})]})},Ph=e=>{let{index:t,title:n,panels:a,filename:i}=e;const o=Ar(),l=(0,r.useMemo)((()=>o.width/12),[o]),[s,c]=(0,r.useState)(!t),[u,d]=(0,r.useState)([]);(0,r.useEffect)((()=>{d(a&&a.map((e=>e.width||12)))}),[a]);const[h,m]=(0,r.useState)({start:0,target:0,enable:!1}),p=(0,r.useCallback)((e=>{if(!h.enable)return;const{start:t}=h,n=Math.ceil((t-e.clientX)/l);if(Math.abs(n)>=12)return;const r=u.map(((e,t)=>e-(t===h.target?n:0)));d(r)}),[h,l]),f=(0,r.useCallback)((()=>{m({...h,enable:!1})}),[h]),v=e=>t=>{((e,t)=>{m({start:e.clientX,target:t,enable:!0})})(t,e)};Nr("mousemove",p),Nr("mouseup",f);return Ct("div",{className:"vm-predefined-dashboard",children:Ct(pi,{defaultExpanded:s,onChange:e=>c(e),title:Ct((()=>Ct("div",{className:xr()({"vm-predefined-dashboard-header":!0,"vm-predefined-dashboard-header_open":s}),children:[(n||i)&&Ct("span",{className:"vm-predefined-dashboard-header__title",children:n||"".concat(t+1,". ").concat(i)}),a&&Ct("span",{className:"vm-predefined-dashboard-header__count",children:["(",a.length," panels)"]})]})),{}),children:Ct("div",{className:"vm-predefined-dashboard-panels",children:Array.isArray(a)&&a.length?a.map(((e,t)=>Ct("div",{className:"vm-predefined-dashboard-panels-panel vm-block vm-block_empty-padding",style:{gridColumn:"span ".concat(u[t])},children:[Ct(Lh,{title:e.title,description:e.description,unit:e.unit,expr:e.expr,alias:e.alias,filename:i,showLegend:e.showLegend}),Ct("button",{className:"vm-predefined-dashboard-panels-panel__resizer",onMouseDown:v(t),"aria-label":"resize the panel"})]},t))):Ct("div",{className:"vm-predefined-dashboard-panels-panel__alert",children:Ct(Qr,{variant:"error",children:[Ct("code",{children:'"panels"'})," not found. Check the configuration file ",Ct("b",{children:i}),"."]})})})})})},Oh=()=>{(()=>{const{duration:e,relativeTime:t,period:{date:n}}=vn(),{customStep:a}=Ur(),{setSearchParamsFromKeys:i}=ii(),o=()=>{const r=al({"g0.range_input":e,"g0.end_input":n,"g0.step_input":a,"g0.relative_time":t});i(r)};(0,r.useEffect)(o,[e,t,n,a]),(0,r.useEffect)(o,[])})();const{isMobile:e}=Wr(),{dashboardsSettings:t,dashboardsLoading:n,dashboardsError:a}=ea(),[i,o]=(0,r.useState)(0),l=(0,r.useMemo)((()=>t.map(((e,t)=>({label:e.title||"",value:t})))),[t]),s=(0,r.useMemo)((()=>t[i]||{}),[t,i]),c=(0,r.useMemo)((()=>null===s||void 0===s?void 0:s.rows),[s]),u=(0,r.useMemo)((()=>s.title||s.filename||""),[s]),d=(0,r.useMemo)((()=>Array.isArray(c)&&!!c.length),[c]),h=e=>()=>{(e=>{o(e)})(e)};return Ct("div",{className:"vm-predefined-panels",children:[n&&Ct(rl,{}),!t.length&&a&&Ct(Qr,{variant:"error",children:a}),!t.length&&Ct(Qr,{variant:"info",children:"Dashboards not found"}),l.length>1&&Ct("div",{className:xr()({"vm-predefined-panels-tabs":!0,"vm-predefined-panels-tabs_mobile":e}),children:l.map((e=>Ct("div",{className:xr()({"vm-predefined-panels-tabs__tab":!0,"vm-predefined-panels-tabs__tab_active":e.value==i}),onClick:h(e.value),children:e.label},e.value)))}),Ct("div",{className:"vm-predefined-panels__dashboards",children:[d&&c.map(((e,t)=>Ct(Ph,{index:t,filename:u,title:e.title,panels:e.panels},"".concat(i,"_").concat(t)))),!!t.length&&!d&&Ct(Qr,{variant:"error",children:[Ct("code",{children:'"rows"'})," not found. Check the configuration file ",Ct("b",{children:u}),"."]})]})]})},Ih=(e,t)=>{const n=t.match?"&match[]="+encodeURIComponent(t.match):"",r=t.focusLabel?"&focusLabel="+encodeURIComponent(t.focusLabel):"";return"".concat(e,"/api/v1/status/tsdb?topN=").concat(t.topN,"&date=").concat(t.date).concat(n).concat(r)};class Rh{constructor(){this.tsdbStatus=void 0,this.tabsNames=void 0,this.isPrometheus=void 0,this.tsdbStatus=this.defaultTSDBStatus,this.tabsNames=["table","graph"],this.isPrometheus=!1,this.getDefaultState=this.getDefaultState.bind(this)}set tsdbStatusData(e){this.isPrometheus=!(null===e||void 0===e||!e.headStats),this.tsdbStatus=e}get tsdbStatusData(){return this.tsdbStatus}get defaultTSDBStatus(){return{totalSeries:0,totalSeriesPrev:0,totalSeriesByAll:0,totalLabelValuePairs:0,seriesCountByMetricName:[],seriesCountByLabelName:[],seriesCountByFocusLabelValue:[],seriesCountByLabelValuePair:[],labelValueCountByLabelName:[]}}get isPrometheusData(){return this.isPrometheus}keys(e,t){const n=e&&/__name__=".+"/.test(e),r=e&&/{.+=".+"}/g.test(e),a=e&&/__name__=".+", .+!=""/g.test(e);let i=[];return i=t||a?i.concat("seriesCountByFocusLabelValue"):n?i.concat("labelValueCountByLabelName"):r?i.concat("seriesCountByMetricName","seriesCountByLabelName"):i.concat("seriesCountByMetricName","seriesCountByLabelName","seriesCountByLabelValuePair","labelValueCountByLabelName"),i}getDefaultState(e,t){return this.keys(e,t).reduce(((e,t)=>({...e,tabs:{...e.tabs,[t]:this.tabsNames},containerRefs:{...e.containerRefs,[t]:(0,r.useRef)(null)}})),{tabs:{},containerRefs:{}})}sectionsTitles(e){return{seriesCountByMetricName:"Metric names with the highest number of series",seriesCountByLabelName:"Labels with the highest number of series",seriesCountByFocusLabelValue:'Values for "'.concat(e,'" label with the highest number of series'),seriesCountByLabelValuePair:"Label=value pairs with the highest number of series",labelValueCountByLabelName:"Labels with the highest number of unique values"}}get sectionsTips(){return{seriesCountByMetricName:"\n \n This table returns a list of metrics with the highest cardinality.\n The cardinality of a metric is the number of time series associated with that metric,\n where each time series is defined as a unique combination of key-value label pairs.\n
\n \n When looking to reduce the number of active series in your data source,\n you can start by inspecting individual metrics with high cardinality\n (i.e. that have lots of active time series associated with them),\n since that single metric contributes a large fraction of the series that make up your total series count.\n
",seriesCountByLabelName:"\n \n This table returns a list of the labels with the highest number of series.\n
\n \n Use this table to identify labels that are storing dimensions with high cardinality\n (many different label values).\n
\n \n It is recommended to choose labels such that they have a finite set of values,\n since every unique combination of key-value label pairs creates a new time series\n and therefore can dramatically increase the number of time series in your system.\n
",seriesCountByFocusLabelValue:"\n \n This table returns a list of unique label values per selected label.\n
\n \n Use this table to identify label values that are storing per each selected series.\n
",labelValueCountByLabelName:"\n \n This table returns a list of labels with the highest number of the unique values.\n
\n ",seriesCountByLabelValuePair:"\n \n This table returns a list of the label values pairs with the highest number of series.\n
\n \n Use this table to identify unique label values pairs. This helps to identify same labels \n is applied to count timeseries in your system, since every unique combination of key-value label pairs \n creates a new time series and therefore can dramatically increase the number of time series in your system\n
"}}get tablesHeaders(){return{seriesCountByMetricName:Dh,seriesCountByLabelName:zh,seriesCountByFocusLabelValue:Fh,seriesCountByLabelValuePair:jh,labelValueCountByLabelName:Hh}}totalSeries(e){return"labelValueCountByLabelName"===e?-1:arguments.length>1&&void 0!==arguments[1]&&arguments[1]?this.tsdbStatus.totalSeriesPrev:this.tsdbStatus.totalSeries}}const Dh=[{id:"name",label:"Metric name"},{id:"value",label:"Number of series"},{id:"percentage",label:"Share in total",info:"Shows the share of a metric to the total number of series"},{id:"action",label:""}],zh=[{id:"name",label:"Label name"},{id:"value",label:"Number of series"},{id:"percentage",label:"Share in total",info:"Shows the share of the label to the total number of series"},{id:"action",label:""}],Fh=[{id:"name",label:"Label value"},{id:"value",label:"Number of series"},{id:"percentage",label:"Share in total"},{disablePadding:!1,id:"action",label:"",numeric:!1}],jh=[{id:"name",label:"Label=value pair"},{id:"value",label:"Number of series"},{id:"percentage",label:"Share in total",info:"Shows the share of the label value pair to the total number of series"},{id:"action",label:""}],Hh=[{id:"name",label:"Label name"},{id:"value",label:"Number of unique values"},{id:"action",label:""}],Vh=()=>{const e=new Rh,[t]=je(),n=t.get("match"),a=t.get("focusLabel"),o=+(t.get("topN")||10),l=t.get("date")||i()().tz().format(Tt),s=$a(l),{serverUrl:c}=Nt(),[u,d]=(0,r.useState)(!1),[h,m]=(0,r.useState)(),[p,f]=(0,r.useState)(e.defaultTSDBStatus),[v,g]=(0,r.useState)(!1),y=async e=>{const t=await fetch(e);if(t.ok)return await t.json();throw new Error("Request failed with status ".concat(t.status))},_=async t=>{if(!c)return;m(""),d(!0),f(e.defaultTSDBStatus);const r={...t,date:t.date,topN:0,match:"",focusLabel:""},a={...t,date:i()(t.date).subtract(1,"day").tz().format(Tt)},o=[Ih(c,t),Ih(c,a)];s!==l&&o.push(Ih(c,r));try{var u,h,v,g,_,b,w,k,x,S;const[e,t,r={}]=await Promise.all(o.map(y)),a={...t.data},{data:i}=r,l={...e.data,totalSeries:(null===(u=e.data)||void 0===u?void 0:u.totalSeries)||(null===(h=e.data)||void 0===h||null===(v=h.headStats)||void 0===v?void 0:v.numSeries)||0,totalLabelValuePairs:(null===(g=e.data)||void 0===g?void 0:g.totalLabelValuePairs)||(null===(_=e.data)||void 0===_||null===(b=_.headStats)||void 0===b?void 0:b.numLabelValuePairs)||0,seriesCountByLabelName:(null===(w=e.data)||void 0===w?void 0:w.seriesCountByLabelName)||[],seriesCountByFocusLabelValue:(null===(k=e.data)||void 0===k?void 0:k.seriesCountByFocusLabelValue)||[],totalSeriesByAll:(null===i||void 0===i?void 0:i.totalSeries)||(null===i||void 0===i||null===(x=i.headStats)||void 0===x?void 0:x.numSeries)||p.totalSeriesByAll||0,totalSeriesPrev:(null===a||void 0===a?void 0:a.totalSeries)||(null===a||void 0===a||null===(S=a.headStats)||void 0===S?void 0:S.numSeries)||0},s=null===n||void 0===n?void 0:n.replace(/[{}"]/g,"");l.seriesCountByLabelValuePair=l.seriesCountByLabelValuePair.filter((e=>e.name!==s)),((e,t)=>{Object.keys(e).forEach((n=>{const r=n,a=e[r],i=t[r];Array.isArray(a)&&Array.isArray(i)&&a.forEach((e=>{var t;const n=null===(t=i.find((t=>t.name===e.name)))||void 0===t?void 0:t.value;e.diff=n?e.value-n:0,e.valuePrev=n||0}))}))})(l,a),f(l),d(!1)}catch(rp){d(!1),rp instanceof Error&&m("".concat(rp.name,": ").concat(rp.message))}};return(0,r.useEffect)((()=>{_({topN:o,match:n,date:l,focusLabel:a})}),[c,n,a,o,l]),(0,r.useEffect)((()=>{h&&(f(e.defaultTSDBStatus),d(!1))}),[h]),(0,r.useEffect)((()=>{const e=Ge(c);g(!!e)}),[c]),e.tsdbStatusData=p,{isLoading:u,appConfigurator:e,error:h,isCluster:v}},$h={seriesCountByMetricName:e=>{let{query:t}=e;return Uh("__name__",t)},seriesCountByLabelName:e=>{let{query:t}=e;return"{".concat(t,'!=""}')},seriesCountByFocusLabelValue:e=>{let{query:t,focusLabel:n}=e;return Uh(n,t)},seriesCountByLabelValuePair:e=>{let{query:t}=e;const n=t.split("="),r=n[0],a=n.slice(1).join("=");return Uh(r,a)},labelValueCountByLabelName:e=>{let{query:t,match:n}=e;return""===n?"{".concat(t,'!=""}'):"".concat(n.replace("}",""),", ").concat(t,'!=""}')}},Uh=(e,t)=>e?"{"+e+"="+JSON.stringify(t)+"}":"",Bh=e=>{var t;let{totalSeries:n=0,totalSeriesPrev:r=0,totalSeriesAll:a=0,seriesCountByMetricName:i=[],isPrometheus:o}=e;const{isMobile:l}=Wr(),[s]=je(),c=s.get("match"),u=s.get("focusLabel"),d=/__name__/.test(c||""),h=(null===(t=i[0])||void 0===t?void 0:t.value)/a*100,m=n-r,p=Math.abs(m)/r*100,f=[{title:"Total series",value:n.toLocaleString("en-US"),dynamic:n&&r&&!o?"".concat(p.toFixed(2),"%"):"",display:!u,info:'The total number of active time series. \n A time series is uniquely identified by its name plus a set of its labels. \n For example, temperature{city="NY",country="US"} and temperature{city="SF",country="US"} \n are two distinct series, since they differ by the city label.'},{title:"Percentage from total",value:isNaN(h)?"-":"".concat(h.toFixed(2),"%"),display:d,info:"The share of these series in the total number of time series."}].filter((e=>e.display));return f.length?Ct("div",{className:xr()({"vm-cardinality-totals":!0,"vm-cardinality-totals_mobile":l}),children:f.map((e=>{let{title:t,value:n,info:a,dynamic:i}=e;return Ct("div",{className:"vm-cardinality-totals-card",children:[Ct("h4",{className:"vm-cardinality-totals-card__title",children:[t,a&&Ct(fa,{title:Ct("p",{className:"vm-cardinality-totals-card__tooltip",children:a}),children:Ct("div",{className:"vm-cardinality-totals-card__info-icon",children:Ct(Rn,{})})})]}),Ct("span",{className:"vm-cardinality-totals-card__value",children:n}),!!i&&Ct(fa,{title:"in relation to the previous day: ".concat(r.toLocaleString("en-US")),children:Ct("span",{className:xr()({"vm-dynamic-number":!0,"vm-dynamic-number_positive vm-dynamic-number_down":m<0,"vm-dynamic-number_negative vm-dynamic-number_up":m>0}),children:i})})]},t)}))}):null},qh=(e,t)=>{const[n]=je(),a=n.get(t)?n.get(t):e,[i,o]=(0,r.useState)(a);return(0,r.useEffect)((()=>{a!==i&&o(a)}),[a]),[i,o]},Yh=e=>{let{isPrometheus:t,isCluster:n,...a}=e;const{isMobile:i}=Wr(),[o]=je(),{setSearchParamsFromKeys:l}=ii(),s=o.get("tips")||"",[c,u]=qh("","match"),[d,h]=qh("","focusLabel"),[m,p]=qh(10,"topN"),f=(0,r.useMemo)((()=>m<0?"Number must be bigger than zero":""),[m]),v=()=>{l({match:c,topN:m,focusLabel:d})};return(0,r.useEffect)((()=>{const e=o.get("match"),t=+(o.get("topN")||10),n=o.get("focusLabel");e!==c&&u(e||""),t!==m&&p(t),n!==d&&h(n||"")}),[o]),Ct("div",{className:xr()({"vm-cardinality-configurator":!0,"vm-cardinality-configurator_mobile":i,"vm-block":!0,"vm-block_mobile":i}),children:[Ct("div",{className:"vm-cardinality-configurator-controls",children:[Ct("div",{className:"vm-cardinality-configurator-controls__query",children:Ct(Ha,{label:"Time series selector",type:"string",value:c,onChange:u,onEnter:v})}),Ct("div",{className:"vm-cardinality-configurator-controls__item",children:Ct(Ha,{label:"Focus label",type:"text",value:d||"",onChange:h,onEnter:v,endIcon:Ct(fa,{title:Ct("div",{children:Ct("p",{children:"To identify values with the highest number of series for the selected label."})}),children:Ct(cr,{})})})}),Ct("div",{className:"vm-cardinality-configurator-controls__item vm-cardinality-configurator-controls__item_limit",children:Ct(Ha,{label:"Limit entries",type:"number",value:t?10:m,error:f,disabled:t,helperText:t?"not available for Prometheus":"",onChange:e=>{const t=+e;p(isNaN(t)?0:t)},onEnter:v})})]}),Ct("div",{className:"vm-cardinality-configurator-bottom",children:[Ct(Bh,{isPrometheus:t,isCluster:n,...a}),n&&Ct("div",{className:"vm-cardinality-configurator-bottom-helpful",children:Ct(il,{href:"https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#cardinality-explorer-statistic-inaccuracy",withIcon:!0,children:[Ct(lr,{}),"Statistic inaccuracy explanation"]})}),Ct("div",{className:"vm-cardinality-configurator-bottom-helpful",children:Ct(il,{href:"https://docs.victoriametrics.com/#cardinality-explorer",withIcon:!0,children:[Ct(lr,{}),"Documentation"]})}),Ct("div",{className:"vm-cardinality-configurator-bottom__execute",children:[Ct(fa,{title:s?"Hide tips":"Show tips",children:Ct(aa,{variant:"text",color:s?"warning":"gray",startIcon:Ct(mr,{}),onClick:()=>{const e=o.get("tips")||"";l({tips:e?"":"true"})},ariaLabel:"visibility tips"})}),Ct(aa,{variant:"text",startIcon:Ct(In,{}),onClick:()=>{l({match:"",focusLabel:""})},children:"Reset"}),Ct(aa,{startIcon:Ct(Yn,{}),onClick:v,children:"Execute Query"})]})]})]})};function Wh(e){const{order:t,orderBy:n,onRequestSort:r,headerCells:a}=e;return Ct("thead",{className:"vm-table-header vm-cardinality-panel-table__header",children:Ct("tr",{className:"vm-table__row vm-table__row_header",children:a.map((e=>{return Ct("th",{className:xr()({"vm-table-cell vm-table-cell_header":!0,"vm-table-cell_sort":"action"!==e.id&&"percentage"!==e.id,"vm-table-cell_right":"action"===e.id}),onClick:(a=e.id,e=>{r(e,a)}),children:Ct("div",{className:"vm-table-cell__content",children:[e.info?Ct(fa,{title:e.info,children:[Ct("div",{className:"vm-metrics-content-header__tip-icon",children:Ct(Rn,{})}),e.label]}):Ct(xt.FK,{children:e.label}),"action"!==e.id&&"percentage"!==e.id&&Ct("div",{className:xr()({"vm-table__sort-icon":!0,"vm-table__sort-icon_active":n===e.id,"vm-table__sort-icon_desc":"desc"===t&&n===e.id}),children:Ct(Vn,{})})]})},e.id);var a}))})})}const Kh=["date","timestamp","time"];function Qh(e,t,n){const r=e[n],a=t[n],o=Kh.includes("".concat(n))?i()("".concat(r)).unix():r,l=Kh.includes("".concat(n))?i()("".concat(a)).unix():a;return lo?1:0}function Zh(e,t){return"desc"===e?(e,n)=>Qh(e,n,t):(e,n)=>-Qh(e,n,t)}function Gh(e,t){const n=e.map(((e,t)=>[e,t]));return n.sort(((e,n)=>{const r=t(e[0],n[0]);return 0!==r?r:e[1]-n[1]})),n.map((e=>e[0]))}const Jh=e=>{let{rows:t,headerCells:n,defaultSortColumn:a,tableCells:i}=e;const[o,l]=(0,r.useState)("desc"),[s,c]=(0,r.useState)(a),u=Gh(t,Zh(o,s));return Ct("table",{className:"vm-table vm-cardinality-panel-table",children:[Ct(Wh,{order:o,orderBy:s,onRequestSort:(e,t)=>{l(s===t&&"asc"===o?"desc":"asc"),c(t)},rowCount:t.length,headerCells:n}),Ct("tbody",{className:"vm-table-header",children:u.map((e=>Ct("tr",{className:"vm-table__row",children:i(e)},e.name)))})]})},Xh=e=>{let{row:t,totalSeries:n,totalSeriesPrev:r,onActionClick:a}=e;const i=n>0?t.value/n*100:-1,o=r>0?t.valuePrev/r*100:-1,l=[i,o].some((e=>-1===e)),s=i-o,c=l?"":"".concat(s.toFixed(2),"%"),u=()=>{a(t.name)};return Ct(xt.FK,{children:[Ct("td",{className:"vm-table-cell",children:Ct("span",{className:"vm-link vm-link_colored",onClick:u,children:t.name})},t.name),Ct("td",{className:"vm-table-cell",children:[t.value,!!t.diff&&Ct(fa,{title:"in relation to the previous day: ".concat(t.valuePrev),children:Ct("span",{className:xr()({"vm-dynamic-number":!0,"vm-dynamic-number_positive":t.diff<0,"vm-dynamic-number_negative":t.diff>0}),children:["\xa0",t.diff>0?"+":"",t.diff]})})]},t.value),i>0&&Ct("td",{className:"vm-table-cell",children:Ct("div",{className:"vm-cardinality-panel-table__progress",children:[Ct(cl,{value:i}),c&&Ct(fa,{title:"in relation to the previous day",children:Ct("span",{className:xr()({"vm-dynamic-number":!0,"vm-dynamic-number_positive vm-dynamic-number_down":s<0,"vm-dynamic-number_negative vm-dynamic-number_up":s>0}),children:c})})]})},t.progressValue),Ct("td",{className:"vm-table-cell vm-table-cell_right",children:Ct("div",{className:"vm-table-cell__content",children:Ct(fa,{title:"Filter by ".concat(t.name),children:Ct(aa,{variant:"text",size:"small",onClick:u,children:Ct(Wn,{})})})})},"action")]})},em=e=>{let{data:t}=e;const[n,a]=(0,r.useState)([]),[i,o]=(0,r.useState)([0,0]);return(0,r.useEffect)((()=>{const e=t.sort(((e,t)=>t.value-e.value)),n=(e=>{const t=e.map((e=>e.value)),n=Math.ceil(t[0]||1),r=n/9;return new Array(11).fill(n+r).map(((e,t)=>Math.round(e-r*t)))})(e);o(n),a(e.map((e=>({...e,percentage:e.value/n[0]*100}))))}),[t]),Ct("div",{className:"vm-simple-bar-chart",children:[Ct("div",{className:"vm-simple-bar-chart-y-axis",children:i.map((e=>Ct("div",{className:"vm-simple-bar-chart-y-axis__tick",children:e},e)))}),Ct("div",{className:"vm-simple-bar-chart-data",children:n.map((e=>{let{name:t,value:n,percentage:r}=e;return Ct(fa,{title:"".concat(t,": ").concat(n),placement:"top-center",children:Ct("div",{className:"vm-simple-bar-chart-data-item",style:{maxHeight:"".concat(r||0,"%")}})},"".concat(t,"_").concat(n))}))})]})},tm=e=>{let{rows:t,tabs:n=[],chartContainer:a,totalSeries:i,totalSeriesPrev:o,onActionClick:l,sectionTitle:s,tip:c,tableHeaderCells:u,isPrometheus:d}=e;const{isMobile:h}=Wr(),[m,p]=(0,r.useState)("table"),f=d&&!t.length,v=(0,r.useMemo)((()=>n.map(((e,t)=>({value:e,label:e,icon:Ct(0===t?Qn:Kn,{})})))),[n]);return Ct("div",{className:xr()({"vm-metrics-content":!0,"vm-metrics-content_mobile":h,"vm-block":!0,"vm-block_mobile":h}),children:[Ct("div",{className:"vm-metrics-content-header vm-section-header",children:[Ct("h5",{className:xr()({"vm-metrics-content-header__title":!0,"vm-section-header__title":!0,"vm-section-header__title_mobile":h}),children:[!h&&c&&Ct(fa,{title:Ct("p",{dangerouslySetInnerHTML:{__html:c},className:"vm-metrics-content-header__tip"}),children:Ct("div",{className:"vm-metrics-content-header__tip-icon",children:Ct(Rn,{})})}),s]}),Ct("div",{className:"vm-section-header__tabs",children:Ct(Mr,{activeItem:m,items:v,onChange:p})})]}),f&&Ct("div",{className:"vm-metrics-content-prom-data",children:[Ct("div",{className:"vm-metrics-content-prom-data__icon",children:Ct(Rn,{})}),Ct("h3",{className:"vm-metrics-content-prom-data__title",children:"Prometheus Data Limitation"}),Ct("p",{className:"vm-metrics-content-prom-data__text",children:["Due to missing data from your Prometheus source, some tables may appear empty.",Ct("br",{}),"This does not indicate an issue with your system or our tool."]})]}),!f&&"table"===m&&Ct("div",{ref:a,className:xr()({"vm-metrics-content__table":!0,"vm-metrics-content__table_mobile":h}),children:Ct(Jh,{rows:t,headerCells:u,defaultSortColumn:"value",tableCells:e=>Ct(Xh,{row:e,totalSeries:i,totalSeriesPrev:o,onActionClick:l})})}),!f&&"graph"===m&&Ct("div",{className:"vm-metrics-content__chart",children:Ct(em,{data:t.map((e=>{let{name:t,value:n}=e;return{name:t,value:n}}))})})]})},nm=e=>{let{title:t,children:n}=e;return Ct("div",{className:"vm-cardinality-tip",children:[Ct("div",{className:"vm-cardinality-tip-header",children:[Ct("div",{className:"vm-cardinality-tip-header__tip-icon",children:Ct(mr,{})}),Ct("h4",{className:"vm-cardinality-tip-header__title",children:t||"Tips"})]}),Ct("p",{className:"vm-cardinality-tip__description",children:n})]})},rm=()=>Ct(nm,{title:"Metrics with a high number of series",children:Ct("ul",{children:[Ct("li",{children:["Identify and eliminate labels with frequently changed values to reduce their\xa0",Ct(il,{href:"https://docs.victoriametrics.com/FAQ.html#what-is-high-cardinality",children:"cardinality"}),"\xa0and\xa0",Ct(il,{href:"https://docs.victoriametrics.com/FAQ.html#what-is-high-churn-rate",children:"high churn rate"})]}),Ct("li",{children:["Find unused time series and\xa0",Ct(il,{href:"https://docs.victoriametrics.com/relabeling.html",children:"drop entire metrics"})]}),Ct("li",{children:["Aggregate time series before they got ingested into the database via\xa0",Ct(il,{href:"https://docs.victoriametrics.com/stream-aggregation.html",children:"streaming aggregation"})]})]})}),am=()=>Ct(nm,{title:"Labels with a high number of unique values",children:Ct("ul",{children:[Ct("li",{children:"Decrease the number of unique label values to reduce cardinality"}),Ct("li",{children:["Drop the label entirely via\xa0",Ct(il,{href:"https://docs.victoriametrics.com/relabeling.html",children:"relabeling"})]}),Ct("li",{children:"For volatile label values (such as URL path, user session, etc.) consider printing them to the log file instead of adding to time series"})]})}),im=()=>Ct(nm,{title:"Dashboard of a single metric",children:[Ct("p",{children:"This dashboard helps to understand the cardinality of a single metric."}),Ct("p",{children:"Each time series is a unique combination of key-value label pairs. Therefore a label key with many values can create a lot of time series for a particular metric. If you\u2019re trying to decrease the cardinality of a metric, start by looking at the labels with the highest number of values."}),Ct("p",{children:"Use the series selector at the top of the page to apply additional filters."})]}),om=()=>Ct(nm,{title:"Dashboard of a label",children:[Ct("p",{children:"This dashboard helps you understand the count of time series per label."}),Ct("p",{children:"Use the selector at the top of the page to pick a label name you\u2019d like to inspect. For the selected label name, you\u2019ll see the label values that have the highest number of series associated with them. So if you\u2019ve chosen `instance` as your label name, you may see that `657` time series have value \u201chost-1\u201d attached to them and `580` time series have value `host-2` attached to them."}),Ct("p",{children:"This can be helpful in allowing you to determine where the bulk of your time series are coming from. If the label \u201cinstance=host-1\u201d was applied to 657 series and the label \u201cinstance=host-2\u201d was only applied to 580 series, you\u2019d know, for example, that host-01 was responsible for sending the majority of the time series."})]}),lm=()=>{const{isMobile:e}=Wr(),[t]=je(),{setSearchParamsFromKeys:n}=ii(),r=t.get("tips")||"",a=t.get("match")||"",i=t.get("focusLabel")||"",{isLoading:o,appConfigurator:l,error:s,isCluster:c}=Vh(),{tsdbStatusData:u,getDefaultState:d,tablesHeaders:h,sectionsTips:m}=l,p=d(a,i);return Ct("div",{className:xr()({"vm-cardinality-panel":!0,"vm-cardinality-panel_mobile":e}),children:[o&&Ct(rl,{message:"Please wait while cardinality stats is calculated. \n This may take some time if the db contains big number of time series."}),Ct(Yh,{isPrometheus:l.isPrometheusData,totalSeries:u.totalSeries,totalSeriesPrev:u.totalSeriesPrev,totalSeriesAll:u.totalSeriesByAll,totalLabelValuePairs:u.totalLabelValuePairs,seriesCountByMetricName:u.seriesCountByMetricName,isCluster:c}),r&&Ct("div",{className:"vm-cardinality-panel-tips",children:[!a&&!i&&Ct(rm,{}),a&&!i&&Ct(im,{}),!a&&!i&&Ct(am,{}),i&&Ct(om,{})]}),s&&Ct(Qr,{variant:"error",children:s}),l.keys(a,i).map((e=>{return Ct(tm,{sectionTitle:l.sectionsTitles(i)[e],tip:m[e],rows:u[e],onActionClick:(t=e,e=>{const r={match:$h[t]({query:e,focusLabel:i,match:a})};"labelValueCountByLabelName"!==t&&"seriesCountByLabelName"!=t||(r.focusLabel=e),"seriesCountByFocusLabelValue"==t&&(r.focusLabel=""),n(r)}),tabs:p.tabs[e],chartContainer:p.containerRefs[e],totalSeriesPrev:l.totalSeries(e,!0),totalSeries:l.totalSeries(e),tableHeaderCells:h[e],isPrometheus:l.isPrometheusData},e);var t}))]})},sm=e=>(["topByAvgDuration","topByCount","topBySumDuration"].forEach((t=>{const n=e[t];Array.isArray(n)&&n.forEach((e=>{const t=Jt(1e3*e.timeRangeSeconds);e.url=((e,t)=>{var n;const{query:r,timeRangeSeconds:a}=e,i=["g0.expr=".concat(encodeURIComponent(r))],o=null===(n=en.find((e=>e.duration===t)))||void 0===n?void 0:n.id;return o&&i.push("g0.relative_time=".concat(o)),a&&i.push("g0.range_input=".concat(t)),"".concat(Ye.home,"?").concat(i.join("&"))})(e,t),e.timeRange=t}))})),e),cm=e=>{let{topN:t,maxLifetime:n}=e;const{serverUrl:a}=Nt(),{setSearchParamsFromKeys:i}=ii(),[o,l]=(0,r.useState)(null),[s,c]=(0,r.useState)(!1),[u,d]=(0,r.useState)(),h=(0,r.useMemo)((()=>((e,t,n)=>"".concat(e,"/api/v1/status/top_queries?topN=").concat(t||"","&maxLifetime=").concat(n||""))(a,t,n)),[a,t,n]);return{data:o,error:u,loading:s,fetch:async()=>{c(!0),i({topN:t,maxLifetime:n});try{const e=await fetch(h),t=await e.json();l(e.ok?sm(t):null),d(String(t.error||""))}catch(rp){rp instanceof Error&&"AbortError"!==rp.name&&d("".concat(rp.name,": ").concat(rp.message))}c(!1)}}},um=e=>{let{rows:t,columns:n,defaultOrderBy:a}=e;const i=Uo(),[o,l]=(0,r.useState)(a||"count"),[s,c]=(0,r.useState)("desc"),u=(0,r.useMemo)((()=>Gh(t,Zh(s,o))),[t,o,s]),d=e=>()=>{var t;t=e,c((e=>"asc"===e&&o===t?"desc":"asc")),l(t)},h=e=>{let{query:t}=e;return async()=>{await i(t,"Query has been copied")}};return Ct("table",{className:"vm-table",children:[Ct("thead",{className:"vm-table-header",children:Ct("tr",{className:"vm-table__row vm-table__row_header",children:[n.map((e=>Ct("th",{className:"vm-table-cell vm-table-cell_header vm-table-cell_sort",onClick:d(e.sortBy||e.key),children:Ct("div",{className:"vm-table-cell__content",children:[e.title||e.key,Ct("div",{className:xr()({"vm-table__sort-icon":!0,"vm-table__sort-icon_active":o===e.key,"vm-table__sort-icon_desc":"desc"===s&&o===e.key}),children:Ct(Vn,{})})]})},e.key))),Ct("th",{className:"vm-table-cell vm-table-cell_header"})," "]})}),Ct("tbody",{className:"vm-table-body",children:u.map(((e,t)=>Ct("tr",{className:"vm-table__row",children:[n.map((t=>Ct("td",{className:"vm-table-cell",children:e[t.key]||"-"},t.key))),Ct("td",{className:"vm-table-cell vm-table-cell_no-padding",children:Ct("div",{className:"vm-top-queries-panels__table-actions",children:[e.url&&Ct(fa,{title:"Execute query",children:Ct(Ie,{to:e.url,target:"_blank",rel:"noreferrer","aria-disabled":!0,children:Ct(aa,{variant:"text",size:"small",startIcon:Ct(Wn,{}),ariaLabel:"execute query"})})}),Ct(fa,{title:"Copy query",children:Ct(aa,{variant:"text",size:"small",startIcon:Ct(ar,{}),onClick:h(e),ariaLabel:"copy query"})})]})})]},t)))})]})},dm=["table","JSON"].map(((e,t)=>({value:String(t),label:e,icon:Ct(0===t?Qn:Zn,{})}))),hm=e=>{let{rows:t,title:n,columns:a,defaultOrderBy:i}=e;const{isMobile:o}=Wr(),[l,s]=(0,r.useState)(0);return Ct("div",{className:xr()({"vm-top-queries-panel":!0,"vm-block":!0,"vm-block_mobile":o}),children:[Ct("div",{className:xr()({"vm-top-queries-panel-header":!0,"vm-section-header":!0,"vm-top-queries-panel-header_mobile":o}),children:[Ct("h5",{className:xr()({"vm-section-header__title":!0,"vm-section-header__title_mobile":o}),children:n}),Ct("div",{className:"vm-section-header__tabs",children:Ct(Mr,{activeItem:String(l),items:dm,onChange:e=>{s(+e)}})})]}),Ct("div",{className:xr()({"vm-top-queries-panel__table":!0,"vm-top-queries-panel__table_mobile":o}),children:[0===l&&Ct(um,{rows:t,columns:a,defaultOrderBy:i}),1===l&&Ct(yh,{data:t})]})]})},mm=()=>{const{isMobile:e}=Wr(),[t,n]=qh(10,"topN"),[a,o]=qh("10m","maxLifetime"),{data:l,error:s,loading:c,fetch:u}=cm({topN:t,maxLifetime:a}),d=(0,r.useMemo)((()=>{const e=a.trim().split(" ").reduce(((e,t)=>{const n=Yt(t);return n?{...e,...n}:{...e}}),{});return!!i().duration(e).asMilliseconds()}),[a]),h=(0,r.useMemo)((()=>!!t&&t<1),[t]),m=(0,r.useMemo)((()=>h?"Number must be bigger than zero":""),[h]),p=(0,r.useMemo)((()=>d?"":"Invalid duration value"),[d]),f=e=>{if(!l)return e;const t=l[e];return"number"===typeof t?vd(t,t,t):t||e},v=e=>{"Enter"===e.key&&u()};return(0,r.useEffect)((()=>{l&&(t||n(+l.topN),a||o(l.maxLifetime))}),[l]),(0,r.useEffect)((()=>(u(),window.addEventListener("popstate",u),()=>{window.removeEventListener("popstate",u)})),[]),Ct("div",{className:xr()({"vm-top-queries":!0,"vm-top-queries_mobile":e}),children:[c&&Ct(rl,{containerStyles:{height:"500px"}}),Ct("div",{className:xr()({"vm-top-queries-controls":!0,"vm-block":!0,"vm-block_mobile":e}),children:[Ct("div",{className:"vm-top-queries-controls-fields",children:[Ct("div",{className:"vm-top-queries-controls-fields__item",children:Ct(Ha,{label:"Max lifetime",value:a,error:p,helperText:"For example ".concat("30ms, 15s, 3d4h, 1y2w"),onChange:e=>{o(e)},onKeyDown:v})}),Ct("div",{className:"vm-top-queries-controls-fields__item",children:Ct(Ha,{label:"Number of returned queries",type:"number",value:t||"",error:m,onChange:e=>{n(+e)},onKeyDown:v})})]}),Ct("div",{className:xr()({"vm-top-queries-controls-bottom":!0,"vm-top-queries-controls-bottom_mobile":e}),children:[Ct("div",{className:"vm-top-queries-controls-bottom__info",children:["VictoriaMetrics tracks the last\xa0",Ct(fa,{title:"search.queryStats.lastQueriesCount",children:Ct("b",{children:f("search.queryStats.lastQueriesCount")})}),"\xa0queries with durations at least\xa0",Ct(fa,{title:"search.queryStats.minQueryDuration",children:Ct("b",{children:f("search.queryStats.minQueryDuration")})})]}),Ct("div",{className:"vm-top-queries-controls-bottom__button",children:Ct(aa,{startIcon:Ct(Yn,{}),onClick:u,children:"Execute"})})]})]}),s&&Ct(Qr,{variant:"error",children:s}),l&&Ct(xt.FK,{children:Ct("div",{className:"vm-top-queries-panels",children:[Ct(hm,{rows:l.topBySumDuration,title:"Queries with most summary time to execute",columns:[{key:"query"},{key:"sumDurationSeconds",title:"sum duration, sec"},{key:"timeRange",sortBy:"timeRangeSeconds",title:"query time interval"},{key:"count"}],defaultOrderBy:"sumDurationSeconds"}),Ct(hm,{rows:l.topByAvgDuration,title:"Most heavy queries",columns:[{key:"query"},{key:"avgDurationSeconds",title:"avg duration, sec"},{key:"timeRange",sortBy:"timeRangeSeconds",title:"query time interval"},{key:"count"}],defaultOrderBy:"avgDurationSeconds"}),Ct(hm,{rows:l.topByCount,title:"Most frequently executed queries",columns:[{key:"query"},{key:"timeRange",sortBy:"timeRangeSeconds",title:"query time interval"},{key:"count"}]})]})})]})},pm={"color-primary":"#589DF6","color-secondary":"#316eca","color-error":"#e5534b","color-warning":"#c69026","color-info":"#539bf5","color-success":"#57ab5a","color-background-body":"#22272e","color-background-block":"#2d333b","color-background-tooltip":"rgba(22, 22, 22, 0.8)","color-text":"#cdd9e5","color-text-secondary":"#768390","color-text-disabled":"#636e7b","box-shadow":"rgba(0, 0, 0, 0.16) 1px 2px 6px","box-shadow-popper":"rgba(0, 0, 0, 0.2) 0px 2px 8px 0px","border-divider":"1px solid rgba(99, 110, 123, 0.5)","color-hover-black":"rgba(0, 0, 0, 0.12)"},fm={"color-primary":"#3F51B5","color-secondary":"#E91E63","color-error":"#FD080E","color-warning":"#FF8308","color-info":"#03A9F4","color-success":"#4CAF50","color-background-body":"#FEFEFF","color-background-block":"#FFFFFF","color-background-tooltip":"rgba(80,80,80,0.9)","color-text":"#110f0f","color-text-secondary":"#706F6F","color-text-disabled":"#A09F9F","box-shadow":"rgba(0, 0, 0, 0.08) 1px 2px 6px","box-shadow-popper":"rgba(0, 0, 0, 0.1) 0px 2px 8px 0px","border-divider":"1px solid rgba(0, 0, 0, 0.15)","color-hover-black":"rgba(0, 0, 0, 0.06)"},vm=()=>{const[e,t]=(0,r.useState)(gt()),n=e=>{t(e.matches)};return(0,r.useEffect)((()=>{const e=window.matchMedia("(prefers-color-scheme: dark)");return e.addEventListener("change",n),()=>e.removeEventListener("change",n)}),[]),e},gm=["primary","secondary","error","warning","info","success"],ym=e=>{let{onLoaded:t}=e;const n=Ke(),{palette:a={}}=We(),{theme:i}=Nt(),o=vm(),l=At(),s=Ar(),[c,u]=(0,r.useState)({[mt.dark]:pm,[mt.light]:fm,[mt.system]:gt()?pm:fm}),d=()=>{const{innerWidth:e,innerHeight:t}=window,{clientWidth:n,clientHeight:r}=document.documentElement;vt("scrollbar-width","".concat(e-n,"px")),vt("scrollbar-height","".concat(t-r,"px")),vt("vh","".concat(.01*t,"px"))},h=()=>{gm.forEach(((e,n)=>{const r=(e=>{let t=e.replace("#","").trim();if(3===t.length&&(t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),6!==t.length)throw new Error("Invalid HEX color.");return(299*parseInt(t.slice(0,2),16)+587*parseInt(t.slice(2,4),16)+114*parseInt(t.slice(4,6),16))/1e3>=128?"#000000":"#FFFFFF"})(ft("color-".concat(e)));vt("".concat(e,"-text"),r),n===gm.length-1&&(l({type:"SET_DARK_THEME"}),t(!0))}))},m=()=>{const e=Xe("THEME")||mt.system,t=c[e];Object.entries(t).forEach((e=>{let[t,n]=e;vt(t,n)})),h(),n&&(gm.forEach((e=>{const t=a[e];t&&vt("color-".concat(e),t)})),h())};return(0,r.useEffect)((()=>{d(),m()}),[c]),(0,r.useEffect)(d,[s]),(0,r.useEffect)((()=>{const e=gt()?pm:fm;c[mt.system]!==e?u((t=>({...t,[mt.system]:e}))):m()}),[i,o]),(0,r.useEffect)((()=>{n&&l({type:"SET_THEME",payload:mt.light})}),[]),null},_m=()=>{const[e,t]=(0,r.useState)([]),[n,a]=(0,r.useState)(!1),i=(0,r.useRef)(document.body),o=e=>{e.preventDefault(),e.stopPropagation(),"dragenter"===e.type||"dragover"===e.type?a(!0):"dragleave"===e.type&&a(!1)};return Nr("dragenter",o,i),Nr("dragleave",o,i),Nr("dragover",o,i),Nr("drop",(e=>{var n;e.preventDefault(),e.stopPropagation(),a(!1),null!==e&&void 0!==e&&null!==(n=e.dataTransfer)&&void 0!==n&&n.files&&e.dataTransfer.files[0]&&(e=>{const n=Array.from(e||[]);t(n)})(e.dataTransfer.files)}),i),Nr("paste",(e=>{var n;const r=null===(n=e.clipboardData)||void 0===n?void 0:n.items;if(!r)return;const a=Array.from(r).filter((e=>"application/json"===e.type)).map((e=>e.getAsFile())).filter((e=>null!==e));t(a)}),i),{files:e,dragging:n}},bm=e=>{let{onOpenModal:t,onChange:n}=e;return Ct("div",{className:"vm-upload-json-buttons",children:[Ct(aa,{variant:"outlined",onClick:t,children:"Paste JSON"}),Ct(aa,{children:["Upload Files",Ct("input",{id:"json",type:"file",accept:"application/json",multiple:!0,title:" ",onChange:n})]})]})},wm=()=>{const[e,t]=(0,r.useState)([]),[n,a]=(0,r.useState)([]),i=(0,r.useMemo)((()=>!!e.length),[e]),{value:o,setTrue:l,setFalse:s}=oa(!1),c=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";a((n=>[{filename:t,text:": ".concat(e.message)},...n]))},u=(e,n)=>{try{const r=JSON.parse(e),a=r.trace||r;if(!a.duration_msec)return void c(new Error(ht.traceNotFound),n);const i=new Go(a,n);t((e=>[i,...e]))}catch(rp){rp instanceof Error&&c(rp,n)}},d=e=>{e.map((e=>{const t=new FileReader,n=(null===e||void 0===e?void 0:e.name)||"";t.onload=e=>{var t;const r=String(null===(t=e.target)||void 0===t?void 0:t.result);u(r,n)},t.readAsText(e)}))},h=e=>{a([]);const t=Array.from(e.target.files||[]);d(t),e.target.value=""},m=e=>()=>{(e=>{a((t=>t.filter(((t,n)=>n!==e))))})(e)},{files:p,dragging:f}=_m();return(0,r.useEffect)((()=>{d(p)}),[p]),Ct("div",{className:"vm-trace-page",children:[Ct("div",{className:"vm-trace-page-header",children:[Ct("div",{className:"vm-trace-page-header-errors",children:n.map(((e,t)=>Ct("div",{className:"vm-trace-page-header-errors-item",children:[Ct(Qr,{variant:"error",children:[Ct("b",{className:"vm-trace-page-header-errors-item__filename",children:e.filename}),Ct("span",{children:e.text})]}),Ct(aa,{className:"vm-trace-page-header-errors-item__close",startIcon:Ct(On,{}),variant:"text",color:"error",onClick:m(t)})]},"".concat(e,"_").concat(t))))}),Ct("div",{children:i&&Ct(bm,{onOpenModal:l,onChange:h})})]}),i&&Ct("div",{children:Ct(ml,{jsonEditor:!0,traces:e,onDeleteClick:n=>{const r=e.filter((e=>e.idValue!==n.idValue));t([...r])}})}),!i&&Ct("div",{className:"vm-trace-page-preview",children:[Ct("p",{className:"vm-trace-page-preview__text",children:["Please, upload file with JSON response content.","\n","The file must contain tracing information in JSON format.","\n","In order to use tracing please refer to the doc:\xa0",Ct("a",{className:"vm-link vm-link_colored",href:"https://docs.victoriametrics.com/#query-tracing",target:"_blank",rel:"help noreferrer",children:"https://docs.victoriametrics.com/#query-tracing"}),"\n","Tracing graph will be displayed after file upload.","\n","Attach files by dragging & dropping, selecting or pasting them."]}),Ct(bm,{onOpenModal:l,onChange:h})]}),o&&Ct(pa,{title:"Paste JSON",onClose:s,children:Ct(hl,{editable:!0,displayTitle:!0,defaultTile:"JSON ".concat(e.length+1),onClose:s,onUpload:u})}),f&&Ct("div",{className:"vm-trace-page__dropzone"})]})},km=e=>{const{serverUrl:t}=Nt(),{period:n}=vn(),[a,i]=(0,r.useState)([]),[o,l]=(0,r.useState)(!1),[s,c]=(0,r.useState)(),u=(0,r.useMemo)((()=>((e,t,n)=>{const r="{job=".concat(JSON.stringify(n),"}");return"".concat(e,"/api/v1/label/instance/values?match[]=").concat(encodeURIComponent(r),"&start=").concat(t.start,"&end=").concat(t.end)})(t,n,e)),[t,n,e]);return(0,r.useEffect)((()=>{if(!e)return;(async()=>{l(!0);try{const e=await fetch(u),t=await e.json(),n=t.data||[];i(n.sort(((e,t)=>e.localeCompare(t)))),e.ok?c(void 0):c("".concat(t.errorType,"\r\n").concat(null===t||void 0===t?void 0:t.error))}catch(rp){rp instanceof Error&&c("".concat(rp.name,": ").concat(rp.message))}l(!1)})().catch(console.error)}),[u]),{instances:a,isLoading:o,error:s}},xm=(e,t)=>{const{serverUrl:n}=Nt(),{period:a}=vn(),[i,o]=(0,r.useState)([]),[l,s]=(0,r.useState)(!1),[c,u]=(0,r.useState)(),d=(0,r.useMemo)((()=>((e,t,n,r)=>{const a=Object.entries({job:n,instance:r}).filter((e=>e[1])).map((e=>{let[t,n]=e;return"".concat(t,"=").concat(JSON.stringify(n))})).join(","),i="{".concat(a,"}");return"".concat(e,"/api/v1/label/__name__/values?match[]=").concat(encodeURIComponent(i),"&start=").concat(t.start,"&end=").concat(t.end)})(n,a,e,t)),[n,a,e,t]);return(0,r.useEffect)((()=>{if(!e)return;(async()=>{s(!0);try{const e=await fetch(d),t=await e.json(),n=t.data||[];o(n.sort(((e,t)=>e.localeCompare(t)))),e.ok?u(void 0):u("".concat(t.errorType,"\r\n").concat(null===t||void 0===t?void 0:t.error))}catch(rp){rp instanceof Error&&u("".concat(rp.name,": ").concat(rp.message))}s(!1)})().catch(console.error)}),[d]),{names:i,isLoading:l,error:c}},Sm=e=>{let{name:t,job:n,instance:a,rateEnabled:i,isBucket:o,height:l}=e;const{isMobile:s}=Wr(),{customStep:c,yaxis:u}=Ur(),{period:d}=vn(),h=Br(),m=gn(),p=Kt(d.end-d.start),f=Wt(c),v=Jt(10*f*1e3),[g,y]=(0,r.useState)(!1),[_,b]=(0,r.useState)(!1),w=g&&c===p?v:c,k=(0,r.useMemo)((()=>{const e=Object.entries({job:n,instance:a}).filter((e=>e[1])).map((e=>{let[t,n]=e;return"".concat(t,"=").concat(JSON.stringify(n))}));e.push("__name__=".concat(JSON.stringify(t))),"node_cpu_seconds_total"==t&&e.push('mode!="idle"');const r="{".concat(e.join(","),"}");if(o)return"sum(rate(".concat(r,")) by (vmrange, le)");const l=i?"rollup_rate(".concat(r,")"):"rollup(".concat(r,")");return"\nwith (q = ".concat(l,') (\n alias(min(label_match(q, "rollup", "min")), "min"),\n alias(max(label_match(q, "rollup", "max")), "max"),\n alias(avg(label_match(q, "rollup", "avg")), "avg"),\n)')}),[t,n,a,i,o]),{isLoading:x,graphData:S,error:C,queryErrors:E,warning:N,isHistogram:A}=nl({predefinedQuery:[k],visible:!0,customStep:w,showAllSeries:_});return(0,r.useEffect)((()=>{y(A)}),[A]),Ct("div",{className:xr()({"vm-explore-metrics-graph":!0,"vm-explore-metrics-graph_mobile":s}),children:[x&&Ct(rl,{}),C&&Ct(Qr,{variant:"error",children:C}),E[0]&&Ct(Qr,{variant:"error",children:E[0]}),N&&Ct(fl,{warning:N,query:[k],onChange:b}),S&&d&&Ct(hh,{data:S,period:d,customStep:w,query:[k],yaxis:u,setYaxisLimits:e=>{h({type:"SET_YAXIS_LIMITS",payload:e})},setPeriod:e=>{let{from:t,to:n}=e;m({type:"SET_PERIOD",payload:{from:t,to:n}})},showLegend:!1,height:l,isHistogram:A})]})},Cm=e=>{let{name:t,index:n,length:r,isBucket:a,rateEnabled:i,onChangeRate:o,onRemoveItem:l,onChangeOrder:s}=e;const{isMobile:c}=Wr(),{value:u,setTrue:d,setFalse:h}=oa(!1),m=()=>{l(t)},p=()=>{s(t,n,n+1)},f=()=>{s(t,n,n-1)};return Ct("div",c?{className:"vm-explore-metrics-item-header vm-explore-metrics-item-header_mobile",children:[Ct("div",{className:"vm-explore-metrics-item-header__name",children:t}),Ct(aa,{variant:"text",size:"small",startIcon:Ct(dr,{}),onClick:d,ariaLabel:"open panel settings"}),u&&Ct(pa,{title:t,onClose:h,children:Ct("div",{className:"vm-explore-metrics-item-header-modal",children:[Ct("div",{className:"vm-explore-metrics-item-header-modal-order",children:[Ct(aa,{startIcon:Ct(Xn,{}),variant:"outlined",onClick:f,disabled:0===n,ariaLabel:"move graph up"}),Ct("p",{children:["position:",Ct("span",{className:"vm-explore-metrics-item-header-modal-order__index",children:["#",n+1]})]}),Ct(aa,{endIcon:Ct(Jn,{}),variant:"outlined",onClick:p,disabled:n===r-1,ariaLabel:"move graph down"})]}),!a&&Ct("div",{className:"vm-explore-metrics-item-header-modal__rate",children:[Ct(jo,{label:Ct("span",{children:["enable ",Ct("code",{children:"rate()"})]}),value:i,onChange:o,fullWidth:!0}),Ct("p",{children:"calculates the average per-second speed of metrics change"})]}),Ct(aa,{startIcon:Ct(On,{}),color:"error",variant:"outlined",onClick:m,fullWidth:!0,children:"Remove graph"})]})})]}:{className:"vm-explore-metrics-item-header",children:[Ct("div",{className:"vm-explore-metrics-item-header-order",children:[Ct(fa,{title:"move graph up",children:Ct(aa,{className:"vm-explore-metrics-item-header-order__up",startIcon:Ct(Hn,{}),variant:"text",color:"gray",size:"small",onClick:f,ariaLabel:"move graph up"})}),Ct("div",{className:"vm-explore-metrics-item-header__index",children:["#",n+1]}),Ct(fa,{title:"move graph down",children:Ct(aa,{className:"vm-explore-metrics-item-header-order__down",startIcon:Ct(Hn,{}),variant:"text",color:"gray",size:"small",onClick:p,ariaLabel:"move graph down"})})]}),Ct("div",{className:"vm-explore-metrics-item-header__name",children:t}),!a&&Ct("div",{className:"vm-explore-metrics-item-header__rate",children:Ct(fa,{title:"calculates the average per-second speed of metric's change",children:Ct(jo,{label:Ct("span",{children:["enable ",Ct("code",{children:"rate()"})]}),value:i,onChange:o})})}),Ct("div",{className:"vm-explore-metrics-item-header__close",children:Ct(fa,{title:"close graph",children:Ct(aa,{startIcon:Ct(On,{}),variant:"text",color:"gray",size:"small",onClick:m,ariaLabel:"close graph"})})})]})},Em=e=>{let{name:t,job:n,instance:a,index:i,length:o,size:l,onRemoveItem:s,onChangeOrder:c}=e;const u=(0,r.useMemo)((()=>/_sum?|_total?|_count?/.test(t)),[t]),d=(0,r.useMemo)((()=>/_bucket?/.test(t)),[t]),[h,m]=(0,r.useState)(u),p=Ar(),f=(0,r.useMemo)(l.height,[l,p]);return(0,r.useEffect)((()=>{m(u)}),[n]),Ct("div",{className:"vm-explore-metrics-item vm-block vm-block_empty-padding",children:[Ct(Cm,{name:t,index:i,length:o,isBucket:d,rateEnabled:h,size:l.id,onChangeRate:m,onRemoveItem:s,onChangeOrder:c}),Ct(Sm,{name:t,job:n,instance:a,rateEnabled:h,isBucket:d,height:f},"".concat(t,"_").concat(n,"_").concat(a,"_").concat(h))]})},Nm=e=>{let{values:t,onRemoveItem:n}=e;const{isMobile:r}=Wr();return r?Ct("span",{className:"vm-select-input-content__counter",children:["selected ",t.length]}):Ct(xt.FK,{children:t.map((e=>{return Ct("div",{className:"vm-select-input-content__selected",children:[Ct("span",{children:e}),Ct("div",{onClick:(t=e,e=>{n(t),e.stopPropagation()}),children:Ct(On,{})})]},e);var t}))})},Am=e=>{let{value:t,list:n,label:a,placeholder:i,noOptionsText:o,clearable:l=!1,searchable:s=!1,autofocus:c,disabled:u,onChange:d}=e;const{isDarkTheme:h}=Nt(),{isMobile:m}=Wr(),[p,f]=(0,r.useState)(""),v=(0,r.useRef)(null),[g,y]=(0,r.useState)(null),[_,b]=(0,r.useState)(!1),w=(0,r.useRef)(null),k=Array.isArray(t),x=Array.isArray(t)?t:void 0,S=m&&k&&!(null===x||void 0===x||!x.length),C=(0,r.useMemo)((()=>_?p:Array.isArray(t)?"":t),[t,p,_,k]),E=(0,r.useMemo)((()=>_?p||"(.+)":""),[p,_]),N=()=>{w.current&&w.current.blur()},A=()=>{b(!1),N()},M=e=>{f(""),d(e),k||A(),k&&w.current&&w.current.focus()};return(0,r.useEffect)((()=>{f(""),_&&w.current&&w.current.focus(),_||N()}),[_,w]),(0,r.useEffect)((()=>{c&&w.current&&!m&&w.current.focus()}),[c,w]),Nr("keyup",(e=>{w.current!==e.target&&b(!1)})),ra(v,A,g),Ct("div",{className:xr()({"vm-select":!0,"vm-select_dark":h,"vm-select_disabled":u}),children:[Ct("div",{className:"vm-select-input",onClick:e=>{e.target instanceof HTMLInputElement||u||b((e=>!e))},ref:v,children:[Ct("div",{className:"vm-select-input-content",children:[!(null===x||void 0===x||!x.length)&&Ct(Nm,{values:x,onRemoveItem:M}),!S&&Ct("input",{value:C,type:"text",placeholder:i,onInput:e=>{f(e.target.value)},onFocus:()=>{u||b(!0)},onBlur:()=>{n.includes(p)&&d(p)},ref:w,readOnly:m||!s})]}),a&&Ct("span",{className:"vm-text-field__label",children:a}),l&&t&&Ct("div",{className:"vm-select-input__icon",onClick:(e=>t=>{M(e),t.stopPropagation()})(""),children:Ct(On,{})}),Ct("div",{className:xr()({"vm-select-input__icon":!0,"vm-select-input__icon_open":_}),children:Ct(Vn,{})})]}),Ct(Ti,{label:a,value:E,options:n.map((e=>({value:e}))),anchor:v,selected:x,minLength:1,fullWidth:!0,noOptionsText:o,onSelect:M,onOpenAutocomplete:b,onChangeWrapperRef:y})]})},Mm=lt.map((e=>e.id)),Tm=e=>{let{jobs:t,instances:n,names:a,job:i,instance:o,size:l,selectedMetrics:s,onChangeJob:c,onChangeInstance:u,onToggleMetric:d,onChangeSize:h}=e;const m=(0,r.useMemo)((()=>i?"":"No instances. Please select job"),[i]),p=(0,r.useMemo)((()=>i?"":"No metric names. Please select job"),[i]),{isMobile:f}=Wr(),{value:v,toggle:g,setFalse:y}=oa("false"!==Xe("EXPLORE_METRICS_TIPS"));return(0,r.useEffect)((()=>{Je("EXPLORE_METRICS_TIPS","".concat(v))}),[v]),Ct(xt.FK,{children:[Ct("div",{className:xr()({"vm-explore-metrics-header":!0,"vm-explore-metrics-header_mobile":f,"vm-block":!0,"vm-block_mobile":f}),children:[Ct("div",{className:"vm-explore-metrics-header__job",children:Ct(Am,{value:i,list:t,label:"Job",placeholder:"Please select job",onChange:c,autofocus:!i&&!!t.length&&!f,searchable:!0})}),Ct("div",{className:"vm-explore-metrics-header__instance",children:Ct(Am,{value:o,list:n,label:"Instance",placeholder:"Please select instance",onChange:u,noOptionsText:m,clearable:!0,searchable:!0})}),Ct("div",{className:"vm-explore-metrics-header__size",children:[Ct(Am,{label:"Size graphs",value:l,list:Mm,onChange:h}),Ct(fa,{title:"".concat(v?"Hide":"Show"," tip"),children:Ct(aa,{variant:"text",color:v?"warning":"gray",startIcon:Ct(mr,{}),onClick:g,ariaLabel:"visibility tips"})})]}),Ct("div",{className:"vm-explore-metrics-header-metrics",children:Ct(Am,{label:"Metrics",value:s,list:a,placeholder:"Search metric name",onChange:d,noOptionsText:p,clearable:!0,searchable:!0})})]}),v&&Ct(Qr,{variant:"warning",children:Ct("div",{className:"vm-explore-metrics-header-description",children:[Ct("p",{children:["Please note: this page is solely designed for exploring Prometheus metrics. Prometheus metrics always contain ",Ct("code",{children:"job"})," and ",Ct("code",{children:"instance"})," labels (see ",Ct("a",{className:"vm-link vm-link_colored",href:"https://prometheus.io/docs/concepts/jobs_instances/",children:"these docs"}),"), and this page relies on them as filters. ",Ct("br",{}),"Please use this page for Prometheus metrics only, in accordance with their naming conventions."]}),Ct(aa,{variant:"text",size:"small",startIcon:Ct(On,{}),onClick:y,ariaLabel:"close tips"})]})})]})},Lm=ct("job",""),Pm=ct("instance",""),Om=ct("metrics",""),Im=ct("size",""),Rm=lt.find((e=>Im?e.id===Im:e.isDefault))||lt[0],Dm=()=>{const[e,t]=(0,r.useState)(Lm),[n,a]=(0,r.useState)(Pm),[i,o]=(0,r.useState)(Om?Om.split("&"):[]),[l,s]=(0,r.useState)(Rm);(e=>{let{job:t,instance:n,metrics:a,size:i}=e;const{duration:o,relativeTime:l,period:{date:s}}=vn(),{customStep:c}=Ur(),{setSearchParamsFromKeys:u}=ii(),d=()=>{const e=al({"g0.range_input":o,"g0.end_input":s,"g0.step_input":c,"g0.relative_time":l,size:i,job:t,instance:n,metrics:a});u(e)};(0,r.useEffect)(d,[o,l,s,c,t,n,a,i]),(0,r.useEffect)(d,[])})({job:e,instance:n,metrics:i.join("&"),size:l.id});const{jobs:c,isLoading:u,error:d}=(()=>{const{serverUrl:e}=Nt(),{period:t}=vn(),[n,a]=(0,r.useState)([]),[i,o]=(0,r.useState)(!1),[l,s]=(0,r.useState)(),c=(0,r.useMemo)((()=>((e,t)=>"".concat(e,"/api/v1/label/job/values?start=").concat(t.start,"&end=").concat(t.end))(e,t)),[e,t]);return(0,r.useEffect)((()=>{(async()=>{o(!0);try{const e=await fetch(c),t=await e.json(),n=t.data||[];a(n.sort(((e,t)=>e.localeCompare(t)))),e.ok?s(void 0):s("".concat(t.errorType,"\r\n").concat(null===t||void 0===t?void 0:t.error))}catch(rp){rp instanceof Error&&s("".concat(rp.name,": ").concat(rp.message))}o(!1)})().catch(console.error)}),[c]),{jobs:n,isLoading:i,error:l}})(),{instances:h,isLoading:m,error:p}=km(e),{names:f,isLoading:v,error:g}=xm(e,n),y=(0,r.useMemo)((()=>u||m||v),[u,m,v]),_=(0,r.useMemo)((()=>d||p||g),[d,p,g]),b=e=>{o(e?t=>t.includes(e)?t.filter((t=>t!==e)):[...t,e]:[])},w=(e,t,n)=>{const r=n>i.length-1;n<0||r||o((e=>{const r=[...e],[a]=r.splice(t,1);return r.splice(n,0,a),r}))};return(0,r.useEffect)((()=>{n&&h.length&&!h.includes(n)&&a("")}),[h,n]),Ct("div",{className:"vm-explore-metrics",children:[Ct(Tm,{jobs:c,instances:h,names:f,job:e,size:l.id,instance:n,selectedMetrics:i,onChangeJob:t,onChangeSize:e=>{const t=lt.find((t=>t.id===e));t&&s(t)},onChangeInstance:a,onToggleMetric:b}),y&&Ct(rl,{}),_&&Ct(Qr,{variant:"error",children:_}),!e&&Ct(Qr,{variant:"info",children:"Please select job to see list of metric names."}),e&&!i.length&&Ct(Qr,{variant:"info",children:"Please select metric names to see the graphs."}),Ct("div",{className:"vm-explore-metrics-body",children:i.map(((t,r)=>Ct(Em,{name:t,job:e,instance:n,index:r,length:i.length,size:l,onRemoveItem:b,onChangeOrder:w},t)))})]})},zm=()=>{const t=Uo();return Ct("div",{className:"vm-preview-icons",children:Object.entries(e).map((e=>{let[n,r]=e;return Ct("div",{className:"vm-preview-icons-item",onClick:(a=n,async()=>{await t("<".concat(a,"/>"),"<".concat(a,"/> has been copied"))}),children:[Ct("div",{className:"vm-preview-icons-item__svg",children:r()}),Ct("div",{className:"vm-preview-icons-item__name",children:"<".concat(n,"/>")})]},n);var a}))})};var Fm=function(e){return e.copy="Copy",e.copied="Copied",e}(Fm||{});const jm=e=>{let{code:t}=e;const[n,a]=(0,r.useState)(Fm.copy);return(0,r.useEffect)((()=>{let e=null;return n===Fm.copied&&(e=setTimeout((()=>a(Fm.copy)),1e3)),()=>{e&&clearTimeout(e)}}),[n]),Ct("code",{className:"vm-code-example",children:[t,Ct("div",{className:"vm-code-example__copy",children:Ct(fa,{title:n,children:Ct(aa,{size:"small",variant:"text",onClick:()=>{navigator.clipboard.writeText(t),a(Fm.copied)},startIcon:Ct(ar,{}),ariaLabel:"close"})})})]})},Hm=()=>Ct("a",{className:"vm-link vm-link_colored",href:"https://docs.victoriametrics.com/MetricsQL.html",target:"_blank",rel:"help noreferrer",children:"MetricsQL"}),Vm=()=>Ct("a",{className:"vm-link vm-link_colored",href:"https://grafana.com/grafana/dashboards/1860-node-exporter-full/",target:"_blank",rel:"help noreferrer",children:"Node Exporter Full"}),$m=()=>Ct("section",{className:"vm-with-template-tutorial",children:[Ct("h2",{className:"vm-with-template-tutorial__title",children:["Tutorial for WITH expressions in ",Ct(Hm,{})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:["Let's look at the following real query from ",Ct(Vm,{})," dashboard:"]}),Ct(jm,{code:'(\n (\n node_memory_MemTotal_bytes{instance=~"$node:$port", job=~"$job"}\n -\n node_memory_MemFree_bytes{instance=~"$node:$port", job=~"$job"}\n )\n /\n node_memory_MemTotal_bytes{instance=~"$node:$port", job=~"$job"}\n) * 100'}),Ct("p",{className:"vm-with-template-tutorial-section__text",children:"It is clear the query calculates the percentage of used memory for the given $node, $port and $job. Isn't it? :)"})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:"What's wrong with this query? Copy-pasted label filters for distinct timeseries which makes it easy to mistype these filters during modification. Let's simplify the query with WITH expressions:"}),Ct(jm,{code:'WITH (\n commonFilters = {instance=~"$node:$port",job=~"$job"}\n)\n(\n node_memory_MemTotal_bytes{commonFilters}\n -\n node_memory_MemFree_bytes{commonFilters}\n)\n /\nnode_memory_MemTotal_bytes{commonFilters} * 100'})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:["Now label filters are located in a single place instead of three distinct places. The query mentions node_memory_MemTotal_bytes metric twice and ","{commonFilters}"," three times. WITH expressions may improve this:"]}),Ct(jm,{code:'WITH (\n my_resource_utilization(free, limit, filters) = (limit{filters} - free{filters}) / limit{filters} * 100\n)\nmy_resource_utilization(\n node_memory_MemFree_bytes,\n node_memory_MemTotal_bytes,\n {instance=~"$node:$port",job=~"$job"},\n)'}),Ct("p",{className:"vm-with-template-tutorial-section__text",children:"Now the template function my_resource_utilization() may be used for monitoring arbitrary resources - memory, CPU, network, storage, you name it."})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:["Let's take another nice query from ",Ct(Vm,{})," dashboard:"]}),Ct(jm,{code:'(\n (\n (\n count(\n count(node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"}) by (cpu)\n )\n )\n -\n avg(\n sum by (mode) (rate(node_cpu_seconds_total{mode=\'idle\',instance=~"$node:$port",job=~"$job"}[5m]))\n )\n )\n *\n 100\n)\n /\ncount(\n count(node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"}) by (cpu)\n)'}),Ct("p",{className:"vm-with-template-tutorial-section__text",children:"Do you understand what does this mess do? Is it manageable? :) WITH expressions are happy to help in a few iterations."})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:"1. Extract common filters used in multiple places into a commonFilters variable:"}),Ct(jm,{code:'WITH (\n commonFilters = {instance=~"$node:$port",job=~"$job"}\n)\n(\n (\n (\n count(\n count(node_cpu_seconds_total{commonFilters}) by (cpu)\n )\n )\n -\n avg(\n sum by (mode) (rate(node_cpu_seconds_total{mode=\'idle\',commonFilters}[5m]))\n )\n )\n *\n 100\n)\n /\ncount(\n count(node_cpu_seconds_total{commonFilters}) by (cpu)\n)'})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:'2. Extract "count(count(...) by (cpu))" into cpuCount variable:'}),Ct(jm,{code:'WITH (\n commonFilters = {instance=~"$node:$port",job=~"$job"},\n cpuCount = count(count(node_cpu_seconds_total{commonFilters}) by (cpu))\n)\n(\n (\n cpuCount\n -\n avg(\n sum by (mode) (rate(node_cpu_seconds_total{mode=\'idle\',commonFilters}[5m]))\n )\n )\n *\n 100\n) / cpuCount'})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:"3. Extract rate(...) part into cpuIdle variable, since it is clear now that this part calculates the number of idle CPUs:"}),Ct(jm,{code:'WITH (\n commonFilters = {instance=~"$node:$port",job=~"$job"},\n cpuCount = count(count(node_cpu_seconds_total{commonFilters}) by (cpu)),\n cpuIdle = sum(rate(node_cpu_seconds_total{mode=\'idle\',commonFilters}[5m]))\n)\n((cpuCount - cpuIdle) * 100) / cpuCount'})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:["4. Put node_cpu_seconds_total","{commonFilters}"," into its own varialbe with the name cpuSeconds:"]}),Ct(jm,{code:'WITH (\n cpuSeconds = node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"},\n cpuCount = count(count(cpuSeconds) by (cpu)),\n cpuIdle = sum(rate(cpuSeconds{mode=\'idle\'}[5m]))\n)\n((cpuCount - cpuIdle) * 100) / cpuCount'}),Ct("p",{className:"vm-with-template-tutorial-section__text",children:"Now the query became more clear comparing to the initial query."})]}),Ct("div",{className:"vm-with-template-tutorial-section",children:[Ct("p",{className:"vm-with-template-tutorial-section__text",children:"WITH expressions may be nested and may be put anywhere. Try expanding the following query:"}),Ct(jm,{code:"WITH (\n f(a, b) = WITH (\n f1(x) = b-x,\n f2(x) = x+x\n ) f1(a)*f2(b)\n) f(foo, with(x=bar) x)"})]})]}),Um=()=>{const{serverUrl:e}=Nt(),[t,n]=je(),[a,i]=(0,r.useState)(""),[o,l]=(0,r.useState)(!1),[s,c]=(0,r.useState)();return{data:a,error:s,loading:o,expand:async r=>{t.set("expr",r),n(t);const a=((e,t)=>"".concat(e,"/expand-with-exprs?query=").concat(encodeURIComponent(t),"&format=json"))(e,r);l(!0);try{const e=await fetch(a),t=await e.json();i((null===t||void 0===t?void 0:t.expr)||""),c(String(t.error||""))}catch(rp){rp instanceof Error&&"AbortError"!==rp.name&&c("".concat(rp.name,": ").concat(rp.message))}l(!1)}}},Bm=()=>{const[e]=je(),{data:t,loading:n,error:a,expand:i}=Um(),[o,l]=(0,r.useState)(e.get("expr")||""),s=()=>{i(o)};return(0,r.useEffect)((()=>{o&&i(o)}),[]),Ct("section",{className:"vm-with-template",children:[n&&Ct(rl,{}),Ct("div",{className:"vm-with-template-body vm-block",children:[Ct("div",{className:"vm-with-template-body__expr",children:Ct(Ha,{type:"textarea",label:"MetricsQL query with optional WITH expressions",value:o,error:a,autofocus:!0,onEnter:s,onChange:e=>{l(e)}})}),Ct("div",{className:"vm-with-template-body__result",children:Ct(Ha,{type:"textarea",label:"MetricsQL query after expanding WITH expressions and applying other optimizations",value:t,disabled:!0})}),Ct("div",{className:"vm-with-template-body-top",children:Ct(aa,{variant:"contained",onClick:s,startIcon:Ct(Yn,{}),children:"Expand"})})]}),Ct("div",{className:"vm-block",children:Ct($m,{})})]})},qm=()=>{const{serverUrl:e}=Nt(),[t,n]=(0,r.useState)(null),[a,i]=(0,r.useState)(!1),[o,l]=(0,r.useState)();return{data:t,error:o,loading:a,fetchData:async(t,r)=>{const a=((e,t,n)=>{const r=["format=json","relabel_configs=".concat(encodeURIComponent(t)),"metric=".concat(encodeURIComponent(n))];return"".concat(e,"/metric-relabel-debug?").concat(r.join("&"))})(e,t,r);i(!0);try{const e=await fetch(a),t=await e.json();n(t.error?null:t),l(String(t.error||""))}catch(rp){rp instanceof Error&&"AbortError"!==rp.name&&l("".concat(rp.name,": ").concat(rp.message))}i(!1)}}},Ym={config:'- if: \'{bar_label=~"b.*"}\'\n source_labels: [foo_label, bar_label]\n separator: "_"\n target_label: foobar\n- action: labeldrop\n regex: "foo_.*"\n- target_label: job\n replacement: "my-application-2"',labels:'{__name__="my_metric", bar_label="bar", foo_label="foo", job="my-application", instance="192.168.0.1"}'},Wm=()=>{const[e,t]=je(),{data:n,loading:a,error:i,fetchData:o}=qm(),[l,s]=qh("","config"),[c,u]=qh("","labels"),d=(0,r.useCallback)((()=>{o(l,c),e.set("config",l),e.set("labels",c),t(e)}),[l,c]);return(0,r.useEffect)((()=>{const t=e.get("config")||"",n=e.get("labels")||"";(n||t)&&(o(t,n),s(t),u(n))}),[]),Ct("section",{className:"vm-relabeling",children:[a&&Ct(rl,{}),Ct("div",{className:"vm-relabeling-header vm-block",children:[Ct("div",{className:"vm-relabeling-header-configs",children:Ct(Ha,{type:"textarea",label:"Relabel configs",value:l,autofocus:!0,onChange:e=>{s(e||"")},onEnter:d})}),Ct("div",{className:"vm-relabeling-header__labels",children:Ct(Ha,{type:"textarea",label:"Labels",value:c,onChange:e=>{u(e||"")},onEnter:d})}),Ct("div",{className:"vm-relabeling-header-bottom",children:[Ct("a",{className:"vm-link vm-link_with-icon",target:"_blank",href:"https://docs.victoriametrics.com/relabeling.html",rel:"help noreferrer",children:[Ct(Rn,{}),"Relabeling cookbook"]}),Ct("a",{className:"vm-link vm-link_with-icon",target:"_blank",href:"https://docs.victoriametrics.com/vmagent.html#relabeling",rel:"help noreferrer",children:[Ct(lr,{}),"Documentation"]}),Ct(aa,{variant:"text",onClick:()=>{const{config:n,labels:r}=Ym;s(n),u(r),o(n,r),e.set("config",n),e.set("labels",r),t(e)},children:"Try example"}),Ct(aa,{variant:"contained",onClick:d,startIcon:Ct(Yn,{}),children:"Submit"})]})]}),i&&Ct(Qr,{variant:"error",children:i}),n&&Ct("div",{className:"vm-relabeling-steps vm-block",children:[n.originalLabels&&Ct("div",{className:"vm-relabeling-steps-item",children:Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Original labels:"}),Ct("code",{dangerouslySetInnerHTML:{__html:n.originalLabels}})]})}),n.steps.map(((e,t)=>Ct("div",{className:"vm-relabeling-steps-item",children:[Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Step:"}),t+1]}),Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Relabeling Rule:"}),Ct("code",{children:Ct("pre",{children:e.rule})})]}),Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Input Labels:"}),Ct("code",{children:Ct("pre",{dangerouslySetInnerHTML:{__html:e.inLabels}})})]}),Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Output labels:"}),Ct("code",{children:Ct("pre",{dangerouslySetInnerHTML:{__html:e.outLabels}})})]})]},t))),n.resultingLabels&&Ct("div",{className:"vm-relabeling-steps-item",children:Ct("div",{className:"vm-relabeling-steps-item__row",children:[Ct("span",{children:"Resulting labels:"}),Ct("code",{dangerouslySetInnerHTML:{__html:n.resultingLabels}})]})})]})]})},Km=e=>{let{rows:t,columns:n,defaultOrderBy:a,copyToClipboard:i,paginationOffset:o}=e;const[l,s]=(0,r.useState)(a),[c,u]=(0,r.useState)("desc"),[d,h]=(0,r.useState)(null),m=(0,r.useMemo)((()=>{const{startIndex:e,endIndex:n}=o;return Gh(t,Zh(c,l)).slice(e,n)}),[t,l,c,o]),p=(e,t)=>async()=>{if(d!==t)try{await navigator.clipboard.writeText(String(e)),h(t)}catch(rp){console.error(rp)}};return(0,r.useEffect)((()=>{if(null===d)return;const e=setTimeout((()=>h(null)),2e3);return()=>clearTimeout(e)}),[d]),Ct("table",{className:"vm-table",children:[Ct("thead",{className:"vm-table-header",children:Ct("tr",{className:"vm-table__row vm-table__row_header",children:[n.map((e=>{return Ct("th",{className:"vm-table-cell vm-table-cell_header vm-table-cell_sort",onClick:(t=e.key,()=>{u((e=>"asc"===e&&l===t?"desc":"asc")),s(t)}),children:Ct("div",{className:"vm-table-cell__content",children:[Ct("div",{children:String(e.title||e.key)}),Ct("div",{className:xr()({"vm-table__sort-icon":!0,"vm-table__sort-icon_active":l===e.key,"vm-table__sort-icon_desc":"desc"===c&&l===e.key}),children:Ct(Vn,{})})]})},String(e.key));var t})),i&&Ct("th",{className:"vm-table-cell vm-table-cell_header"})]})}),Ct("tbody",{className:"vm-table-body",children:m.map(((e,t)=>Ct("tr",{className:"vm-table__row",children:[n.map((t=>Ct("td",{className:xr()({"vm-table-cell":!0,["".concat(t.className)]:t.className}),children:e[t.key]||"-"},String(t.key)))),i&&Ct("td",{className:"vm-table-cell vm-table-cell_right",children:e[i]&&Ct("div",{className:"vm-table-cell__content",children:Ct(fa,{title:d===t?"Copied":"Copy row",children:Ct(aa,{variant:"text",color:d===t?"success":"gray",size:"small",startIcon:Ct(d===t?er:ar,{}),onClick:p(e[i],t),ariaLabel:"copy row"})})})})]},t)))})]})},Qm=()=>{const{isMobile:e}=Wr(),{timezone:t}=vn(),{data:n,lastUpdated:a,isLoading:o,error:l,fetchData:s}=(()=>{const{serverUrl:e}=Nt(),[t,n]=(0,r.useState)([]),[a,o]=(0,r.useState)(i()().format(Pt)),[l,s]=(0,r.useState)(!1),[c,u]=(0,r.useState)(),d=(0,r.useMemo)((()=>"".concat(e,"/api/v1/status/active_queries")),[e]),h=async()=>{s(!0);try{const e=await fetch(d),t=await e.json();n(t.data),o(i()().format("HH:mm:ss:SSS")),e.ok?u(void 0):u("".concat(t.errorType,"\r\n").concat(null===t||void 0===t?void 0:t.error))}catch(rp){rp instanceof Error&&u("".concat(rp.name,": ").concat(rp.message))}s(!1)};return(0,r.useEffect)((()=>{h().catch(console.error)}),[d]),{data:t,lastUpdated:a,isLoading:l,error:c,fetchData:h}})(),c=(0,r.useMemo)((()=>n.map((e=>{const t=i()(e.start).tz().format(Lt),n=i()(e.end).tz().format(Lt);return{duration:e.duration,remote_addr:e.remote_addr,query:e.query,args:"".concat(t," to ").concat(n,", step=").concat(qt(e.step)),data:JSON.stringify(e,null,2)}}))),[n,t]),u=(0,r.useMemo)((()=>{if(null===c||void 0===c||!c.length)return[];const e=Object.keys(c[0]),t={remote_addr:"client address"},n=["data"];return e.filter((e=>!n.includes(e))).map((e=>({key:e,title:t[e]||e})))}),[c]);return Ct("div",{className:"vm-active-queries",children:[o&&Ct(rl,{}),Ct("div",{className:"vm-active-queries-header",children:[!c.length&&!l&&Ct(Qr,{variant:"info",children:"There are currently no active queries running"}),l&&Ct(Qr,{variant:"error",children:l}),Ct("div",{className:"vm-active-queries-header-controls",children:[Ct(aa,{variant:"contained",onClick:async()=>{s().catch(console.error)},startIcon:Ct(jn,{}),children:"Update"}),Ct("div",{className:"vm-active-queries-header__update-msg",children:["Last updated: ",a]})]})]}),!!c.length&&Ct("div",{className:xr()({"vm-block":!0,"vm-block_mobile":e}),children:Ct(Km,{rows:c,columns:u,defaultOrderBy:"duration",copyToClipboard:"data",paginationOffset:{startIndex:0,endIndex:1/0}})})]})},Zm=e=>{let{onClose:t,onUpload:n}=e;const{isMobile:a}=Wr(),[i,o]=(0,r.useState)(""),[l,s]=(0,r.useState)(""),c=(0,r.useMemo)((()=>{try{return JSON.parse(i),""}catch(rp){return rp instanceof Error?rp.message:"Unknown error"}}),[i]),u=()=>{s(c),c||(n(i),t())};return Ct("div",{className:xr()({"vm-json-form vm-json-form_one-field":!0,"vm-json-form_mobile vm-json-form_one-field_mobile":a}),children:[Ct(Ha,{value:i,label:"JSON",type:"textarea",error:l,autofocus:!0,onChange:e=>{s(""),o(e)},onEnter:u}),Ct("div",{className:"vm-json-form-footer",children:Ct("div",{className:"vm-json-form-footer__controls vm-json-form-footer__controls_right",children:[Ct(aa,{variant:"outlined",color:"error",onClick:t,children:"Cancel"}),Ct(aa,{variant:"contained",onClick:u,children:"apply"})]})})]})},Gm=e=>{let{data:t,period:n}=e;const{isMobile:a}=Wr(),{tableCompact:i}=Fr(),o=jr(),[l,s]=(0,r.useState)([]),[c,u]=(0,r.useState)(),[d,h]=(0,r.useState)(),[m,p]=(0,r.useState)(!1),[f,v]=(0,r.useState)([]),[g,y]=(0,r.useState)(),_=(0,r.useMemo)((()=>_h(d||[]).map((e=>e.key))),[d]),b=(0,r.useMemo)((()=>{const e=t.some((e=>"matrix"===e.data.resultType));return t.some((e=>"vector"===e.data.resultType))&&e?Tr:e?Tr.filter((e=>"chart"===e.value)):Tr.filter((e=>"chart"!==e.value))}),[t]),[w,k]=(0,r.useState)(b[0].value),{yaxis:x,spanGaps:S}=Ur(),C=Br(),E=e=>{C({type:"SET_YAXIS_LIMITS",payload:e})};return(0,r.useEffect)((()=>{const e="chart"===w?"matrix":"vector",n=t.filter((t=>t.data.resultType===e&&t.trace)).map((e=>{var t,n;return e.trace?new Go(e.trace,(null===e||void 0===e||null===(t=e.vmui)||void 0===t||null===(n=t.params)||void 0===n?void 0:n.query)||"Query"):null}));s(n.filter(Boolean))}),[t,w]),(0,r.useEffect)((()=>{const e=[],n=[],r=[];t.forEach(((t,a)=>{const i=t.data.result.map((e=>{var n,r,i;return{...e,group:Number(null!==(n=null===(r=t.vmui)||void 0===r||null===(i=r.params)||void 0===i?void 0:i.id)&&void 0!==n?n:a)+1}}));var o,l;"matrix"===t.data.resultType?(n.push(...i),e.push((null===(o=t.vmui)||void 0===o||null===(l=o.params)||void 0===l?void 0:l.query)||"Query")):r.push(...i)})),v(e),u(n),h(r)}),[t]),(0,r.useEffect)((()=>{p(!!c&&el(c))}),[c]),Ct("div",{className:xr()({"vm-query-analyzer-view":!0,"vm-query-analyzer-view_mobile":a}),children:[!!l.length&&Ct(ml,{traces:l,onDeleteClick:e=>{s((t=>t.filter((t=>t.idValue!==e.idValue))))}}),Ct("div",{className:xr()({"vm-block":!0,"vm-block_mobile":a}),children:[Ct("div",{className:"vm-custom-panel-body-header",children:[Ct("div",{className:"vm-custom-panel-body-header__tabs",children:Ct(Mr,{activeItem:w,items:b,onChange:e=>{k(e)}})}),Ct("div",{className:"vm-custom-panel-body-header__graph-controls",children:["chart"===w&&Ct(ba,{}),"chart"===w&&Ct(vh,{yaxis:x,setYaxisLimits:E,toggleEnableLimits:()=>{C({type:"TOGGLE_ENABLE_YAXIS_LIMITS"})},spanGaps:{value:S,onChange:e=>{C({type:"SET_SPAN_GAPS",payload:e})}}}),"table"===w&&Ct(Sh,{columns:_,defaultColumns:g,onChangeColumns:y,tableCompact:i,toggleTableCompact:()=>{o({type:"TOGGLE_TABLE_COMPACT"})}})]})]}),c&&n&&"chart"===w&&Ct(hh,{data:c,period:n,customStep:n.step||"1s",query:f,yaxis:x,setYaxisLimits:E,setPeriod:()=>null,height:a?.5*window.innerHeight:500,isHistogram:m,spanGaps:S}),d&&"code"===w&&Ct(yh,{data:d}),d&&"table"===w&&Ct(wh,{data:d,displayColumns:g})]})]})},Jm=e=>{var t,n;let{data:a,period:o}=e;const l=(0,r.useMemo)((()=>a.filter((e=>e.stats&&"matrix"===e.data.resultType))),[a]),s=(0,r.useMemo)((()=>{var e,t;return null===(e=a.find((e=>{var t;return null===e||void 0===e||null===(t=e.vmui)||void 0===t?void 0:t.comment})))||void 0===e||null===(t=e.vmui)||void 0===t?void 0:t.comment}),[a]),c=(0,r.useMemo)((()=>{if(!o)return"";const e=i()(1e3*o.start).tz().format(Lt),t=i()(1e3*o.end).tz().format(Lt);return"".concat(e," - ").concat(t)}),[o]),{value:u,setTrue:d,setFalse:h}=oa(!1);return Ct(xt.FK,{children:[Ct("div",{className:"vm-query-analyzer-info-header",children:[Ct(aa,{startIcon:Ct(Rn,{}),variant:"outlined",color:"warning",onClick:d,children:"Show report info"}),o&&Ct(xt.FK,{children:[Ct("div",{className:"vm-query-analyzer-info-header__period",children:[Ct(or,{})," step: ",o.step]}),Ct("div",{className:"vm-query-analyzer-info-header__period",children:[Ct($n,{})," ",c]})]})]}),u&&Ct(pa,{title:"Report info",onClose:h,children:Ct("div",{className:"vm-query-analyzer-info",children:[s&&Ct("div",{className:"vm-query-analyzer-info-item vm-query-analyzer-info-item_comment",children:[Ct("div",{className:"vm-query-analyzer-info-item__title",children:"Comment:"}),Ct("div",{className:"vm-query-analyzer-info-item__text",children:s})]}),l.map(((e,t)=>{var n;return Ct("div",{className:"vm-query-analyzer-info-item",children:[Ct("div",{className:"vm-query-analyzer-info-item__title",children:l.length>1?"Query ".concat(t+1,":"):"Stats:"}),Ct("div",{className:"vm-query-analyzer-info-item__text",children:[Object.entries(e.stats||{}).map((e=>{let[t,n]=e;return Ct("div",{children:[t,": ",null!==n&&void 0!==n?n:"-"]},t)})),"isPartial: ",String(null!==(n=e.isPartial)&&void 0!==n?n:"-")]})]},t)})),Ct("div",{className:"vm-query-analyzer-info-type",children:null!==(t=l[0])&&void 0!==t&&null!==(n=t.vmui)&&void 0!==n&&n.params?"The report was created using vmui":"The report was created manually"})]})})]})},Xm=()=>{const[e,t]=(0,r.useState)([]),[n,a]=(0,r.useState)(""),i=(0,r.useMemo)((()=>!!e.length),[e]),{value:o,setTrue:l,setFalse:s}=oa(!1),c=(0,r.useMemo)((()=>{var t,n;if(!e)return;const r=null===(t=e[0])||void 0===t||null===(n=t.vmui)||void 0===n?void 0:n.params,a={start:+((null===r||void 0===r?void 0:r.start)||0),end:+((null===r||void 0===r?void 0:r.end)||0),step:null===r||void 0===r?void 0:r.step,date:""};if(!r){const t=e.filter((e=>"matrix"===e.data.resultType)).map((e=>e.data.result)).flat().map((e=>{var t;return e.values?null===(t=e.values)||void 0===t?void 0:t.map((e=>e[0])):[0]})).flat(),n=Array.from(new Set(t.filter(Boolean))).sort(((e,t)=>e-t));a.start=n[0],a.end=n[n.length-1],a.step=Bt((e=>{const t=e.slice(1).map(((t,n)=>t-e[n])),n={};t.forEach((e=>{const t=e.toString();n[t]=(n[t]||0)+1}));let r=0,a=0;for(const i in n)n[i]>a&&(a=n[i],r=Number(i));return r})(n))}return a.date=Zt(Xt(a.end)),a}),[e]),u=e=>{try{const n=JSON.parse(e),r=Array.isArray(n)?n:[n];(e=>e.every((e=>{if("object"===typeof e&&null!==e){const t=e.data;if("object"===typeof t&&null!==t){const e=t.result,n=t.resultType;return Array.isArray(e)&&"string"===typeof n}}return!1})))(r)?t(r):a("Invalid structure - JSON does not match the expected format")}catch(rp){rp instanceof Error&&a("".concat(rp.name,": ").concat(rp.message))}},d=e=>{e.map((e=>{const t=new FileReader;t.onload=e=>{var t;const n=String(null===(t=e.target)||void 0===t?void 0:t.result);u(n)},t.readAsText(e)}))},h=e=>{a("");const t=Array.from(e.target.files||[]);d(t),e.target.value=""},{files:m,dragging:p}=_m();return(0,r.useEffect)((()=>{d(m)}),[m]),Ct("div",{className:"vm-trace-page",children:[i&&Ct("div",{className:"vm-trace-page-header",children:[Ct("div",{className:"vm-trace-page-header-errors",children:Ct(Jm,{data:e,period:c})}),Ct("div",{children:Ct(bm,{onOpenModal:l,onChange:h})})]}),n&&Ct("div",{className:"vm-trace-page-header-errors-item vm-trace-page-header-errors-item_margin-bottom",children:[Ct(Qr,{variant:"error",children:n}),Ct(aa,{className:"vm-trace-page-header-errors-item__close",startIcon:Ct(On,{}),variant:"text",color:"error",onClick:()=>{a("")}})]}),i&&Ct(Gm,{data:e,period:c}),!i&&Ct("div",{className:"vm-trace-page-preview",children:[Ct("p",{className:"vm-trace-page-preview__text",children:["Please, upload file with JSON response content.","\n","The file must contain query information in JSON format.","\n","Graph will be displayed after file upload.","\n","Attach files by dragging & dropping, selecting or pasting them."]}),Ct(bm,{onOpenModal:l,onChange:h})]}),o&&Ct(pa,{title:"Paste JSON",onClose:s,children:Ct(Zm,{onClose:s,onUpload:u})}),p&&Ct("div",{className:"vm-trace-page__dropzone"})]})},ep=()=>{const[e,t]=(0,r.useState)(!1);return Ct(xt.FK,{children:Ct(Le,{children:Ct(ta,{children:Ct(xt.FK,{children:[Ct(ym,{onLoaded:t}),e&&Ct(ke,{children:Ct(be,{path:"/",element:Ct(Ai,{}),children:[Ct(be,{path:Ye.home,element:Ct(Th,{})}),Ct(be,{path:Ye.metrics,element:Ct(Dm,{})}),Ct(be,{path:Ye.cardinality,element:Ct(lm,{})}),Ct(be,{path:Ye.topQueries,element:Ct(mm,{})}),Ct(be,{path:Ye.trace,element:Ct(wm,{})}),Ct(be,{path:Ye.queryAnalyzer,element:Ct(Xm,{})}),Ct(be,{path:Ye.dashboards,element:Ct(Oh,{})}),Ct(be,{path:Ye.withTemplate,element:Ct(Bm,{})}),Ct(be,{path:Ye.relabel,element:Ct(Wm,{})}),Ct(be,{path:Ye.activeQueries,element:Ct(Qm,{})}),Ct(be,{path:Ye.icons,element:Ct(zm,{})})]})})]})})})})},tp=e=>{e&&n.e(685).then(n.bind(n,685)).then((t=>{let{getCLS:n,getFID:r,getFCP:a,getLCP:i,getTTFB:o}=t;n(e),r(e),a(e),i(e),o(e)}))},np=document.getElementById("root");np&&(0,r.render)(Ct(ep,{}),np),tp()})()})();
\ No newline at end of file
diff --git a/app/vmselect/vmui/static/js/main.202937c2.js.LICENSE.txt b/app/vmselect/vmui/static/js/main.59c17910.js.LICENSE.txt
similarity index 100%
rename from app/vmselect/vmui/static/js/main.202937c2.js.LICENSE.txt
rename to app/vmselect/vmui/static/js/main.59c17910.js.LICENSE.txt
diff --git a/app/vmselect/vmui/static/media/MetricsQL.da86c2db4f0b05e286b0.md b/app/vmselect/vmui/static/media/MetricsQL.df7574389d8f8bbcf0c7.md
similarity index 91%
rename from app/vmselect/vmui/static/media/MetricsQL.da86c2db4f0b05e286b0.md
rename to app/vmselect/vmui/static/media/MetricsQL.df7574389d8f8bbcf0c7.md
index 7f3ccc498..fec10e5dc 100644
--- a/app/vmselect/vmui/static/media/MetricsQL.da86c2db4f0b05e286b0.md
+++ b/app/vmselect/vmui/static/media/MetricsQL.df7574389d8f8bbcf0c7.md
@@ -79,6 +79,8 @@ The list of MetricsQL features on top of PromQL:
* [Series selectors](https://docs.victoriametrics.com/keyconcepts/#filtering) accept multiple `or` filters. For example, `{env="prod",job="a" or env="dev",job="b"}`
selects series with `{env="prod",job="a"}` or `{env="dev",job="b"}` labels.
See [these docs](https://docs.victoriametrics.com/keyconcepts/#filtering-by-multiple-or-filters) for details.
+* Support for matching against multiple numeric constants via `q == (C1, ..., CN)` and `q != (C1, ..., CN)` syntax. For example, `status_code == (300, 301, 304)`
+ returns `status_code` metrics with one of `300`, `301` or `304` values.
* Support for `group_left(*)` and `group_right(*)` for copying all the labels from time series on the `one` side
of [many-to-one operations](https://prometheus.io/docs/prometheus/latest/querying/operators/#many-to-one-and-one-to-many-vector-matches).
The copied label names may clash with the existing label names, so MetricsQL provides an ability to add prefix to the copied metric names
@@ -152,9 +154,9 @@ MetricsQL provides the following functions:
### Rollup functions
-**Rollup functions** (aka range functions or window functions) calculate rollups over **raw samples**
+**Rollup functions** (aka range functions or window functions) calculate rollups over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window for the [selected time series](https://docs.victoriametrics.com/keyconcepts/#filtering).
-For example, `avg_over_time(temperature[24h])` calculates the average temperature over raw samples for the last 24 hours.
+For example, `avg_over_time(temperature[24h])` calculates the average temperature over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) for the last 24 hours.
Additional details:
@@ -184,7 +186,7 @@ The list of supported rollup functions:
#### absent_over_time
`absent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1
-if the given lookbehind window `d` doesn't contain raw samples. Otherwise, it returns an empty result.
+if the given lookbehind window `d` doesn't contain [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples). Otherwise, it returns an empty result.
This function is supported by PromQL.
@@ -193,7 +195,7 @@ See also [present_over_time](#present_over_time).
#### aggr_over_time
`aggr_over_time(("rollup_func1", "rollup_func2", ...), series_selector[d])` is a [rollup function](#rollup-functions),
-which calculates all the listed `rollup_func*` for raw samples on the given lookbehind window `d`.
+which calculates all the listed `rollup_func*` for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`.
The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -203,7 +205,7 @@ would calculate [min_over_time](#min_over_time), [max_over_time](#max_over_time)
#### ascent_over_time
`ascent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
-ascent of raw sample values on the given lookbehind window `d`. The calculations are performed individually
+ascent of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples) values on the given lookbehind window `d`. The calculations are performed individually
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is useful for tracking height gains in GPS tracking. Metric names are stripped from the resulting rollups.
@@ -215,7 +217,7 @@ See also [descent_over_time](#descent_over_time).
#### avg_over_time
`avg_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average value
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -225,7 +227,7 @@ See also [median_over_time](#median_over_time).
#### changes
`changes(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of times
-the raw samples changed on the given lookbehind window `d` per each time series returned
+the [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) changed on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Unlike `changes()` in Prometheus it takes into account the change from the last sample before the given lookbehind window `d`.
@@ -240,7 +242,7 @@ See also [changes_prometheus](#changes_prometheus).
#### changes_prometheus
`changes_prometheus(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of times
-the raw samples changed on the given lookbehind window `d` per each time series returned
+the [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) changed on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
It doesn't take into account the change from the last sample before the given lookbehind window `d` in the same way as Prometheus does.
@@ -254,7 +256,7 @@ See also [changes](#changes).
#### count_eq_over_time
-`count_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are equal to `eq`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -264,7 +266,7 @@ See also [count_over_time](#count_over_time), [share_eq_over_time](#share_eq_ove
#### count_gt_over_time
-`count_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are bigger than `gt`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -274,7 +276,7 @@ See also [count_over_time](#count_over_time) and [share_gt_over_time](#share_gt_
#### count_le_over_time
-`count_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which don't exceed `le`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -284,7 +286,7 @@ See also [count_over_time](#count_over_time) and [share_le_over_time](#share_le_
#### count_ne_over_time
-`count_ne_over_time(series_selector[d], ne)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_ne_over_time(series_selector[d], ne)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which aren't equal to `ne`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -294,7 +296,7 @@ See also [count_over_time](#count_over_time).
#### count_over_time
-`count_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -305,7 +307,7 @@ See also [count_le_over_time](#count_le_over_time), [count_gt_over_time](#count_
#### count_values_over_time
-`count_values_over_time("label", series_selector[d])` is a [rollup function](#rollup-functions), which counts the number of raw samples
+`count_values_over_time("label", series_selector[d])` is a [rollup function](#rollup-functions), which counts the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the same value over the given lookbehind window and stores the counts in a time series with an additional `label`, which contains each initial value.
The results are calculated independently per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -315,8 +317,8 @@ See also [count_eq_over_time](#count_eq_over_time), [count_values](#count_values
#### decreases_over_time
-`decreases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw sample value decreases
-over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`decreases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value decreases over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -324,8 +326,8 @@ See also [increases_over_time](#increases_over_time).
#### default_rollup
-`default_rollup(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last raw sample value on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`default_rollup(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
If the lookbehind window is skipped in square brackets, then it is automatically calculated as `max(step, scrape_interval)`, where `step` is the query arg value
passed to [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query) or [/api/v1/query](https://docs.victoriametrics.com/keyconcepts/#instant-query),
@@ -375,7 +377,7 @@ See also [deriv_fast](#deriv_fast) and [ideriv](#ideriv).
#### deriv_fast
`deriv_fast(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second derivative
-using the first and the last raw samples on the given lookbehind window `d` per each time series returned
+using the first and the last [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -384,8 +386,8 @@ See also [deriv](#deriv) and [ideriv](#ideriv).
#### descent_over_time
-`descent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates descent of raw sample values
-on the given lookbehind window `d`. The calculations are performed individually per each time series returned
+`descent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates descent of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d`. The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is useful for tracking height loss in GPS tracking.
@@ -396,8 +398,8 @@ See also [ascent_over_time](#ascent_over_time).
#### distinct_over_time
-`distinct_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number of distinct raw sample values
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`distinct_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number of unique [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -416,15 +418,15 @@ See also [lifetime](#lifetime) and [lag](#lag).
#### first_over_time
-`first_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the first raw sample value
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`first_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the first [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
See also [last_over_time](#last_over_time) and [tfirst_over_time](#tfirst_over_time).
#### geomean_over_time
`geomean_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [geometric mean](https://en.wikipedia.org/wiki/Geometric_mean)
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -432,8 +434,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### histogram_over_time
`histogram_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
-[VictoriaMetrics histogram](https://godoc.org/github.com/VictoriaMetrics/metrics#Histogram) over raw samples on the given lookbehind window `d`.
-It is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+[VictoriaMetrics histogram](https://godoc.org/github.com/VictoriaMetrics/metrics#Histogram) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+on the given lookbehind window `d`. It is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The resulting histograms are useful to pass to [histogram_quantile](#histogram_quantile) for calculating quantiles
over multiple [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
For example, the following query calculates median temperature by country over the last 24 hours:
@@ -457,7 +459,7 @@ See also [hoeffding_bound_lower](#hoeffding_bound_lower).
#### holt_winters
`holt_winters(series_selector[d], sf, tf)` is a [rollup function](#rollup-functions), which calculates Holt-Winters value
-(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for raw samples
+(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
over the given lookbehind window `d` using the given smoothing factor `sf` and the given trend factor `tf`.
Both `sf` and `tf` must be in the range `[0...1]`. It is expected that the [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
returns time series of [gauge type](https://docs.victoriametrics.com/keyconcepts/#gauge).
@@ -468,7 +470,7 @@ See also [range_linear_regression](#range_linear_regression).
#### idelta
-`idelta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the difference between the last two raw samples
+`idelta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the difference between the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -479,7 +481,8 @@ See also [delta](#delta).
#### ideriv
-`ideriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the per-second derivative based on the last two raw samples
+`ideriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the per-second derivative based
+on the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
over the given lookbehind window `d`. The derivative is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -522,8 +525,8 @@ while [increase](#increase) ignores the first value in a series if it is too big
#### increases_over_time
-`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw sample value increases
-over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value increases over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -531,14 +534,15 @@ See also [decreases_over_time](#decreases_over_time).
#### integrate
-`integrate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the integral over raw samples on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`integrate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the integral over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
#### irate
-`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over the last two raw samples
+`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over
+the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
@@ -560,8 +564,8 @@ See also [lifetime](#lifetime) and [duration_over_time](#duration_over_time).
#### last_over_time
-`last_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last raw sample value on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`last_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -579,13 +583,14 @@ See also [duration_over_time](#duration_over_time) and [lag](#lag).
#### mad_over_time
`mad_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [median absolute deviation](https://en.wikipedia.org/wiki/Median_absolute_deviation)
-over raw samples on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
+from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outlier_iqr_over_time).
#### max_over_time
-`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over raw samples
+`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -594,7 +599,7 @@ See also [tmax_over_time](#tmax_over_time).
#### median_over_time
-`median_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates median value over raw samples
+`median_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates median value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -602,7 +607,7 @@ See also [avg_over_time](#avg_over_time).
#### min_over_time
-`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over raw samples
+`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -612,15 +617,16 @@ See also [tmin_over_time](#tmin_over_time).
#### mode_over_time
`mode_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [mode](https://en.wikipedia.org/wiki/Mode_(statistics))
-for raw samples on the given lookbehind window `d`. It is calculated individually per each time series returned
-from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that raw sample values are discrete.
+for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`. It is calculated individually per each time series returned
+from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values are discrete.
#### outlier_iqr_over_time
`outlier_iqr_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last sample on the given lookbehind window `d`
if its value is either smaller than the `q25-1.5*iqr` or bigger than `q75+1.5*iqr` where:
-- `iqr` is an [Interquartile range](https://en.wikipedia.org/wiki/Interquartile_range) over raw samples on the lookbehind window `d`
-- `q25` and `q75` are 25th and 75th [percentiles](https://en.wikipedia.org/wiki/Percentile) over raw samples on the lookbehind window `d`.
+- `iqr` is an [Interquartile range](https://en.wikipedia.org/wiki/Interquartile_range) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the lookbehind window `d`
+- `q25` and `q75` are 25th and 75th [percentiles](https://en.wikipedia.org/wiki/Percentile) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the lookbehind window `d`.
The `outlier_iqr_over_time()` is useful for detecting anomalies in gauge values based on the previous history of values.
For example, `outlier_iqr_over_time(memory_usage_bytes[1h])` triggers when `memory_usage_bytes` suddenly goes outside the usual value range for the last hour.
@@ -630,8 +636,8 @@ See also [outliers_iqr](#outliers_iqr).
#### predict_linear
`predict_linear(series_selector[d], t)` is a [rollup function](#rollup-functions), which calculates the value `t` seconds in the future using
-linear interpolation over raw samples on the given lookbehind window `d`. The predicted value is calculated individually per each time series
-returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+linear interpolation over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`.
+The predicted value is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -639,7 +645,7 @@ See also [range_linear_regression](#range_linear_regression).
#### present_over_time
-`present_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1 if there is at least a single raw sample
+`present_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1 if there is at least a single [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`. Otherwise, an empty result is returned.
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -648,7 +654,7 @@ This function is supported by PromQL.
#### quantile_over_time
-`quantile_over_time(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi`-quantile over raw samples
+`quantile_over_time(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi`-quantile over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The `phi` value must be in the range `[0...1]`.
@@ -659,7 +665,7 @@ See also [quantiles_over_time](#quantiles_over_time).
#### quantiles_over_time
`quantiles_over_time("phiLabel", phi1, ..., phiN, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi*`-quantiles
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The function returns individual series per each `phi*` with `{phiLabel="phi*"}` label. `phi*` values must be in the range `[0...1]`.
@@ -667,7 +673,7 @@ See also [quantile_over_time](#quantile_over_time).
#### range_over_time
-`range_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates value range over raw samples
+`range_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates value range over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
E.g. it calculates `max_over_time(series_selector[d]) - min_over_time(series_selector[d])`.
@@ -692,7 +698,7 @@ See also [irate](#irate) and [rollup_rate](#rollup_rate).
#### rate_over_sum
-`rate_over_sum(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second rate over the sum of raw samples
+`rate_over_sum(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second rate over the sum of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`. The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -711,7 +717,7 @@ This function is supported by PromQL.
#### rollup
-`rollup(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `min`, `max` and `avg` values for raw samples
+`rollup(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `min`, `max` and `avg` values for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
These values are calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -721,7 +727,8 @@ See also [label_match](#label_match).
#### rollup_candlestick
`rollup_candlestick(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `open`, `high`, `low` and `close` values (aka OHLC)
-over raw samples on the given lookbehind window `d` and returns them in time series with `rollup="open"`, `rollup="high"`, `rollup="low"` and `rollup="close"` additional labels.
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns them in time series
+with `rollup="open"`, `rollup="high"`, `rollup="low"` and `rollup="close"` additional labels.
The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). This function is useful for financial applications.
@@ -730,7 +737,7 @@ See also [label_match](#label_match).
#### rollup_delta
-`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent raw samples
+`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated differences
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -745,8 +752,8 @@ See also [rollup_increase](#rollup_increase).
#### rollup_deriv
`rollup_deriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second derivatives
-for adjacent raw samples on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second derivatives
-and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
+for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns `min`, `max` and `avg` values
+for the calculated per-second derivatives and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
@@ -756,7 +763,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_increase
-`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent raw samples
+`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated increases
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -768,7 +775,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_rate
-`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates for adjacent raw samples
+`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates
+for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second change rates
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
@@ -785,7 +793,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_scrape_interval
`rollup_scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the interval in seconds between
-adjacent raw samples on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated interval
+adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated interval
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -796,7 +804,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### scrape_interval
-`scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average interval in seconds between raw samples
+`scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average interval in seconds
+between [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -805,7 +814,8 @@ See also [rollup_scrape_interval](#rollup_scrape_interval).
#### share_gt_over_time
-`share_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are bigger than `gt`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -817,7 +827,8 @@ See also [share_le_over_time](#share_le_over_time) and [count_gt_over_time](#cou
#### share_le_over_time
-`share_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are smaller or equal to `le`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -830,7 +841,8 @@ See also [share_gt_over_time](#share_gt_over_time) and [count_le_over_time](#cou
#### share_eq_over_time
-`share_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are equal to `eq`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -848,7 +860,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### stddev_over_time
-`stddev_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard deviation over raw samples
+`stddev_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard deviation over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -859,7 +871,7 @@ See also [stdvar_over_time](#stdvar_over_time).
#### stdvar_over_time
-`stdvar_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard variance over raw samples
+`stdvar_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard variance over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -870,8 +882,8 @@ See also [stddev_over_time](#stddev_over_time).
#### sum_eq_over_time
-`sum_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values equal to `eq`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values equal to `eq` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -879,8 +891,8 @@ See also [sum_over_time](#sum_over_time) and [count_eq_over_time](#count_eq_over
#### sum_gt_over_time
-`sum_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values bigger than `gt`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values bigger than `gt` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -888,8 +900,8 @@ See also [sum_over_time](#sum_over_time) and [count_gt_over_time](#count_gt_over
#### sum_le_over_time
-`sum_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values smaller or equal to `le`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values smaller or equal to `le` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -897,7 +909,7 @@ See also [sum_over_time](#sum_over_time) and [count_le_over_time](#count_le_over
#### sum_over_time
-`sum_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of raw sample values
+`sum_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples) values
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -906,14 +918,15 @@ This function is supported by PromQL.
#### sum2_over_time
-`sum2_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of squares for raw sample values
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum2_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of squares for [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
#### timestamp
-`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the last raw sample
+`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -924,7 +937,8 @@ See also [time](#time) and [now](#now).
#### timestamp_with_name
-`timestamp_with_name(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the last raw sample
+`timestamp_with_name(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are preserved in the resulting rollups.
@@ -933,7 +947,8 @@ See also [timestamp](#timestamp) and [keep_metric_names](#keep_metric_names) mod
#### tfirst_over_time
-`tfirst_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the first raw sample
+`tfirst_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the first [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -957,7 +972,8 @@ See also [tlast_change_over_time](#tlast_change_over_time).
#### tmax_over_time
-`tmax_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the raw sample
+`tmax_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the maximum value on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -967,7 +983,8 @@ See also [max_over_time](#max_over_time).
#### tmin_over_time
-`tmin_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the raw sample
+`tmin_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the minimum value on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -978,7 +995,7 @@ See also [min_over_time](#min_over_time).
#### zscore_over_time
`zscore_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns [z-score](https://en.wikipedia.org/wiki/Standard_score)
-for raw samples on the given lookbehind window `d`. It is calculated independently per each time series returned
+for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -2212,6 +2229,7 @@ Any [rollup function](#rollup-functions) for something other than [series select
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
since it contains [default_rollup](#default_rollup) nested into [delta](#delta).
+This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
VictoriaMetrics performs subqueries in the following way:
@@ -2244,4 +2262,5 @@ VictoriaMetrics performs the following implicit conversions for incoming queries
For example, `avg_over_time(rate(http_requests_total[5m])[1h])` is automatically converted to `avg_over_time(rate(http_requests_total[5m])[1h:1i])`.
* If something other than [series selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
is passed to [rollup function](#rollup-functions), then a [subquery](#subqueries) with `1i` lookbehind window and `1i` step is automatically formed.
- For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
diff --git a/app/vmui/Dockerfile-web b/app/vmui/Dockerfile-web
index f54841860..1ccad9a66 100644
--- a/app/vmui/Dockerfile-web
+++ b/app/vmui/Dockerfile-web
@@ -1,4 +1,4 @@
-FROM golang:1.22.2 as build-web-stage
+FROM golang:1.22.3 as build-web-stage
COPY build /build
WORKDIR /build
diff --git a/app/vmui/packages/vmui/src/assets/MetricsQL.md b/app/vmui/packages/vmui/src/assets/MetricsQL.md
index 7f3ccc498..fec10e5dc 100644
--- a/app/vmui/packages/vmui/src/assets/MetricsQL.md
+++ b/app/vmui/packages/vmui/src/assets/MetricsQL.md
@@ -79,6 +79,8 @@ The list of MetricsQL features on top of PromQL:
* [Series selectors](https://docs.victoriametrics.com/keyconcepts/#filtering) accept multiple `or` filters. For example, `{env="prod",job="a" or env="dev",job="b"}`
selects series with `{env="prod",job="a"}` or `{env="dev",job="b"}` labels.
See [these docs](https://docs.victoriametrics.com/keyconcepts/#filtering-by-multiple-or-filters) for details.
+* Support for matching against multiple numeric constants via `q == (C1, ..., CN)` and `q != (C1, ..., CN)` syntax. For example, `status_code == (300, 301, 304)`
+ returns `status_code` metrics with one of `300`, `301` or `304` values.
* Support for `group_left(*)` and `group_right(*)` for copying all the labels from time series on the `one` side
of [many-to-one operations](https://prometheus.io/docs/prometheus/latest/querying/operators/#many-to-one-and-one-to-many-vector-matches).
The copied label names may clash with the existing label names, so MetricsQL provides an ability to add prefix to the copied metric names
@@ -152,9 +154,9 @@ MetricsQL provides the following functions:
### Rollup functions
-**Rollup functions** (aka range functions or window functions) calculate rollups over **raw samples**
+**Rollup functions** (aka range functions or window functions) calculate rollups over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window for the [selected time series](https://docs.victoriametrics.com/keyconcepts/#filtering).
-For example, `avg_over_time(temperature[24h])` calculates the average temperature over raw samples for the last 24 hours.
+For example, `avg_over_time(temperature[24h])` calculates the average temperature over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) for the last 24 hours.
Additional details:
@@ -184,7 +186,7 @@ The list of supported rollup functions:
#### absent_over_time
`absent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1
-if the given lookbehind window `d` doesn't contain raw samples. Otherwise, it returns an empty result.
+if the given lookbehind window `d` doesn't contain [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples). Otherwise, it returns an empty result.
This function is supported by PromQL.
@@ -193,7 +195,7 @@ See also [present_over_time](#present_over_time).
#### aggr_over_time
`aggr_over_time(("rollup_func1", "rollup_func2", ...), series_selector[d])` is a [rollup function](#rollup-functions),
-which calculates all the listed `rollup_func*` for raw samples on the given lookbehind window `d`.
+which calculates all the listed `rollup_func*` for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`.
The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -203,7 +205,7 @@ would calculate [min_over_time](#min_over_time), [max_over_time](#max_over_time)
#### ascent_over_time
`ascent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
-ascent of raw sample values on the given lookbehind window `d`. The calculations are performed individually
+ascent of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples) values on the given lookbehind window `d`. The calculations are performed individually
per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is useful for tracking height gains in GPS tracking. Metric names are stripped from the resulting rollups.
@@ -215,7 +217,7 @@ See also [descent_over_time](#descent_over_time).
#### avg_over_time
`avg_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average value
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -225,7 +227,7 @@ See also [median_over_time](#median_over_time).
#### changes
`changes(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of times
-the raw samples changed on the given lookbehind window `d` per each time series returned
+the [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) changed on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Unlike `changes()` in Prometheus it takes into account the change from the last sample before the given lookbehind window `d`.
@@ -240,7 +242,7 @@ See also [changes_prometheus](#changes_prometheus).
#### changes_prometheus
`changes_prometheus(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of times
-the raw samples changed on the given lookbehind window `d` per each time series returned
+the [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) changed on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
It doesn't take into account the change from the last sample before the given lookbehind window `d` in the same way as Prometheus does.
@@ -254,7 +256,7 @@ See also [changes](#changes).
#### count_eq_over_time
-`count_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are equal to `eq`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -264,7 +266,7 @@ See also [count_over_time](#count_over_time), [share_eq_over_time](#share_eq_ove
#### count_gt_over_time
-`count_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are bigger than `gt`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -274,7 +276,7 @@ See also [count_over_time](#count_over_time) and [share_gt_over_time](#share_gt_
#### count_le_over_time
-`count_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which don't exceed `le`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -284,7 +286,7 @@ See also [count_over_time](#count_over_time) and [share_le_over_time](#share_le_
#### count_ne_over_time
-`count_ne_over_time(series_selector[d], ne)` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_ne_over_time(series_selector[d], ne)` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which aren't equal to `ne`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -294,7 +296,7 @@ See also [count_over_time](#count_over_time).
#### count_over_time
-`count_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw samples
+`count_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -305,7 +307,7 @@ See also [count_le_over_time](#count_le_over_time), [count_gt_over_time](#count_
#### count_values_over_time
-`count_values_over_time("label", series_selector[d])` is a [rollup function](#rollup-functions), which counts the number of raw samples
+`count_values_over_time("label", series_selector[d])` is a [rollup function](#rollup-functions), which counts the number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the same value over the given lookbehind window and stores the counts in a time series with an additional `label`, which contains each initial value.
The results are calculated independently per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -315,8 +317,8 @@ See also [count_eq_over_time](#count_eq_over_time), [count_values](#count_values
#### decreases_over_time
-`decreases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw sample value decreases
-over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`decreases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value decreases over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -324,8 +326,8 @@ See also [increases_over_time](#increases_over_time).
#### default_rollup
-`default_rollup(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last raw sample value on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`default_rollup(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
If the lookbehind window is skipped in square brackets, then it is automatically calculated as `max(step, scrape_interval)`, where `step` is the query arg value
passed to [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query) or [/api/v1/query](https://docs.victoriametrics.com/keyconcepts/#instant-query),
@@ -375,7 +377,7 @@ See also [deriv_fast](#deriv_fast) and [ideriv](#ideriv).
#### deriv_fast
`deriv_fast(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second derivative
-using the first and the last raw samples on the given lookbehind window `d` per each time series returned
+using the first and the last [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -384,8 +386,8 @@ See also [deriv](#deriv) and [ideriv](#ideriv).
#### descent_over_time
-`descent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates descent of raw sample values
-on the given lookbehind window `d`. The calculations are performed individually per each time series returned
+`descent_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates descent of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d`. The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is useful for tracking height loss in GPS tracking.
@@ -396,8 +398,8 @@ See also [ascent_over_time](#ascent_over_time).
#### distinct_over_time
-`distinct_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number of distinct raw sample values
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`distinct_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the number of unique [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -416,15 +418,15 @@ See also [lifetime](#lifetime) and [lag](#lag).
#### first_over_time
-`first_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the first raw sample value
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`first_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the first [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
See also [last_over_time](#last_over_time) and [tfirst_over_time](#tfirst_over_time).
#### geomean_over_time
`geomean_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [geometric mean](https://en.wikipedia.org/wiki/Geometric_mean)
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -432,8 +434,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### histogram_over_time
`histogram_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates
-[VictoriaMetrics histogram](https://godoc.org/github.com/VictoriaMetrics/metrics#Histogram) over raw samples on the given lookbehind window `d`.
-It is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+[VictoriaMetrics histogram](https://godoc.org/github.com/VictoriaMetrics/metrics#Histogram) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+on the given lookbehind window `d`. It is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The resulting histograms are useful to pass to [histogram_quantile](#histogram_quantile) for calculating quantiles
over multiple [gauges](https://docs.victoriametrics.com/keyconcepts/#gauge).
For example, the following query calculates median temperature by country over the last 24 hours:
@@ -457,7 +459,7 @@ See also [hoeffding_bound_lower](#hoeffding_bound_lower).
#### holt_winters
`holt_winters(series_selector[d], sf, tf)` is a [rollup function](#rollup-functions), which calculates Holt-Winters value
-(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for raw samples
+(aka [double exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing#Double_exponential_smoothing)) for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
over the given lookbehind window `d` using the given smoothing factor `sf` and the given trend factor `tf`.
Both `sf` and `tf` must be in the range `[0...1]`. It is expected that the [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
returns time series of [gauge type](https://docs.victoriametrics.com/keyconcepts/#gauge).
@@ -468,7 +470,7 @@ See also [range_linear_regression](#range_linear_regression).
#### idelta
-`idelta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the difference between the last two raw samples
+`idelta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the difference between the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -479,7 +481,8 @@ See also [delta](#delta).
#### ideriv
-`ideriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the per-second derivative based on the last two raw samples
+`ideriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the per-second derivative based
+on the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
over the given lookbehind window `d`. The derivative is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -522,8 +525,8 @@ while [increase](#increase) ignores the first value in a series if it is too big
#### increases_over_time
-`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of raw sample value increases
-over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`increases_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the number of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value increases over the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -531,14 +534,15 @@ See also [decreases_over_time](#decreases_over_time).
#### integrate
-`integrate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the integral over raw samples on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`integrate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the integral over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
#### irate
-`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over the last two raw samples
+`irate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the "instant" per-second increase rate over
+the last two [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
It is expected that the `series_selector` returns time series of [counter type](https://docs.victoriametrics.com/keyconcepts/#counter).
@@ -560,8 +564,8 @@ See also [lifetime](#lifetime) and [duration_over_time](#duration_over_time).
#### last_over_time
-`last_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last raw sample value on the given lookbehind window `d`
-per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`last_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+value on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -579,13 +583,14 @@ See also [duration_over_time](#duration_over_time) and [lag](#lag).
#### mad_over_time
`mad_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [median absolute deviation](https://en.wikipedia.org/wiki/Median_absolute_deviation)
-over raw samples on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
+from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
See also [mad](#mad), [range_mad](#range_mad) and [outlier_iqr_over_time](#outlier_iqr_over_time).
#### max_over_time
-`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over raw samples
+`max_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the maximum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -594,7 +599,7 @@ See also [tmax_over_time](#tmax_over_time).
#### median_over_time
-`median_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates median value over raw samples
+`median_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates median value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -602,7 +607,7 @@ See also [avg_over_time](#avg_over_time).
#### min_over_time
-`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over raw samples
+`min_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the minimum value over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -612,15 +617,16 @@ See also [tmin_over_time](#tmin_over_time).
#### mode_over_time
`mode_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates [mode](https://en.wikipedia.org/wiki/Mode_(statistics))
-for raw samples on the given lookbehind window `d`. It is calculated individually per each time series returned
-from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that raw sample values are discrete.
+for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`. It is calculated individually per each time series returned
+from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). It is expected that [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values are discrete.
#### outlier_iqr_over_time
`outlier_iqr_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the last sample on the given lookbehind window `d`
if its value is either smaller than the `q25-1.5*iqr` or bigger than `q75+1.5*iqr` where:
-- `iqr` is an [Interquartile range](https://en.wikipedia.org/wiki/Interquartile_range) over raw samples on the lookbehind window `d`
-- `q25` and `q75` are 25th and 75th [percentiles](https://en.wikipedia.org/wiki/Percentile) over raw samples on the lookbehind window `d`.
+- `iqr` is an [Interquartile range](https://en.wikipedia.org/wiki/Interquartile_range) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the lookbehind window `d`
+- `q25` and `q75` are 25th and 75th [percentiles](https://en.wikipedia.org/wiki/Percentile) over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the lookbehind window `d`.
The `outlier_iqr_over_time()` is useful for detecting anomalies in gauge values based on the previous history of values.
For example, `outlier_iqr_over_time(memory_usage_bytes[1h])` triggers when `memory_usage_bytes` suddenly goes outside the usual value range for the last hour.
@@ -630,8 +636,8 @@ See also [outliers_iqr](#outliers_iqr).
#### predict_linear
`predict_linear(series_selector[d], t)` is a [rollup function](#rollup-functions), which calculates the value `t` seconds in the future using
-linear interpolation over raw samples on the given lookbehind window `d`. The predicted value is calculated individually per each time series
-returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+linear interpolation over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`.
+The predicted value is calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
This function is supported by PromQL.
@@ -639,7 +645,7 @@ See also [range_linear_regression](#range_linear_regression).
#### present_over_time
-`present_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1 if there is at least a single raw sample
+`present_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns 1 if there is at least a single [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`. Otherwise, an empty result is returned.
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -648,7 +654,7 @@ This function is supported by PromQL.
#### quantile_over_time
-`quantile_over_time(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi`-quantile over raw samples
+`quantile_over_time(phi, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi`-quantile over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The `phi` value must be in the range `[0...1]`.
@@ -659,7 +665,7 @@ See also [quantiles_over_time](#quantiles_over_time).
#### quantiles_over_time
`quantiles_over_time("phiLabel", phi1, ..., phiN, series_selector[d])` is a [rollup function](#rollup-functions), which calculates `phi*`-quantiles
-over raw samples on the given lookbehind window `d` per each time series returned
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
The function returns individual series per each `phi*` with `{phiLabel="phi*"}` label. `phi*` values must be in the range `[0...1]`.
@@ -667,7 +673,7 @@ See also [quantile_over_time](#quantile_over_time).
#### range_over_time
-`range_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates value range over raw samples
+`range_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates value range over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
E.g. it calculates `max_over_time(series_selector[d]) - min_over_time(series_selector[d])`.
@@ -692,7 +698,7 @@ See also [irate](#irate) and [rollup_rate](#rollup_rate).
#### rate_over_sum
-`rate_over_sum(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second rate over the sum of raw samples
+`rate_over_sum(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second rate over the sum of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`. The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -711,7 +717,7 @@ This function is supported by PromQL.
#### rollup
-`rollup(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `min`, `max` and `avg` values for raw samples
+`rollup(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `min`, `max` and `avg` values for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
These values are calculated individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -721,7 +727,8 @@ See also [label_match](#label_match).
#### rollup_candlestick
`rollup_candlestick(series_selector[d])` is a [rollup function](#rollup-functions), which calculates `open`, `high`, `low` and `close` values (aka OHLC)
-over raw samples on the given lookbehind window `d` and returns them in time series with `rollup="open"`, `rollup="high"`, `rollup="low"` and `rollup="close"` additional labels.
+over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns them in time series
+with `rollup="open"`, `rollup="high"`, `rollup="low"` and `rollup="close"` additional labels.
The calculations are performed individually per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering). This function is useful for financial applications.
@@ -730,7 +737,7 @@ See also [label_match](#label_match).
#### rollup_delta
-`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent raw samples
+`rollup_delta(series_selector[d])` is a [rollup function](#rollup-functions), which calculates differences between adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated differences
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -745,8 +752,8 @@ See also [rollup_increase](#rollup_increase).
#### rollup_deriv
`rollup_deriv(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second derivatives
-for adjacent raw samples on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second derivatives
-and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
+for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns `min`, `max` and `avg` values
+for the calculated per-second derivatives and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Optional 2nd argument `"min"`, `"max"` or `"avg"` can be passed to keep only one calculation result and without adding a label.
@@ -756,7 +763,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_increase
-`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent raw samples
+`rollup_increase(series_selector[d])` is a [rollup function](#rollup-functions), which calculates increases for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated increases
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -768,7 +775,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_rate
-`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates for adjacent raw samples
+`rollup_rate(series_selector[d])` is a [rollup function](#rollup-functions), which calculates per-second change rates
+for adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated per-second change rates
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
@@ -785,7 +793,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### rollup_scrape_interval
`rollup_scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the interval in seconds between
-adjacent raw samples on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated interval
+adjacent [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d` and returns `min`, `max` and `avg` values for the calculated interval
and returns them in time series with `rollup="min"`, `rollup="max"` and `rollup="avg"` additional labels.
The calculations are performed individually per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -796,7 +804,8 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### scrape_interval
-`scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average interval in seconds between raw samples
+`scrape_interval(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the average interval in seconds
+between [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -805,7 +814,8 @@ See also [rollup_scrape_interval](#rollup_scrape_interval).
#### share_gt_over_time
-`share_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are bigger than `gt`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -817,7 +827,8 @@ See also [share_le_over_time](#share_le_over_time) and [count_gt_over_time](#cou
#### share_le_over_time
-`share_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are smaller or equal to `le`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -830,7 +841,8 @@ See also [share_gt_over_time](#share_gt_over_time) and [count_le_over_time](#cou
#### share_eq_over_time
-`share_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`) of raw samples
+`share_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-functions), which returns share (in the range `[0...1]`)
+of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d`, which are equal to `eq`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -848,7 +860,7 @@ Metric names are stripped from the resulting rollups. Add [keep_metric_names](#k
#### stddev_over_time
-`stddev_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard deviation over raw samples
+`stddev_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard deviation over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -859,7 +871,7 @@ See also [stdvar_over_time](#stdvar_over_time).
#### stdvar_over_time
-`stdvar_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard variance over raw samples
+`stdvar_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates standard variance over [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -870,8 +882,8 @@ See also [stddev_over_time](#stddev_over_time).
#### sum_eq_over_time
-`sum_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values equal to `eq`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_eq_over_time(series_selector[d], eq)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values equal to `eq` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -879,8 +891,8 @@ See also [sum_over_time](#sum_over_time) and [count_eq_over_time](#count_eq_over
#### sum_gt_over_time
-`sum_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values bigger than `gt`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_gt_over_time(series_selector[d], gt)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values bigger than `gt` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -888,8 +900,8 @@ See also [sum_over_time](#sum_over_time) and [count_gt_over_time](#count_gt_over
#### sum_le_over_time
-`sum_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-function), which calculates the sum of raw sample values smaller or equal to `le`
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum_le_over_time(series_selector[d], le)` is a [rollup function](#rollup-function), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values smaller or equal to `le` on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -897,7 +909,7 @@ See also [sum_over_time](#sum_over_time) and [count_le_over_time](#count_le_over
#### sum_over_time
-`sum_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of raw sample values
+`sum_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples) values
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -906,14 +918,15 @@ This function is supported by PromQL.
#### sum2_over_time
-`sum2_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of squares for raw sample values
-on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
+`sum2_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which calculates the sum of squares for [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
+values on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
#### timestamp
-`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the last raw sample
+`timestamp(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -924,7 +937,8 @@ See also [time](#time) and [now](#now).
#### timestamp_with_name
-`timestamp_with_name(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the last raw sample
+`timestamp_with_name(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the last [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are preserved in the resulting rollups.
@@ -933,7 +947,8 @@ See also [timestamp](#timestamp) and [keep_metric_names](#keep_metric_names) mod
#### tfirst_over_time
-`tfirst_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the first raw sample
+`tfirst_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the first [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
on the given lookbehind window `d` per each time series returned from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -957,7 +972,8 @@ See also [tlast_change_over_time](#tlast_change_over_time).
#### tmax_over_time
-`tmax_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the raw sample
+`tmax_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the maximum value on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -967,7 +983,8 @@ See also [max_over_time](#max_over_time).
#### tmin_over_time
-`tmin_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision for the raw sample
+`tmin_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns the timestamp in seconds with millisecond precision
+for the [raw sample](https://docs.victoriametrics.com/keyconcepts/#raw-samples)
with the minimum value on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
@@ -978,7 +995,7 @@ See also [min_over_time](#min_over_time).
#### zscore_over_time
`zscore_over_time(series_selector[d])` is a [rollup function](#rollup-functions), which returns [z-score](https://en.wikipedia.org/wiki/Standard_score)
-for raw samples on the given lookbehind window `d`. It is calculated independently per each time series returned
+for [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) on the given lookbehind window `d`. It is calculated independently per each time series returned
from the given [series_selector](https://docs.victoriametrics.com/keyconcepts/#filtering).
Metric names are stripped from the resulting rollups. Add [keep_metric_names](#keep_metric_names) modifier in order to keep metric names.
@@ -2212,6 +2229,7 @@ Any [rollup function](#rollup-functions) for something other than [series select
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
since it contains [default_rollup](#default_rollup) nested into [delta](#delta).
+This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
VictoriaMetrics performs subqueries in the following way:
@@ -2244,4 +2262,5 @@ VictoriaMetrics performs the following implicit conversions for incoming queries
For example, `avg_over_time(rate(http_requests_total[5m])[1h])` is automatically converted to `avg_over_time(rate(http_requests_total[5m])[1h:1i])`.
* If something other than [series selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
is passed to [rollup function](#rollup-functions), then a [subquery](#subqueries) with `1i` lookbehind window and `1i` step is automatically formed.
- For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
diff --git a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx
index a2a2c7a42..2a4290264 100644
--- a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx
+++ b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditor.tsx
@@ -9,6 +9,7 @@ import { partialWarning, seriesFetchedWarning } from "./warningText";
import { AutocompleteOptions } from "../../Main/Autocomplete/Autocomplete";
import useDeviceDetect from "../../../hooks/useDeviceDetect";
import { useQueryState } from "../../../state/query/QueryStateContext";
+import debounce from "lodash.debounce";
export interface QueryEditorProps {
onChange: (query: string) => void;
@@ -40,9 +41,12 @@ const QueryEditor: FC = ({
const { isMobile } = useDeviceDetect();
const [openAutocomplete, setOpenAutocomplete] = useState(false);
- const [caretPosition, setCaretPosition] = useState([0, 0]);
+ const [caretPosition, setCaretPosition] = useState<[number, number]>([0, 0]);
const autocompleteAnchorEl = useRef(null);
+ const [showAutocomplete, setShowAutocomplete] = useState(autocomplete);
+ const debouncedSetShowAutocomplete = useRef(debounce(setShowAutocomplete, 500)).current;
+
const warning = [
{
show: stats?.seriesFetched === "0" && !stats.resultLength,
@@ -58,8 +62,9 @@ const QueryEditor: FC = ({
label = `${label} (${stats.executionTimeMsec || 0}ms)`;
}
- const handleSelect = (val: string) => {
+ const handleSelect = (val: string, caretPosition: number) => {
onChange(val);
+ setCaretPosition([caretPosition, caretPosition]);
};
const handleKeyDown = (e: KeyboardEvent) => {
@@ -100,14 +105,19 @@ const QueryEditor: FC = ({
setOpenAutocomplete(!!val.length);
};
- const handleChangeCaret = (val: number[]) => {
- setCaretPosition(val);
+ const handleChangeCaret = (val: [number, number]) => {
+ setCaretPosition(prev => prev[0] === val[0] && prev[1] === val[1] ? prev : val);
};
useEffect(() => {
setOpenAutocomplete(autocomplete);
}, [autocompleteQuick]);
+ useEffect(() => {
+ setShowAutocomplete(false);
+ debouncedSetShowAutocomplete(true);
+ }, [caretPosition]);
+
return (
= ({
onChangeCaret={handleChangeCaret}
disabled={disabled}
inputmode={"search"}
+ caretPosition={caretPosition}
/>
- {autocomplete && (
+ {showAutocomplete && autocomplete && (
diff --git a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditorAutocomplete.tsx b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditorAutocomplete.tsx
index edbd85d35..c19934895 100644
--- a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditorAutocomplete.tsx
+++ b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/QueryEditorAutocomplete.tsx
@@ -1,7 +1,6 @@
-import React, { FC, Ref, useState, useEffect, useMemo } from "preact/compat";
+import React, { FC, Ref, useState, useEffect, useMemo, useCallback } from "preact/compat";
import Autocomplete, { AutocompleteOptions } from "../../Main/Autocomplete/Autocomplete";
import { useFetchQueryOptions } from "../../../hooks/useFetchQueryOptions";
-import { getTextWidth } from "../../../utils/uplot";
import { escapeRegexp, hasUnclosedQuotes } from "../../../utils/regexp";
import useGetMetricsQL from "../../../hooks/useGetMetricsQL";
import { QueryContextType } from "../../../types";
@@ -10,8 +9,9 @@ import { AUTOCOMPLETE_LIMITS } from "../../../constants/queryAutocomplete";
interface QueryEditorAutocompleteProps {
value: string;
anchorEl: Ref
;
- caretPosition: number[];
- onSelect: (val: string) => void;
+ caretPosition: [number, number]; // [start, end]
+ hasHelperText: boolean;
+ onSelect: (val: string, caretPosition: number) => void;
onFoundOptions: (val: AutocompleteOptions[]) => void;
}
@@ -19,16 +19,24 @@ const QueryEditorAutocomplete: FC = ({
value,
anchorEl,
caretPosition,
+ hasHelperText,
onSelect,
onFoundOptions
}) => {
- const [leftOffset, setLeftOffset] = useState(0);
+ const [offsetPos, setOffsetPos] = useState({ top: 0, left: 0 });
const metricsqlFunctions = useGetMetricsQL();
+ const values = useMemo(() => {
+ if (caretPosition[0] !== caretPosition[1]) return { beforeCursor: value, afterCursor: "" };
+ const beforeCursor = value.substring(0, caretPosition[0]);
+ const afterCursor = value.substring(caretPosition[1]);
+ return { beforeCursor, afterCursor };
+ }, [value, caretPosition]);
+
const exprLastPart = useMemo(() => {
- const parts = value.split("}");
+ const parts = values.beforeCursor.split("}");
return parts[parts.length - 1];
- }, [value]);
+ }, [values]);
const metric = useMemo(() => {
const regexp = /\b[^{}(),\s]+(?={|$)/g;
@@ -43,7 +51,7 @@ const QueryEditorAutocomplete: FC = ({
}, [exprLastPart]);
const shouldSuppressAutoSuggestion = (value: string) => {
- const pattern = /([(),+\-*/^]|\b(?:or|and|unless|default|ifnot|if|group_left|group_right)\b)/;
+ const pattern = /([{(),+\-*/^]|\b(?:or|and|unless|default|ifnot|if|group_left|group_right)\b)/;
const parts = value.split(/\s+/);
const partsCount = parts.length;
const lastPart = parts[partsCount - 1];
@@ -55,7 +63,7 @@ const QueryEditorAutocomplete: FC = ({
};
const context = useMemo(() => {
- if (!value || value.endsWith("}") || shouldSuppressAutoSuggestion(value)) {
+ if (!values.beforeCursor || values.beforeCursor.endsWith("}") || shouldSuppressAutoSuggestion(values.beforeCursor)) {
return QueryContextType.empty;
}
@@ -63,19 +71,19 @@ const QueryEditorAutocomplete: FC = ({
const labelValueRegexp = new RegExp(`(${escapeRegexp(metric)})?{?.+${escapeRegexp(label)}(=|!=|=~|!~)"?([^"]*)$`, "g");
switch (true) {
- case labelValueRegexp.test(value):
+ case labelValueRegexp.test(values.beforeCursor):
return QueryContextType.labelValue;
- case labelRegexp.test(value):
+ case labelRegexp.test(values.beforeCursor):
return QueryContextType.label;
default:
return QueryContextType.metricsql;
}
- }, [value, metric, label]);
+ }, [values, metric, label]);
const valueByContext = useMemo(() => {
- const wordMatch = value.match(/([\w_\-.:/]+(?![},]))$/);
+ const wordMatch = values.beforeCursor.match(/([\w_\-.:/]+(?![},]))$/);
return wordMatch ? wordMatch[0] : "";
- }, [value]);
+ }, [values.beforeCursor]);
const { metrics, labels, labelValues, loading } = useFetchQueryOptions({
valueByContext,
@@ -97,8 +105,10 @@ const QueryEditorAutocomplete: FC = ({
}
}, [context, metrics, labels, labelValues]);
- const handleSelect = (insert: string) => {
+ const handleSelect = useCallback((insert: string) => {
// Find the start and end of valueByContext in the query string
+ const value = values.beforeCursor;
+ let valueAfterCursor = values.afterCursor;
const startIndexOfValueByContext = value.lastIndexOf(valueByContext, caretPosition[0]);
const endIndexOfValueByContext = startIndexOfValueByContext + valueByContext.length;
@@ -110,26 +120,59 @@ const QueryEditorAutocomplete: FC = ({
if (context === QueryContextType.labelValue) {
const quote = "\"";
const needsQuote = /(?:=|!=|=~|!~)$/.test(beforeValueByContext);
+ valueAfterCursor = valueAfterCursor.replace(/^[^\s"|},]*/, "");
insert = `${needsQuote ? quote : ""}${insert}`;
}
+ if (context === QueryContextType.label) {
+ valueAfterCursor = valueAfterCursor.replace(/^[^\s=!,{}()"|+\-/*^]*/, "");
+ }
+
+ if (context === QueryContextType.metricsql) {
+ valueAfterCursor = valueAfterCursor.replace(/^[^\s[\]{}()"|+\-/*^]*/, "");
+ }
// Assemble the new value with the inserted text
- const newVal = `${beforeValueByContext}${insert}${afterValueByContext}`;
- onSelect(newVal);
- };
+ const newVal = `${beforeValueByContext}${insert}${afterValueByContext}${valueAfterCursor}`;
+ onSelect(newVal, beforeValueByContext.length + insert.length);
+ }, [values]);
useEffect(() => {
if (!anchorEl.current) {
- setLeftOffset(0);
+ setOffsetPos({ top: 0, left: 0 });
return;
}
- const style = window.getComputedStyle(anchorEl.current);
+ const element = anchorEl.current.querySelector("textarea") || anchorEl.current;
+ const style = window.getComputedStyle(element);
const fontSize = `${style.getPropertyValue("font-size")}`;
const fontFamily = `${style.getPropertyValue("font-family")}`;
- const offset = getTextWidth(value, `${fontSize} ${fontFamily}`);
- setLeftOffset(offset);
- }, [anchorEl, caretPosition]);
+ const lineHeight = parseInt(`${style.getPropertyValue("line-height")}`);
+
+ const span = document.createElement("div");
+ span.style.font = `${fontSize} ${fontFamily}`;
+ span.style.padding = style.getPropertyValue("padding");
+ span.style.lineHeight = `${lineHeight}px`;
+ span.style.width = `${element.offsetWidth}px`;
+ span.style.maxWidth = `${element.offsetWidth}px`;
+ span.style.whiteSpace = style.getPropertyValue("white-space");
+ span.style.overflowWrap = style.getPropertyValue("overflow-wrap");
+
+ const marker = document.createElement("span");
+ span.appendChild(document.createTextNode(values.beforeCursor));
+ span.appendChild(marker);
+ span.appendChild(document.createTextNode(values.afterCursor));
+ document.body.appendChild(span);
+
+ const spanRect = span.getBoundingClientRect();
+ const markerRect = marker.getBoundingClientRect();
+
+ const leftOffset = markerRect.left - spanRect.left;
+ const topOffset = markerRect.bottom - spanRect.bottom - (hasHelperText ? lineHeight : 0);
+ setOffsetPos({ top: topOffset, left: leftOffset });
+
+ span.remove();
+ marker.remove();
+ }, [anchorEl, caretPosition, hasHelperText]);
return (
<>
@@ -140,7 +183,7 @@ const QueryEditorAutocomplete: FC = ({
options={options}
anchor={anchorEl}
minLength={0}
- offset={{ top: 0, left: leftOffset }}
+ offset={offsetPos}
onSelect={handleSelect}
onFoundOptions={onFoundOptions}
maxDisplayResults={{
diff --git a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss
index db48a9cf1..b012403ae 100644
--- a/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss
+++ b/app/vmui/packages/vmui/src/components/Configurators/QueryEditor/style.scss
@@ -2,4 +2,13 @@
.vm-query-editor {
position: relative;
+
+ .marker-detection {
+ position: absolute;
+ top: 0;
+ left: 0;
+ pointer-events: none;
+ z-index: -9999;
+ visibility: hidden;
+ }
}
diff --git a/app/vmui/packages/vmui/src/components/Main/Autocomplete/Autocomplete.tsx b/app/vmui/packages/vmui/src/components/Main/Autocomplete/Autocomplete.tsx
index ab83c2518..bbb15c76f 100644
--- a/app/vmui/packages/vmui/src/components/Main/Autocomplete/Autocomplete.tsx
+++ b/app/vmui/packages/vmui/src/components/Main/Autocomplete/Autocomplete.tsx
@@ -120,7 +120,7 @@ const Autocomplete: FC = ({
const handleKeyDown = useCallback((e: KeyboardEvent) => {
const { key, ctrlKey, metaKey, shiftKey } = e;
const modifiers = ctrlKey || metaKey || shiftKey;
- const hasOptions = foundOptions.length;
+ const hasOptions = foundOptions.length && !hideFoundedOptions;
if (key === "ArrowUp" && !modifiers && hasOptions) {
e.preventDefault();
@@ -148,7 +148,7 @@ const Autocomplete: FC = ({
if (key === "Escape") {
handleCloseAutocomplete();
}
- }, [focusOption, foundOptions, handleCloseAutocomplete, onSelect, selected]);
+ }, [focusOption, foundOptions, hideFoundedOptions, handleCloseAutocomplete, onSelect, selected]);
useEffect(() => {
setOpenAutocomplete(value.length >= minLength);
diff --git a/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx b/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx
index f95b4194e..a2a938885 100644
--- a/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx
+++ b/app/vmui/packages/vmui/src/components/Main/TextField/TextField.tsx
@@ -1,6 +1,7 @@
import React, {
FC,
useEffect,
+ useState,
useRef,
useMemo,
FormEvent,
@@ -28,12 +29,13 @@ interface TextFieldProps {
autofocus?: boolean
helperText?: string
inputmode?: "search" | "text" | "email" | "tel" | "url" | "none" | "numeric" | "decimal"
+ caretPosition?: [number, number]
onChange?: (value: string) => void
onEnter?: () => void
onKeyDown?: (e: KeyboardEvent) => void
onFocus?: () => void
onBlur?: () => void
- onChangeCaret?: (position: number[]) => void
+ onChangeCaret?: (position: [number, number]) => void
}
const TextField: FC = ({
@@ -49,6 +51,7 @@ const TextField: FC = ({
disabled = false,
autofocus = false,
inputmode = "text",
+ caretPosition,
onChange,
onEnter,
onKeyDown,
@@ -62,6 +65,7 @@ const TextField: FC = ({
const inputRef = useRef(null);
const textareaRef = useRef(null);
const fieldRef = useMemo(() => type === "textarea" ? textareaRef : inputRef, [type]);
+ const [selectionPos, setSelectionPos] = useState<[start: number, end: number]>([0, 0]);
const inputClasses = classNames({
"vm-text-field__input": true,
@@ -74,7 +78,7 @@ const TextField: FC = ({
const updateCaretPosition = (target: HTMLInputElement | HTMLTextAreaElement) => {
const { selectionStart, selectionEnd } = target;
- onChangeCaret && onChangeCaret([selectionStart || 0, selectionEnd || 0]);
+ setSelectionPos([selectionStart || 0, selectionEnd || 0]);
};
const handleMouseUp = (e: MouseEvent) => {
@@ -102,11 +106,6 @@ const TextField: FC = ({
updateCaretPosition(e.currentTarget);
};
- useEffect(() => {
- if (!autofocus || isMobile) return;
- fieldRef?.current?.focus && fieldRef.current.focus();
- }, [fieldRef, autofocus]);
-
const handleFocus = () => {
onFocus && onFocus();
};
@@ -115,6 +114,31 @@ const TextField: FC = ({
onBlur && onBlur();
};
+ const setSelectionRange = (range: [number, number]) => {
+ try {
+ fieldRef.current && fieldRef.current.setSelectionRange(range[0], range[1]);
+ } catch (e) {
+ return e;
+ }
+ };
+
+ useEffect(() => {
+ if (!autofocus || isMobile) return;
+ fieldRef?.current?.focus && fieldRef.current.focus();
+ }, [fieldRef, autofocus]);
+
+ useEffect(() => {
+ onChangeCaret && onChangeCaret(selectionPos);
+ }, [selectionPos]);
+
+ useEffect(() => {
+ setSelectionRange(selectionPos);
+ }, [value]);
+
+ useEffect(() => {
+ caretPosition && setSelectionRange(caretPosition);
+ }, [caretPosition]);
+
return (): [(node: T | n
useEventListener("resize", handleSize);
- useIsomorphicLayoutEffect(handleSize, [ref?.offsetHeight, ref?.offsetWidth]);
+ useEffect(handleSize, [ref?.offsetHeight, ref?.offsetWidth]);
return [setRef, size];
};
diff --git a/app/vmui/packages/vmui/src/hooks/useEventListener.ts b/app/vmui/packages/vmui/src/hooks/useEventListener.ts
index f97ce2d85..0ce2f1729 100644
--- a/app/vmui/packages/vmui/src/hooks/useEventListener.ts
+++ b/app/vmui/packages/vmui/src/hooks/useEventListener.ts
@@ -1,5 +1,4 @@
import { RefObject, useEffect, useRef } from "react";
-import useIsomorphicLayoutEffect from "./useIsomorphicLayoutEffect";
// MediaQueryList Event based useEventListener interface
function useEventListener(
@@ -56,7 +55,7 @@ function useEventListener<
// Create a ref that stores handler
const savedHandler = useRef(handler);
- useIsomorphicLayoutEffect(() => {
+ useEffect(() => {
savedHandler.current = handler;
}, [handler]);
diff --git a/app/vmui/packages/vmui/src/hooks/useFetchQuery.ts b/app/vmui/packages/vmui/src/hooks/useFetchQuery.ts
index 345958fe7..d700c7a4e 100644
--- a/app/vmui/packages/vmui/src/hooks/useFetchQuery.ts
+++ b/app/vmui/packages/vmui/src/hooks/useFetchQuery.ts
@@ -153,9 +153,17 @@ export const useFetchQuery = ({
setTraces(tempTraces);
setIsHistogram(prev => totalLength ? isHistogramResult : prev);
} catch (e) {
- if (e instanceof Error && e.name !== "AbortError") {
- setError(`${e.name}: ${e.message}`);
+ const error = e as Error;
+ if (error.name === "AbortError") {
+ // Aborts are expected, don't show an error for them.
+ return;
}
+ const helperText = "Please check your serverURL settings and confirm server availability.";
+ let text = `Error executing query: ${error.message}. ${helperText}`;
+ if (error.message === "Unexpected end of JSON input") {
+ text += "\nAdditionally, this error can occur if the server response is too large to process. Apply more specific filters to reduce the data volume.";
+ }
+ setError(text);
}
setIsLoading(false);
};
diff --git a/app/vmui/packages/vmui/src/hooks/useFetchQueryOptions.tsx b/app/vmui/packages/vmui/src/hooks/useFetchQueryOptions.tsx
index 44689e6ea..b15a00f91 100644
--- a/app/vmui/packages/vmui/src/hooks/useFetchQueryOptions.tsx
+++ b/app/vmui/packages/vmui/src/hooks/useFetchQueryOptions.tsx
@@ -96,6 +96,7 @@ export const useFetchQueryOptions = ({ valueByContext, metric, label, context }:
const cachedData = autocompleteCache.get(key);
if (cachedData) {
setter(processData(cachedData, type));
+ setLoading(false);
return;
}
const response = await fetch(`${serverUrl}/api/v1/${urlSuffix}?${params}`, { signal });
@@ -104,13 +105,13 @@ export const useFetchQueryOptions = ({ valueByContext, metric, label, context }:
setter(processData(data, type));
queryDispatch({ type: "SET_AUTOCOMPLETE_CACHE", payload: { key, value: data } });
}
+ setLoading(false);
} catch (e) {
if (e instanceof Error && e.name !== "AbortError") {
queryDispatch({ type: "SET_AUTOCOMPLETE_CACHE", payload: { key, value: [] } });
+ setLoading(false);
console.error(e);
}
- } finally {
- setLoading(false);
}
};
diff --git a/app/vmui/packages/vmui/src/hooks/useIsomorphicLayoutEffect.ts b/app/vmui/packages/vmui/src/hooks/useIsomorphicLayoutEffect.ts
deleted file mode 100644
index 8ccca8a63..000000000
--- a/app/vmui/packages/vmui/src/hooks/useIsomorphicLayoutEffect.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { useEffect, useLayoutEffect } from "react";
-
-const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
-
-export default useIsomorphicLayoutEffect;
diff --git a/app/vmui/packages/vmui/src/hooks/useWindowSize.ts b/app/vmui/packages/vmui/src/hooks/useWindowSize.ts
index 1b1e1021f..01090ea4d 100644
--- a/app/vmui/packages/vmui/src/hooks/useWindowSize.ts
+++ b/app/vmui/packages/vmui/src/hooks/useWindowSize.ts
@@ -1,6 +1,6 @@
import { useState } from "react";
-import useIsomorphicLayoutEffect from "./useIsomorphicLayoutEffect";
import useEventListener from "./useEventListener";
+import { useEffect } from "preact/compat";
interface WindowSize {
width: number
@@ -23,7 +23,7 @@ const useWindowSize = (): WindowSize => {
useEventListener("resize", handleSize);
// Set size at the first client-side load
- useIsomorphicLayoutEffect(handleSize, []);
+ useEffect(handleSize, []);
return windowSize;
};
diff --git a/dashboards/backupmanager.json b/dashboards/backupmanager.json
index 71e44416b..74c3c9d27 100644
--- a/dashboards/backupmanager.json
+++ b/dashboards/backupmanager.json
@@ -12,7 +12,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "9.0.4"
+ "version": "10.4.0"
},
{
"type": "datasource",
@@ -124,9 +124,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -198,9 +200,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -260,9 +264,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -323,9 +329,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -399,9 +407,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -471,9 +481,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -546,9 +558,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -577,7 +591,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -630,7 +646,9 @@
},
"id": 22,
"options": {
+ "cellHeight": "sm",
"footer": {
+ "countRows": false,
"fields": "",
"reducer": [
"sum"
@@ -645,7 +663,7 @@
}
]
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -700,7 +718,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -753,7 +773,9 @@
},
"id": 21,
"options": {
+ "cellHeight": "sm",
"footer": {
+ "countRows": false,
"fields": "",
"reducer": [
"sum"
@@ -768,7 +790,7 @@
}
]
},
- "pluginVersion": "9.0.4",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -885,7 +907,7 @@
"min",
"mean"
],
- "displayMode": "table",
+ "displayMode": "list",
"placement": "bottom",
"showLegend": false
},
@@ -1106,7 +1128,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1251,7 +1275,8 @@
"legend": {
"calcs": [],
"displayMode": "list",
- "placement": "bottom"
+ "placement": "bottom",
+ "showLegend": true
},
"orientation": "auto",
"showValue": "auto",
@@ -1343,7 +1368,7 @@
"max",
"mean"
],
- "displayMode": "table",
+ "displayMode": "list",
"placement": "right",
"showLegend": false
},
@@ -1436,7 +1461,8 @@
"legend": {
"calcs": [],
"displayMode": "list",
- "placement": "bottom"
+ "placement": "bottom",
+ "showLegend": true
},
"orientation": "auto",
"showValue": "auto",
@@ -1657,8 +1683,7 @@
}
],
"refresh": "1m",
- "schemaVersion": 36,
- "style": "dark",
+ "schemaVersion": 39,
"tags": [],
"templating": {
"list": [
diff --git a/dashboards/clusterbytenant.json b/dashboards/clusterbytenant.json
index 02650c3ba..80b8688e4 100644
--- a/dashboards/clusterbytenant.json
+++ b/dashboards/clusterbytenant.json
@@ -1,4 +1,38 @@
{
+ "__inputs": [],
+ "__elements": {},
+ "__requires": [
+ {
+ "type": "grafana",
+ "id": "grafana",
+ "name": "Grafana",
+ "version": "10.4.0"
+ },
+ {
+ "type": "panel",
+ "id": "piechart",
+ "name": "Pie chart",
+ "version": ""
+ },
+ {
+ "type": "datasource",
+ "id": "prometheus",
+ "name": "Prometheus",
+ "version": "1.0.0"
+ },
+ {
+ "type": "panel",
+ "id": "table",
+ "name": "Table",
+ "version": ""
+ },
+ {
+ "type": "panel",
+ "id": "timeseries",
+ "name": "Time series",
+ "version": ""
+ }
+ ],
"annotations": {
"list": [
{
@@ -26,7 +60,7 @@
"fiscalYearStartMonth": 0,
"gnetId": 16399,
"graphTooltip": 1,
- "id": 80,
+ "id": null,
"links": [],
"liveNow": false,
"panels": [
@@ -55,6 +89,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -158,6 +193,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -214,7 +250,6 @@
"y": 1
},
"id": 4,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -264,6 +299,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -376,6 +412,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -432,7 +469,6 @@
"y": 9
},
"id": 31,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -482,6 +518,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -538,7 +575,6 @@
"y": 17
},
"id": 10,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -587,6 +623,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -1114,7 +1151,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1198,7 +1237,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1230,7 +1269,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1314,7 +1355,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1346,7 +1387,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1430,7 +1473,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1462,7 +1505,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1546,7 +1591,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1578,7 +1623,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1662,7 +1709,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1694,7 +1741,9 @@
},
"custom": {
"align": "auto",
- "displayMode": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
"inspect": false
},
"mappings": [],
@@ -1778,7 +1827,7 @@
}
]
},
- "pluginVersion": "10.1.5",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1800,8 +1849,7 @@
}
],
"refresh": false,
- "schemaVersion": 37,
- "style": "dark",
+ "schemaVersion": 39,
"tags": [
"VictoriaMetrics",
"monitoring"
@@ -1828,15 +1876,7 @@
},
{
"allValue": ".*",
- "current": {
- "selected": true,
- "text": [
- "All"
- ],
- "value": [
- "$__all"
- ]
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "$ds"
@@ -1862,15 +1902,7 @@
},
{
"allValue": ".*",
- "current": {
- "selected": true,
- "text": [
- "All"
- ],
- "value": [
- "$__all"
- ]
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "$ds"
@@ -1915,6 +1947,6 @@
"timezone": "",
"title": "VictoriaMetrics Cluster Per Tenant Statistic",
"uid": "IZFqd3lMz",
- "version": 15,
+ "version": 1,
"weekStart": ""
}
\ No newline at end of file
diff --git a/dashboards/operator.json b/dashboards/operator.json
index 4f9cc6c7a..df0f71fce 100644
--- a/dashboards/operator.json
+++ b/dashboards/operator.json
@@ -6,13 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "9.2.2"
- },
- {
- "type": "panel",
- "id": "graph",
- "name": "Graph (old)",
- "version": ""
+ "version": "10.4.0"
},
{
"type": "datasource",
@@ -31,6 +25,12 @@
"id": "text",
"name": "Text",
"version": ""
+ },
+ {
+ "type": "panel",
+ "id": "timeseries",
+ "name": "Time series",
+ "version": ""
}
],
"annotations": {
@@ -67,7 +67,7 @@
"collapsed": false,
"datasource": {
"type": "prometheus",
- "uid": "$ds"
+ "uid": "PB894574A363DF0AF"
},
"gridPos": {
"h": 1,
@@ -81,7 +81,7 @@
{
"datasource": {
"type": "prometheus",
- "uid": "$ds"
+ "uid": "PB894574A363DF0AF"
},
"refId": "A"
}
@@ -110,7 +110,7 @@
"content": "$version
",
"mode": "markdown"
},
- "pluginVersion": "9.2.2",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -170,10 +170,12 @@
"fields": "",
"values": false
},
+ "showPercentChange": false,
"text": {},
- "textMode": "auto"
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.2.2",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -205,12 +207,12 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
+ "color": "red",
"value": null
},
{
- "color": "red",
- "value": 80
+ "color": "green",
+ "value": 1800
}
]
},
@@ -237,9 +239,11 @@
"fields": "",
"values": false
},
- "textMode": "auto"
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "9.2.2",
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -261,49 +265,88 @@
"type": "stat"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
- "fill": 1,
- "fillGradient": 0,
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
"gridPos": {
"h": 13,
"w": 12,
"x": 0,
"y": 8
},
- "hiddenSeries": false,
"id": 12,
- "legend": {
- "alignAsTable": true,
- "avg": true,
- "current": false,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
},
- "percentage": false,
- "pluginVersion": "9.2.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -311,87 +354,99 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=~\"requeue_after|requeue|success\"}[$__rate_interval])) by(controller)",
+ "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=~\"requeue_after|requeue|success\"}[$__rate_interval])) by(controller) > 0",
"legendFormat": "{{controller}}",
"range": true,
"refId": "A"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "Reconciliation rate by controller",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
"description": "",
- "fill": 1,
- "fillGradient": 0,
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
"gridPos": {
"h": 13,
"w": 12,
"x": 12,
"y": 8
},
- "hiddenSeries": false,
"id": 16,
- "legend": {
- "alignAsTable": true,
- "avg": true,
- "current": false,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
},
- "percentage": false,
- "pluginVersion": "9.2.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -405,41 +460,14 @@
"refId": "A"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "Log message rate",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
},
{
- "collapsed": false,
+ "collapsed": true,
"datasource": {
"type": "prometheus",
- "uid": "$ds"
+ "uid": "PB894574A363DF0AF"
},
"gridPos": {
"h": 1,
@@ -448,402 +476,442 @@
"y": 21
},
"id": 6,
- "panels": [],
- "targets": [
+ "panels": [
{
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
+ "description": "Non zero metrics indicates about error with CR object definition (typos or incorrect values) or errors with kubernetes API connection.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 2
+ },
+ "id": 10,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "sum(rate(controller_runtime_reconcile_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) by(controller) > 0 ",
+ "instant": false,
+ "legendFormat": "{{controller}}",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=\"error\"}[$__rate_interval])) by(controller) > 0",
+ "hide": false,
+ "legendFormat": "{{label_name}}",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "reconcile errors by controller",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": "Operator limits number of reconcilation events to 5 events per 2 seconds.\n For now, this limit is applied only for vmalert and vmagent controllers.\n It should reduce load at kubernetes cluster and increase operator performance.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 2
+ },
+ "id": 18,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(operator_reconcile_throttled_events_total[$__rate_interval])) by(controller)",
+ "legendFormat": "{{controller}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "throttled reconcilation events",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": "Number of objects waiting in the queue for reconciliation. Non-zero values indicate that operator cannot process CR objects changes with the given resources.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 11,
+ "w": 12,
+ "x": 0,
+ "y": 10
+ },
+ "id": 20,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "10.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "max(workqueue_depth{job=~\"$job\",instance=~\"$instance\"}) by (name)",
+ "legendFormat": "{{label_name}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Wokring queue depth",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": " For controllers with StatefulSet it's ok to see latency greater then 3 seconds. It could be vmalertmanager,vmcluster or vmagent in statefulMode.\n\n For other controllers, latency greater then 1 second may indicate issues with kubernetes cluster or operator's performance.\n ",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 11,
+ "w": 12,
+ "x": 12,
+ "y": 10
+ },
+ "id": 26,
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "10.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "histogram_quantile(0.99, sum(rate(controller_runtime_reconcile_time_seconds_bucket[$__rate_interval])) by(le,controller))",
+ "legendFormat": "q.99 {{controller}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Reconcilation latency by controller",
+ "type": "timeseries"
+ }
+ ],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PB894574A363DF0AF"
+ },
"refId": "A"
}
],
"title": "Troubleshooting",
"type": "row"
},
- {
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "description": "Non zero metrics indicates about error with CR object definition (typos or incorrect values) or errors with kubernetes API connection.",
- "fill": 1,
- "fillGradient": 0,
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 0,
- "y": 22
- },
- "hiddenSeries": false,
- "id": 10,
- "legend": {
- "alignAsTable": true,
- "avg": false,
- "current": true,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
- "options": {
- "alertThreshold": true
- },
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "sum(rate(controller_runtime_reconcile_errors_total{job=~\"$job\",instance=~\"$instance\"}[$__rate_interval])) by(controller) > 0 ",
- "instant": false,
- "legendFormat": "{{controller}}",
- "range": true,
- "refId": "A"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "expr": "sum(rate(controller_runtime_reconcile_total{job=~\"$job\",instance=~\"$instance\",result=\"error\"}[$__rate_interval])) by(controller) > 0",
- "hide": false,
- "legendFormat": "{{label_name}}",
- "range": true,
- "refId": "B"
- }
- ],
- "thresholds": [],
- "timeRegions": [],
- "title": "reconcile errors by controller",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
- },
- {
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "description": "Operator limits number of reconcilation events to 5 events per 2 seconds.\n For now, this limit is applied only for vmalert and vmagent controllers.\n It should reduce load at kubernetes cluster and increase operator performance.",
- "fill": 1,
- "fillGradient": 0,
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 12,
- "y": 22
- },
- "hiddenSeries": false,
- "id": 18,
- "legend": {
- "avg": false,
- "current": false,
- "max": false,
- "min": false,
- "show": true,
- "total": false,
- "values": false
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
- "options": {
- "alertThreshold": true
- },
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "expr": "sum(rate(operator_reconcile_throttled_events_total[$__rate_interval])) by(controller)",
- "legendFormat": "{{controller}}",
- "range": true,
- "refId": "A"
- }
- ],
- "thresholds": [],
- "timeRegions": [],
- "title": "throttled reconcilation events",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
- },
- {
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "description": "Number of objects waiting in the queue for reconciliation. Non-zero values indicate that operator cannot process CR objects changes with the given resources.",
- "fill": 1,
- "fillGradient": 0,
- "gridPos": {
- "h": 11,
- "w": 12,
- "x": 0,
- "y": 30
- },
- "hiddenSeries": false,
- "id": 20,
- "legend": {
- "alignAsTable": true,
- "avg": false,
- "current": true,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
- "options": {
- "alertThreshold": true
- },
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "expr": "max(workqueue_depth{job=~\"$job\",instance=~\"$instance\"}) by (name)",
- "legendFormat": "{{label_name}}",
- "range": true,
- "refId": "A"
- }
- ],
- "thresholds": [],
- "timeRegions": [],
- "title": "Wokring queue depth",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
- },
- {
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "description": " For controllers with StatefulSet it's ok to see latency greater then 3 seconds. It could be vmalertmanager,vmcluster or vmagent in statefulMode.\n\n For other controllers, latency greater then 1 second may indicate issues with kubernetes cluster or operator's performance.\n ",
- "fieldConfig": {
- "defaults": {
- "unit": "s"
- },
- "overrides": []
- },
- "fill": 1,
- "fillGradient": 0,
- "gridPos": {
- "h": 11,
- "w": 12,
- "x": 12,
- "y": 30
- },
- "hiddenSeries": false,
- "id": 26,
- "legend": {
- "alignAsTable": true,
- "avg": true,
- "current": false,
- "max": true,
- "min": false,
- "rightSide": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
- "options": {
- "alertThreshold": true
- },
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "expr": "histogram_quantile(0.99,sum(rate(controller_runtime_reconcile_time_seconds_bucket[$__rate_interval])) by(le,controller) )",
- "legendFormat": "q.99 {{controller}}",
- "range": true,
- "refId": "A"
- }
- ],
- "thresholds": [],
- "timeRegions": [],
- "title": "Reconcilation latency by controller",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "s",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
- },
{
"collapsed": false,
"datasource": {
"type": "prometheus",
- "uid": "$ds"
+ "uid": "PB894574A363DF0AF"
},
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
- "y": 41
+ "y": 22
},
"id": 4,
"panels": [],
@@ -851,7 +919,7 @@
{
"datasource": {
"type": "prometheus",
- "uid": "$ds"
+ "uid": "PB894574A363DF0AF"
},
"refId": "A"
}
@@ -860,55 +928,89 @@
"type": "row"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
"fieldConfig": {
"defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
"unit": "bytes"
},
"overrides": []
},
- "fill": 1,
- "fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
- "y": 42
+ "y": 23
},
- "hiddenSeries": false,
"id": 28,
- "legend": {
- "alignAsTable": true,
- "avg": true,
- "current": true,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
},
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -958,79 +1060,90 @@
"refId": "D"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "Memory usage ($instance)",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "bytes",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
- "fill": 1,
- "fillGradient": 0,
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "axisSoftMin": 0,
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
- "y": 42
+ "y": 23
},
- "hiddenSeries": false,
"id": 30,
- "legend": {
- "avg": false,
- "current": false,
- "max": false,
- "min": false,
- "show": true,
- "total": false,
- "values": false
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
},
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1044,79 +1157,89 @@
"refId": "A"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "CPU ($instance)",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
- "fill": 1,
- "fillGradient": 0,
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
- "y": 50
+ "y": 31
},
- "hiddenSeries": false,
"id": 32,
- "legend": {
- "avg": false,
- "current": false,
- "max": false,
- "min": false,
- "show": true,
- "total": false,
- "values": false
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
},
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1130,86 +1253,92 @@
"refId": "A"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "Goroutines ($instance)",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
},
{
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
"fieldConfig": {
"defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
"unit": "s"
},
"overrides": []
},
- "fill": 1,
- "fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
- "y": 50
+ "y": 31
},
- "hiddenSeries": false,
"id": 34,
- "legend": {
- "alignAsTable": true,
- "avg": true,
- "current": false,
- "max": true,
- "min": false,
- "show": true,
- "total": false,
- "values": true
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
"options": {
- "alertThreshold": true
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
},
- "percentage": false,
- "pluginVersion": "8.3.2",
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
+ "pluginVersion": "10.4.0",
"targets": [
{
"datasource": {
@@ -1223,40 +1352,12 @@
"refId": "A"
}
],
- "thresholds": [],
- "timeRegions": [],
"title": "GC duration ($instance)",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "mode": "time",
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "s",
- "logBase": 1,
- "show": true
- },
- {
- "format": "short",
- "logBase": 1,
- "show": true
- }
- ],
- "yaxis": {
- "align": false
- }
+ "type": "timeseries"
}
],
"refresh": "",
- "schemaVersion": 37,
- "style": "dark",
+ "schemaVersion": 39,
"tags": [
"operator",
"VictoriaMetrics"
@@ -1265,9 +1366,9 @@
"list": [
{
"current": {
- "selected": false,
- "text": "cloud-c15",
- "value": "cloud-c15"
+ "selected": true,
+ "text": "VictoriaMetrics",
+ "value": "PF64AB64142051B50"
},
"hide": 0,
"includeAll": false,
@@ -1331,15 +1432,16 @@
"type": "prometheus",
"uid": "$ds"
},
- "definition": "label_values(vm_app_version{job=\"$job\", instance=\"$instance\"}, version)",
+ "definition": "label_values(vm_app_version{job=\"$job\", instance=~\"$instance\"},version)",
"hide": 2,
"includeAll": false,
"multi": false,
"name": "version",
"options": [],
"query": {
- "query": "label_values(vm_app_version{job=\"$job\", instance=\"$instance\"}, version)",
- "refId": "StandardVariableQuery"
+ "qryType": 1,
+ "query": "label_values(vm_app_version{job=\"$job\", instance=~\"$instance\"},version)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
diff --git a/dashboards/victorialogs.json b/dashboards/victorialogs.json
index 9a08b5660..ca0871ccd 100644
--- a/dashboards/victorialogs.json
+++ b/dashboards/victorialogs.json
@@ -6,7 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -115,8 +115,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -127,7 +126,6 @@
"y": 1
},
"id": 10,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -146,7 +144,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -188,8 +186,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -200,7 +197,6 @@
"y": 1
},
"id": 22,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -219,7 +215,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -261,8 +257,7 @@
}
]
},
- "unit": "none",
- "unitScale": true
+ "unit": "none"
},
"overrides": []
},
@@ -273,7 +268,6 @@
"y": 1
},
"id": 25,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -292,7 +286,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -338,8 +332,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -350,7 +343,6 @@
"y": 1
},
"id": 30,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -369,7 +361,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -414,8 +406,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -443,7 +434,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -483,8 +474,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -495,7 +485,6 @@
"y": 3
},
"id": 24,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -514,7 +503,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -556,8 +545,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -568,7 +556,6 @@
"y": 3
},
"id": 36,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -587,7 +574,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -629,8 +616,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -641,7 +627,6 @@
"y": 3
},
"id": 34,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -660,7 +645,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -751,8 +736,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -763,7 +747,6 @@
"y": 6
},
"id": 2,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -860,8 +843,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -872,7 +854,6 @@
"y": 6
},
"id": 14,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -970,8 +951,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -982,7 +962,6 @@
"y": 14
},
"id": 6,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1080,8 +1059,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1092,7 +1070,6 @@
"y": 14
},
"id": 26,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1203,8 +1180,7 @@
}
]
},
- "unit": "percentunit",
- "unitScale": true
+ "unit": "percentunit"
},
"overrides": []
},
@@ -1215,7 +1191,6 @@
"y": 23
},
"id": 38,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1312,8 +1287,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -1324,7 +1298,6 @@
"y": 23
},
"id": 40,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1471,8 +1444,7 @@
}
]
},
- "unit": "percentunit",
- "unitScale": true
+ "unit": "percentunit"
},
"overrides": []
},
@@ -1483,7 +1455,6 @@
"y": 31
},
"id": 42,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1579,8 +1550,7 @@
}
]
},
- "unit": "percentunit",
- "unitScale": true
+ "unit": "percentunit"
},
"overrides": []
},
@@ -1591,7 +1561,6 @@
"y": 31
},
"id": 44,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1691,8 +1660,7 @@
}
]
},
- "unit": "percentunit",
- "unitScale": true
+ "unit": "percentunit"
},
"overrides": [
{
@@ -1719,7 +1687,6 @@
"y": 39
},
"id": 46,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1818,8 +1785,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": [
{
@@ -1846,7 +1812,6 @@
"y": 39
},
"id": 48,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1958,8 +1923,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1970,7 +1934,6 @@
"y": 47
},
"id": 50,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2066,8 +2029,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": [
{
@@ -2091,7 +2053,6 @@
"y": 47
},
"id": 52,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2201,8 +2162,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -2213,7 +2173,6 @@
"y": 55
},
"id": 54,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2309,8 +2268,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": [
{
@@ -2334,7 +2292,6 @@
"y": 55
},
"id": 56,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2448,8 +2405,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -2460,7 +2416,6 @@
"y": 63
},
"id": 58,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2558,8 +2513,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -2570,7 +2524,6 @@
"y": 63
},
"id": 60,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -2617,7 +2570,7 @@
"list": [
{
"current": {
- "selected": true,
+ "selected": false,
"text": "VictoriaMetrics",
"value": "P4169E866C3094E38"
},
@@ -2700,4 +2653,4 @@
"uid": "OqPIZTX4z",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/victoriametrics-cluster.json b/dashboards/victoriametrics-cluster.json
index ffb70b10b..b180668e4 100644
--- a/dashboards/victoriametrics-cluster.json
+++ b/dashboards/victoriametrics-cluster.json
@@ -6,7 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -168,8 +168,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -180,7 +179,6 @@
"y": 1
},
"id": 131,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -199,7 +197,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -240,8 +238,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -252,7 +249,6 @@
"y": 1
},
"id": 124,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -271,7 +267,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -314,8 +310,7 @@
}
]
},
- "unit": "req/s",
- "unitScale": true
+ "unit": "req/s"
},
"overrides": []
},
@@ -326,7 +321,6 @@
"y": 1
},
"id": 130,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -345,7 +339,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -387,8 +381,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -399,7 +392,6 @@
"y": 1
},
"id": 126,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -418,7 +410,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -460,8 +452,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -472,7 +463,6 @@
"y": 4
},
"id": 34,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -491,7 +481,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -533,8 +523,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -545,7 +534,6 @@
"y": 4
},
"id": 35,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -564,7 +552,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -606,8 +594,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -618,7 +605,6 @@
"y": 4
},
"id": 112,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -637,7 +623,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -678,8 +664,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -690,7 +675,6 @@
"y": 4
},
"id": 128,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -709,7 +693,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -761,8 +745,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -816,7 +799,7 @@
}
]
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -893,8 +876,7 @@
}
]
},
- "unit": "none",
- "unitScale": true
+ "unit": "none"
},
"overrides": []
},
@@ -1018,8 +1000,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1126,8 +1107,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1138,7 +1118,6 @@
"y": 13
},
"id": 6,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1235,8 +1214,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1341,8 +1319,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -1353,7 +1330,6 @@
"y": 21
},
"id": 8,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1441,7 +1417,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1449,8 +1426,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1461,7 +1437,6 @@
"y": 29
},
"id": 52,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1555,7 +1530,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1563,8 +1539,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1575,7 +1550,6 @@
"y": 29
},
"id": 104,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1686,8 +1660,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1801,8 +1774,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1915,8 +1887,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2025,8 +1996,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2166,8 +2136,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2292,8 +2261,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2432,8 +2400,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2540,8 +2507,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2648,8 +2614,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2756,8 +2721,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2865,8 +2829,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4779,6 +4742,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4792,6 +4756,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4815,7 +4780,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -4831,10 +4797,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 14
+ "y": 6
},
"id": 100,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -4884,6 +4849,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4897,6 +4863,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4926,7 +4893,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -4942,10 +4910,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 14
+ "y": 6
},
"id": 113,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -4996,6 +4963,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5009,6 +4977,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5038,7 +5007,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5054,10 +5024,9 @@
"h": 7,
"w": 12,
"x": 0,
- "y": 22
+ "y": 14
},
"id": 151,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5141,6 +5110,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5154,6 +5124,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5183,7 +5154,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5199,10 +5171,9 @@
"h": 7,
"w": 12,
"x": 12,
- "y": 22
+ "y": 14
},
"id": 167,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5274,109 +5245,6 @@
"title": "Memory usage % ($instance)",
"type": "timeseries"
},
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "description": "Value > 0 means vmstorage is in readonly mode.",
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 0,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green"
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "short"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 0,
- "y": 29
- },
- "id": 141,
- "links": [
- {
- "targetBlank": true,
- "title": "Readonly mode",
- "url": "https://docs.victoriametrics.com/cluster-victoriametrics/#readonly-mode"
- }
- ],
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": false
- },
- "tooltip": {
- "mode": "multi",
- "sort": "desc"
- }
- },
- "pluginVersion": "9.1.0",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "$ds"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "vm_storage_is_read_only{job=~\"$job_storage\", instance=~\"$instance\"} > 0",
- "interval": "",
- "legendFormat": "{{ instance }}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Readonly mode",
- "type": "timeseries"
- },
{
"datasource": {
"type": "prometheus",
@@ -5389,6 +5257,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5402,6 +5271,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5423,7 +5293,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5454,10 +5325,10 @@
"gridPos": {
"h": 8,
"w": 12,
- "x": 12,
- "y": 29
+ "x": 0,
+ "y": 21
},
- "id": 133,
+ "id": 212,
"links": [
{
"targetBlank": true,
@@ -5521,13 +5392,14 @@
"type": "prometheus",
"uid": "$ds"
},
- "description": "The number of on-going merges in storage nodes. It is expected to have high numbers for `storage/small` metric.",
+ "description": "Shows the number of concurrently executed read requests, where:\n* `max` - equal to `-search.maxConcurrentRequest` cmd-line flag;\n* `current` - current number of concurrent select requests executed by storage.\n\nEach concurrent select request requires RAM, CPU and disk IO resources during processing. Too many concurrent requests could result into OOM exceptions.\n\nWhen `current` hits `max` constantly, it means storage is overloaded and requires more CPU (see CPU usage) or disks with more IOPS (see disk writes and reads panels in Resource Usage row).\n\nSee more at https://docs.victoriametrics.com/cluster-victoriametrics/#resource-usage-limits",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5541,6 +5413,142 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "max"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#C4162A",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 21
+ },
+ "id": 133,
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true,
+ "sortBy": "Last *",
+ "sortDesc": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "max(\n max_over_time(vm_vmselect_concurrent_requests_current{job=~\"$job_storage\", \n instance=~\"$instance\"}[$__rate_interval])\n)",
+ "interval": "",
+ "legendFormat": "current",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "min(vm_vmselect_concurrent_requests_capacity{job=~\"$job_storage\", instance=~\"$instance\"})",
+ "hide": false,
+ "interval": "",
+ "legendFormat": "max",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Concurrent selects ($instance)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": "The max number of on-going merges across storage nodes.\n The drastic change in number of merges could be a sign of on-going deduplication/downsampling activity.\n It is expected to have high numbers for `storage/small` metric.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5565,7 +5573,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5581,7 +5590,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 37
+ "y": 29
},
"id": 54,
"options": {
@@ -5610,7 +5619,7 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(max_over_time(vm_active_merges{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
+ "expr": "max(max_over_time(vm_active_merges{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
"legendFormat": "__auto",
"range": true,
"refId": "A"
@@ -5631,6 +5640,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5644,6 +5654,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5668,7 +5679,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5684,7 +5696,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 37
+ "y": 29
},
"id": 55,
"options": {
@@ -5734,6 +5746,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5747,6 +5760,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5776,7 +5790,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5792,10 +5807,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 45
+ "y": 37
},
"id": 20,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5873,6 +5887,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5886,6 +5901,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5909,7 +5925,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5925,10 +5942,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 45
+ "y": 37
},
"id": 22,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5979,6 +5995,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5992,6 +6009,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6021,7 +6039,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
},
@@ -6033,10 +6052,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 53
+ "y": 45
},
"id": 202,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6100,6 +6118,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -6113,6 +6132,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6136,7 +6156,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -6169,10 +6190,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 53
+ "y": 45
},
"id": 14,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6237,6 +6257,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -6250,6 +6271,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6272,7 +6294,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -6299,12 +6322,11 @@
},
"gridPos": {
"h": 8,
- "w": 24,
+ "w": 12,
"x": 0,
- "y": 61
+ "y": 53
},
"id": 206,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6354,6 +6376,112 @@
],
"title": "Network usage ($instance)",
"type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": "Value > 0 means vmstorage is in readonly mode.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 53
+ },
+ "id": 141,
+ "links": [
+ {
+ "targetBlank": true,
+ "title": "Readonly mode",
+ "url": "https://docs.victoriametrics.com/cluster-victoriametrics/#readonly-mode"
+ }
+ ],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "vm_storage_is_read_only{job=~\"$job_storage\", instance=~\"$instance\"} > 0",
+ "interval": "",
+ "legendFormat": "{{ instance }}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Readonly mode",
+ "type": "timeseries"
}
],
"title": "vmstorage ($instance)",
@@ -9681,4 +9809,4 @@
"uid": "oS7Bi_0Wz",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/victoriametrics.json b/dashboards/victoriametrics.json
index ec39cbe3f..785bc07be 100644
--- a/dashboards/victoriametrics.json
+++ b/dashboards/victoriametrics.json
@@ -6,7 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -168,7 +168,7 @@
"content": "$version
",
"mode": "markdown"
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -202,8 +202,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -214,7 +213,6 @@
"y": 1
},
"id": 26,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -233,13 +231,14 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
"expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
"format": "time_series",
@@ -274,8 +273,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -286,7 +284,6 @@
"y": 1
},
"id": 107,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -305,7 +302,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -347,8 +344,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -359,7 +355,6 @@
"y": 1
},
"id": 108,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -378,7 +373,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -424,8 +419,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -436,7 +430,6 @@
"y": 1
},
"id": 77,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -455,7 +448,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -499,8 +492,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -528,7 +520,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -537,7 +529,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "vm_app_uptime_seconds{job=~\"$job\", instance=~\"$instance\"}",
+ "expr": "min(vm_app_uptime_seconds{job=~\"$job\", instance=~\"$instance\"})",
"instant": true,
"interval": "",
"legendFormat": "",
@@ -568,8 +560,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -580,7 +571,6 @@
"y": 3
},
"id": 38,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -599,15 +589,16 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}",
+ "expr": "sum(vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"})",
"format": "time_series",
"instant": true,
"interval": "",
@@ -640,8 +631,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -652,7 +642,6 @@
"y": 3
},
"id": 81,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -671,7 +660,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -713,8 +702,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -725,7 +713,6 @@
"y": 3
},
"id": 82,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -744,7 +731,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -753,7 +740,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) / sum(vm_rows{job=~\"$job\", instance=~\"$instance\"})",
+ "expr": "max(sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) / sum(vm_rows{job=~\"$job\", instance=~\"$instance\"}))",
"format": "time_series",
"instant": true,
"interval": "",
@@ -786,8 +773,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -798,7 +784,6 @@
"y": 3
},
"id": 78,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -817,7 +802,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -921,8 +906,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -933,7 +917,6 @@
"y": 6
},
"id": 106,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -958,16 +941,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0",
+ "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type, instance) > 0",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Datapoints ingestion rate ($instance)",
+ "title": "Datapoints ingestion rate",
"type": "timeseries"
},
{
@@ -1029,8 +1012,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1041,7 +1023,6 @@
"y": 6
},
"id": 12,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1068,16 +1049,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0",
+ "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path, instance) > 0",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{path}}",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Requests rate ($instance)",
+ "title": "Requests rate",
"type": "timeseries"
},
{
@@ -1139,8 +1120,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1181,14 +1161,16 @@
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "Active time series",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Active time series ($instance)",
+ "title": "Active time series",
"type": "timeseries"
},
{
@@ -1250,8 +1232,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -1262,7 +1243,6 @@
"y": 14
},
"id": 22,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1289,15 +1269,15 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (path) > 0",
+ "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (instance, path) > 0",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Query duration 0.99 quantile ($instance)",
+ "title": "Query duration 0.99 quantile",
"type": "timeseries"
},
{
@@ -1312,6 +1292,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -1325,6 +1306,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1348,7 +1330,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1367,7 +1350,6 @@
"y": 22
},
"id": 35,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1392,16 +1374,16 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0",
+ "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, path) > 0",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Requests error rate ($instance)",
+ "title": "Requests error rate",
"type": "timeseries"
},
{
@@ -1416,6 +1398,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -1429,6 +1412,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1450,7 +1434,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1493,9 +1478,9 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (level, location) > 0",
+ "expr": "sum(rate(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (instance, level, location) > 0",
"interval": "5m",
- "legendFormat": "{{level}}: {{location}}",
+ "legendFormat": "{{instance}} - {{level}}: {{location}}",
"range": true,
"refId": "A"
}
@@ -1567,8 +1552,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1585,7 +1569,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 3
+ "y": 31
},
"id": 112,
"links": [],
@@ -1623,7 +1607,7 @@
"refId": "A"
}
],
- "title": "RSS memory % usage ($instance)",
+ "title": "RSS memory % usage",
"type": "timeseries"
},
{
@@ -1676,8 +1660,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1694,7 +1677,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 3
+ "y": 31
},
"id": 44,
"links": [],
@@ -1723,11 +1706,13 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "requested from system",
+ "legendFormat": "{{instance}} - requested from system",
+ "range": true,
"refId": "A"
},
{
@@ -1735,11 +1720,13 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "heap inuse",
+ "legendFormat": "{{instance}} - heap inuse",
+ "range": true,
"refId": "B"
},
{
@@ -1747,11 +1734,13 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "stack inuse",
+ "legendFormat": "{{instance}} - stack inuse",
+ "range": true,
"refId": "C"
},
{
@@ -1759,12 +1748,14 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "resident",
+ "legendFormat": "{{instance}} - resident",
+ "range": true,
"refId": "D"
},
{
@@ -1772,17 +1763,19 @@
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "resident anonymous",
+ "legendFormat": "{{instance}} - resident anonymous",
+ "range": true,
"refId": "E"
}
],
- "title": "Memory usage ($instance)",
+ "title": "Memory usage",
"type": "timeseries"
},
{
@@ -1835,8 +1828,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1853,7 +1845,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 11
+ "y": 39
},
"id": 123,
"links": [],
@@ -1891,7 +1883,7 @@
"refId": "A"
}
],
- "title": "RSS anonymous memory % usage ($instance)",
+ "title": "RSS anonymous memory % usage",
"type": "timeseries"
},
{
@@ -1943,8 +1935,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1961,7 +1952,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 11
+ "y": 39
},
"id": 114,
"links": [],
@@ -2001,7 +1992,7 @@
"refId": "A"
}
],
- "title": "CPU % usage ($instance)",
+ "title": "CPU % usage",
"type": "timeseries"
},
{
@@ -2055,8 +2046,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2089,7 +2079,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 19
+ "y": 47
},
"id": 75,
"links": [],
@@ -2129,7 +2119,7 @@
"refId": "A"
}
],
- "title": "Open FDs ($instance)",
+ "title": "Open FDs",
"type": "timeseries"
},
{
@@ -2137,7 +2127,7 @@
"type": "prometheus",
"uid": "$ds"
},
- "description": "",
+ "description": "CPU cores used by instance",
"fieldConfig": {
"defaults": {
"color": {
@@ -2182,8 +2172,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2216,7 +2205,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 19
+ "y": 47
},
"id": 57,
"links": [],
@@ -2245,11 +2234,13 @@
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"expr": "rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "CPU cores used",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
},
{
@@ -2257,17 +2248,19 @@
"type": "prometheus",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"}",
+ "expr": "min(process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"})",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "Limit",
+ "range": true,
"refId": "B"
}
],
- "title": "CPU ($instance)",
+ "title": "CPU",
"type": "timeseries"
},
{
@@ -2320,8 +2313,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2338,7 +2330,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 27
+ "y": 55
},
"id": 47,
"links": [],
@@ -2376,7 +2368,7 @@
"refId": "A"
}
],
- "title": "Goroutines ($instance)",
+ "title": "Goroutines",
"type": "timeseries"
},
{
@@ -2428,8 +2420,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2443,8 +2434,8 @@
"overrides": [
{
"matcher": {
- "id": "byName",
- "options": "read"
+ "id": "byRegexp",
+ "options": "/.*read/"
},
"properties": [
{
@@ -2459,7 +2450,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 27
+ "y": 55
},
"id": 76,
"links": [],
@@ -2488,12 +2479,14 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "read",
+ "legendFormat": "{{instance}} - read",
+ "range": true,
"refId": "A"
},
{
@@ -2501,16 +2494,18 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "write",
+ "legendFormat": "{{instance}} - write",
+ "range": true,
"refId": "B"
}
],
- "title": "Disk writes/reads ($instance)",
+ "title": "Disk writes/reads",
"type": "timeseries"
},
{
@@ -2563,8 +2558,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2581,7 +2575,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 35
+ "y": 63
},
"id": 48,
"links": [],
@@ -2619,7 +2613,7 @@
"refId": "A"
}
],
- "title": "Threads ($instance)",
+ "title": "Threads",
"type": "timeseries"
},
{
@@ -2671,8 +2665,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2686,8 +2679,8 @@
"overrides": [
{
"matcher": {
- "id": "byName",
- "options": "read calls"
+ "id": "byRegexp",
+ "options": "/.*read.*/"
},
"properties": [
{
@@ -2702,7 +2695,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 35
+ "y": 63
},
"id": 124,
"links": [],
@@ -2732,12 +2725,12 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "read calls",
+ "legendFormat": "{{instance}} - read calls",
"range": true,
"refId": "A"
},
@@ -2747,17 +2740,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "write calls",
+ "legendFormat": "{{instance}} - write calls",
"range": true,
"refId": "B"
}
],
- "title": "Disk write/read calls ($instance)",
+ "title": "Disk write/read calls",
"type": "timeseries"
},
{
@@ -2810,8 +2803,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2828,7 +2820,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 43
+ "y": 71
},
"id": 49,
"links": [],
@@ -2867,7 +2859,7 @@
"refId": "A"
}
],
- "title": "TCP connections rate ($instance)",
+ "title": "TCP connections rate",
"type": "timeseries"
},
{
@@ -2920,8 +2912,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2938,7 +2929,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 43
+ "y": 71
},
"id": 37,
"links": [],
@@ -2977,7 +2968,142 @@
"refId": "A"
}
],
- "title": "TCP connections ($instance)",
+ "title": "TCP connections",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "description": "Shows network usage by VM:\n* Writes show traffic sent to clients\n* Reads show traffic received from clients",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "links": [],
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "decbits",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byRegexp",
+ "options": "/read.*/"
+ },
+ "properties": [
+ {
+ "id": "custom.transform",
+ "value": "negative-Y"
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 79
+ },
+ "id": 127,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true,
+ "sortBy": "Last *",
+ "sortDesc": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(vm_tcplistener_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(name) * 8 > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "read via {{name}}",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(vm_tcplistener_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(name) * 8 > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "write via {{name}}",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Network usage",
"type": "timeseries"
},
{
@@ -3031,8 +3157,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3048,8 +3173,8 @@
"gridPos": {
"h": 8,
"w": 12,
- "x": 0,
- "y": 51
+ "x": 12,
+ "y": 79
},
"id": 125,
"links": [],
@@ -3086,7 +3211,7 @@
"refId": "A"
}
],
- "title": "CPU spent on GC ($instance)",
+ "title": "CPU spent on GC",
"type": "timeseries"
}
],
@@ -3128,6 +3253,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3141,6 +3267,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3172,7 +3299,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3180,7 +3308,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 16
+ "y": 4
},
"id": 66,
"options": {
@@ -3208,9 +3336,11 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"interval": "",
- "legendFormat": "churn rate",
+ "legendFormat": "{{instance}} - churn rate",
+ "range": true,
"refId": "A"
},
{
@@ -3218,13 +3348,15 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[24h]))",
+ "editorMode": "code",
+ "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[24h])) by (instance)",
"interval": "",
- "legendFormat": "new series over 24h",
+ "legendFormat": "{{instance}} - new series over 24h",
+ "range": true,
"refId": "B"
}
],
- "title": "Churn rate ($instance)",
+ "title": "Churn rate",
"type": "timeseries"
},
{
@@ -3239,6 +3371,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3252,6 +3385,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3284,7 +3418,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3292,7 +3427,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 16
+ "y": 4
},
"id": 68,
"links": [],
@@ -3322,17 +3457,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job\"}[$__rate_interval])\n)",
+ "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job\"}[$__rate_interval])\n) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "slow inserts percentage",
+ "legendFormat": "{{instance}}",
"range": true,
"refId": "A"
}
],
- "title": "Slow inserts ($instance)",
+ "title": "Slow inserts %",
"type": "timeseries"
},
{
@@ -3347,6 +3482,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3360,6 +3496,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3391,7 +3528,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3399,7 +3537,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 24
+ "y": 12
},
"id": 116,
"links": [],
@@ -3428,16 +3566,16 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type) > 0",
+ "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance, type) > 0",
"format": "time_series",
"interval": "5m",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Assisted merges ($instance)",
+ "title": "Assisted merges",
"type": "timeseries"
},
{
@@ -3452,6 +3590,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3465,6 +3604,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3496,7 +3636,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3504,7 +3645,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 24
+ "y": 12
},
"id": 60,
"links": [],
@@ -3533,15 +3674,17 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(rate(vm_slow_queries_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_slow_queries_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "slow queries rate",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Slow queries rate ($instance)",
+ "title": "Slow queries rate",
"type": "timeseries"
},
{
@@ -3556,6 +3699,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3569,6 +3713,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3598,7 +3743,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3606,7 +3752,7 @@
"h": 9,
"w": 12,
"x": 0,
- "y": 32
+ "y": 20
},
"id": 90,
"options": {
@@ -3638,12 +3784,12 @@
"exemplar": false,
"expr": "vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"} / vm_cache_size_max_bytes{job=~\"$job\", instance=~\"$instance\"}",
"interval": "",
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Cache usage % by type ($instance)",
+ "title": "Cache usage % by type",
"type": "timeseries"
},
{
@@ -3658,6 +3804,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3671,6 +3818,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3703,7 +3851,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3711,7 +3860,7 @@
"h": 9,
"w": 12,
"x": 12,
- "y": 32
+ "y": 20
},
"id": 118,
"links": [],
@@ -3747,12 +3896,12 @@
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Cache miss ratio ($instance)",
+ "title": "Cache miss ratio",
"type": "timeseries"
},
{
@@ -3760,6 +3909,7 @@
"type": "prometheus",
"uid": "$ds"
},
+ "description": "Flags explicitly set to non-default values",
"fieldConfig": {
"defaults": {
"color": {
@@ -3784,9 +3934,22 @@
"value": 80
}
]
- }
+ },
+ "unitScale": true
},
"overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Time"
+ },
+ "properties": [
+ {
+ "id": "custom.hidden",
+ "value": true
+ }
+ ]
+ },
{
"matcher": {
"id": "byName",
@@ -3802,7 +3965,7 @@
{
"matcher": {
"id": "byName",
- "options": "Time"
+ "options": "job"
},
"properties": [
{
@@ -3817,26 +3980,22 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 41
+ "y": 29
},
- "id": 120,
+ "id": 126,
"options": {
+ "cellHeight": "sm",
"footer": {
+ "countRows": false,
"fields": "",
"reducer": [
"sum"
],
"show": false
},
- "showHeader": true,
- "sortBy": [
- {
- "desc": true,
- "displayName": "job"
- }
- ]
+ "showHeader": true
},
- "pluginVersion": "9.1.0",
+ "pluginVersion": "10.3.1",
"targets": [
{
"datasource": {
@@ -3854,29 +4013,6 @@
}
],
"title": "Non-default flags",
- "transformations": [
- {
- "id": "groupBy",
- "options": {
- "fields": {
- "instance": {
- "aggregations": []
- },
- "job": {
- "aggregations": []
- },
- "name": {
- "aggregations": [],
- "operation": "groupby"
- },
- "value": {
- "aggregations": [],
- "operation": "groupby"
- }
- }
- }
- }
- ],
"type": "table"
},
{
@@ -3891,6 +4027,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3904,6 +4041,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3936,7 +4074,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3944,7 +4083,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 41
+ "y": 29
},
"id": 74,
"links": [],
@@ -3972,16 +4111,17 @@
"uid": "$ds"
},
"exemplar": false,
- "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "limit exceeded",
+ "legendFormat": "{{instance}} - limit exceeded",
+ "range": true,
"refId": "A"
}
],
- "title": "Labels limit exceeded ($instance)",
+ "title": "Labels limit exceeded",
"type": "timeseries"
}
],
@@ -4023,6 +4163,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4036,6 +4177,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4067,7 +4209,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4075,7 +4218,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 41
+ "y": 5
},
"id": 10,
"links": [],
@@ -4105,16 +4248,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0",
+ "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, type) > 0",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Datapoints ingestion rate ($instance)",
+ "title": "Datapoints ingestion rate",
"type": "timeseries"
},
{
@@ -4129,6 +4272,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4142,6 +4286,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4173,7 +4318,8 @@
}
]
},
- "unit": "s"
+ "unit": "s",
+ "unitScale": true
},
"overrides": []
},
@@ -4181,7 +4327,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 41
+ "y": 5
},
"id": 73,
"links": [],
@@ -4221,7 +4367,7 @@
"refId": "A"
}
],
- "title": "Storage full ETA ($instance)",
+ "title": "Storage full ETA",
"type": "timeseries"
},
{
@@ -4236,6 +4382,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4249,6 +4396,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4280,7 +4428,8 @@
}
]
},
- "unit": "bytes"
+ "unit": "bytes",
+ "unitScale": true
},
"overrides": []
},
@@ -4288,7 +4437,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 49
+ "y": 13
},
"id": 53,
"links": [],
@@ -4318,11 +4467,11 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Used (datapoints)",
+ "legendFormat": "{{instance}} - Used (datapoints)",
"range": true,
"refId": "A"
},
@@ -4335,7 +4484,8 @@
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Free",
+ "legendFormat": "{{instance}} - Free",
+ "range": true,
"refId": "B"
},
{
@@ -4344,17 +4494,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Used (index)",
+ "legendFormat": "{{instance}} - Used (index)",
"range": true,
"refId": "C"
}
],
- "title": "Disk space usage - datapoints ($instance)",
+ "title": "Disk space usage - datapoints",
"type": "timeseries"
},
{
@@ -4369,6 +4519,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4382,6 +4533,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4413,7 +4565,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -4438,7 +4591,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 49
+ "y": 13
},
"id": 34,
"links": [],
@@ -4471,7 +4624,8 @@
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "pending datapoints",
+ "legendFormat": "{{instance}} - pending datapoints",
+ "range": true,
"refId": "A"
},
{
@@ -4483,11 +4637,12 @@
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "pending index entries",
+ "legendFormat": "{{instance}} - pending index entries",
+ "range": true,
"refId": "B"
}
],
- "title": "Pending datapoints ($instance)",
+ "title": "Pending datapoints",
"type": "timeseries"
},
{
@@ -4502,6 +4657,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4515,6 +4671,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4546,7 +4703,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -4571,7 +4729,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 57
+ "y": 21
},
"id": 30,
"links": [],
@@ -4600,11 +4758,13 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "editorMode": "code",
+ "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "total datapoints",
+ "legendFormat": "{{instance}} - total datapoints",
+ "range": true,
"refId": "A"
},
{
@@ -4613,16 +4773,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) \n/ sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)\n/ sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "bytes-per-datapoint",
+ "legendFormat": "{{instance}} - bytes-per-datapoint",
"range": true,
"refId": "B"
}
],
- "title": "Datapoints ($instance)",
+ "title": "Datapoints",
"type": "timeseries"
},
{
@@ -4636,6 +4796,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4649,6 +4810,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4680,7 +4842,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4688,7 +4851,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 57
+ "y": 21
},
"id": 36,
"links": [],
@@ -4717,14 +4880,16 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(vm_parts{job=~\"$job\", instance=~\"$instance\"}) by (type)",
+ "editorMode": "code",
+ "expr": "sum(vm_parts{job=~\"$job\", instance=~\"$instance\"}) by (instance, type)",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "LSM parts ($instance)",
+ "title": "LSM parts",
"type": "timeseries"
},
{
@@ -4739,6 +4904,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4752,6 +4918,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4783,7 +4950,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4791,7 +4959,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 65
+ "y": 29
},
"id": 58,
"links": [],
@@ -4820,17 +4988,17 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job\", instance=~\"$instance\"}[1h])) by (reason)",
+ "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job\", instance=~\"$instance\"}[1h])) by (instance, reason)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{reason}}",
+ "legendFormat": "{{instance}} - {{reason}}",
"range": true,
"refId": "A"
}
],
- "title": "Rows ignored for last 1h ($instance)",
+ "title": "Rows ignored for last 1h",
"type": "timeseries"
},
{
@@ -4845,6 +5013,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4858,6 +5027,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4890,7 +5060,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4898,7 +5069,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 65
+ "y": 29
},
"id": 62,
"options": {
@@ -4924,12 +5095,14 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(vm_active_merges{job=~\"$job\", instance=~\"$instance\"}) by(type)",
- "legendFormat": "{{type}}",
+ "editorMode": "code",
+ "expr": "sum(vm_active_merges{job=~\"$job\", instance=~\"$instance\"}) by(instance, type)",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Active merges ($instance)",
+ "title": "Active merges",
"type": "timeseries"
},
{
@@ -4944,6 +5117,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4957,6 +5131,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4989,7 +5164,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -5013,7 +5189,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 73
+ "y": 37
},
"id": 59,
"links": [],
@@ -5044,7 +5220,7 @@
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "max",
+ "legendFormat": "{{instance}} - max",
"range": true,
"refId": "A"
},
@@ -5053,14 +5229,16 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "current",
+ "legendFormat": "{{instance}} - current",
+ "range": true,
"refId": "B"
}
],
- "title": "Concurrent flushes on disk ($instance)",
+ "title": "Concurrent flushes on disk",
"type": "timeseries"
},
{
@@ -5075,6 +5253,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5088,6 +5267,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5120,7 +5300,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5128,7 +5309,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 73
+ "y": 37
},
"id": 64,
"options": {
@@ -5156,12 +5337,14 @@
"type": "prometheus",
"uid": "$ds"
},
- "expr": "sum(rate(vm_rows_merged_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
- "legendFormat": "{{type}}",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_rows_merged_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance, type)",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Merge speed ($instance)",
+ "title": "Merge speed",
"type": "timeseries"
},
{
@@ -5176,6 +5359,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5189,6 +5373,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5221,7 +5406,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5229,7 +5415,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 81
+ "y": 45
},
"id": 99,
"links": [],
@@ -5268,7 +5454,7 @@
"refId": "A"
}
],
- "title": "Series read per query ($instance)",
+ "title": "Series read per query",
"type": "timeseries"
},
{
@@ -5283,6 +5469,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5296,6 +5483,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5328,7 +5516,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5336,7 +5525,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 81
+ "y": 45
},
"id": 103,
"links": [],
@@ -5375,7 +5564,7 @@
"refId": "A"
}
],
- "title": "Datapoints read per series ($instance)",
+ "title": "Datapoints read per series",
"type": "timeseries"
},
{
@@ -5390,6 +5579,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5403,6 +5593,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5435,7 +5626,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5443,7 +5635,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 89
+ "y": 53
},
"id": 122,
"links": [],
@@ -5482,7 +5674,7 @@
"refId": "A"
}
],
- "title": "Datapoints read per query ($instance)",
+ "title": "Datapoints read per query",
"type": "timeseries"
},
{
@@ -5497,6 +5689,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5510,6 +5703,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5542,7 +5736,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5550,7 +5745,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 89
+ "y": 53
},
"id": 105,
"links": [],
@@ -5589,7 +5784,7 @@
"refId": "A"
}
],
- "title": "Datapoints scanned per query ($instance)",
+ "title": "Datapoints scanned per query",
"type": "timeseries"
}
],
@@ -5674,7 +5869,7 @@
"refId": "VictoriaMetrics-version-Variable-Query"
},
"refresh": 1,
- "regex": "/.*-tags-(v\\d+\\.\\d+\\.\\d+)/",
+ "regex": "/.*-(?:tags|heads)-(.*)-(?:0|dirty)-.*/",
"skipUrlSync": false,
"sort": 2,
"tagValuesQuery": "",
@@ -5683,6 +5878,7 @@
"useTags": false
},
{
+ "allValue": ".*",
"current": {},
"datasource": {
"type": "prometheus",
@@ -5690,8 +5886,8 @@
},
"definition": "label_values(vm_app_version{job=~\"$job\"}, instance)",
"hide": 0,
- "includeAll": false,
- "multi": false,
+ "includeAll": true,
+ "multi": true,
"name": "instance",
"options": [],
"query": {
@@ -5753,4 +5949,4 @@
"uid": "wNf0q_kZk",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vm/victoriametrics-cluster.json b/dashboards/vm/victoriametrics-cluster.json
index ca906f49f..9d24600fd 100644
--- a/dashboards/vm/victoriametrics-cluster.json
+++ b/dashboards/vm/victoriametrics-cluster.json
@@ -7,7 +7,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -169,8 +169,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -181,7 +180,6 @@
"y": 1
},
"id": 131,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -200,7 +198,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -241,8 +239,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -253,7 +250,6 @@
"y": 1
},
"id": 124,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -272,7 +268,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -315,8 +311,7 @@
}
]
},
- "unit": "req/s",
- "unitScale": true
+ "unit": "req/s"
},
"overrides": []
},
@@ -327,7 +322,6 @@
"y": 1
},
"id": 130,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -346,7 +340,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -388,8 +382,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -400,7 +393,6 @@
"y": 1
},
"id": 126,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -419,7 +411,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -461,8 +453,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -473,7 +464,6 @@
"y": 4
},
"id": 34,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -492,7 +482,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -534,8 +524,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -546,7 +535,6 @@
"y": 4
},
"id": 35,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -565,7 +553,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -607,8 +595,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -619,7 +606,6 @@
"y": 4
},
"id": 112,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -638,7 +624,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -679,8 +665,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -691,7 +676,6 @@
"y": 4
},
"id": 128,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -710,7 +694,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -762,8 +746,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -817,7 +800,7 @@
}
]
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -894,8 +877,7 @@
}
]
},
- "unit": "none",
- "unitScale": true
+ "unit": "none"
},
"overrides": []
},
@@ -1019,8 +1001,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1127,8 +1108,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1139,7 +1119,6 @@
"y": 13
},
"id": 6,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1236,8 +1215,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1342,8 +1320,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -1354,7 +1331,6 @@
"y": 21
},
"id": 8,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1442,7 +1418,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1450,8 +1427,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1462,7 +1438,6 @@
"y": 29
},
"id": 52,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1556,7 +1531,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1564,8 +1540,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1576,7 +1551,6 @@
"y": 29
},
"id": 104,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1687,8 +1661,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1802,8 +1775,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1916,8 +1888,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2026,8 +1997,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2167,8 +2137,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2293,8 +2262,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2433,8 +2401,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2541,8 +2508,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2649,8 +2615,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2757,8 +2722,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2866,8 +2830,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4780,6 +4743,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4793,6 +4757,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4816,7 +4781,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -4832,10 +4798,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 14
+ "y": 6
},
"id": 100,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -4885,6 +4850,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4898,6 +4864,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4927,7 +4894,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -4943,10 +4911,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 14
+ "y": 6
},
"id": 113,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -4997,6 +4964,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5010,6 +4978,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5039,7 +5008,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5055,10 +5025,9 @@
"h": 7,
"w": 12,
"x": 0,
- "y": 22
+ "y": 14
},
"id": 151,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5142,6 +5111,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5155,6 +5125,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5184,7 +5155,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5200,10 +5172,9 @@
"h": 7,
"w": 12,
"x": 12,
- "y": 22
+ "y": 14
},
"id": 167,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5275,109 +5246,6 @@
"title": "Memory usage % ($instance)",
"type": "timeseries"
},
- {
- "datasource": {
- "type": "victoriametrics-datasource",
- "uid": "$ds"
- },
- "description": "Value > 0 means vmstorage is in readonly mode.",
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 0,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green"
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "short"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 0,
- "y": 29
- },
- "id": 141,
- "links": [
- {
- "targetBlank": true,
- "title": "Readonly mode",
- "url": "https://docs.victoriametrics.com/cluster-victoriametrics/#readonly-mode"
- }
- ],
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": false
- },
- "tooltip": {
- "mode": "multi",
- "sort": "desc"
- }
- },
- "pluginVersion": "9.1.0",
- "targets": [
- {
- "datasource": {
- "type": "victoriametrics-datasource",
- "uid": "$ds"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "vm_storage_is_read_only{job=~\"$job_storage\", instance=~\"$instance\"} > 0",
- "interval": "",
- "legendFormat": "{{ instance }}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Readonly mode",
- "type": "timeseries"
- },
{
"datasource": {
"type": "victoriametrics-datasource",
@@ -5390,6 +5258,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5403,6 +5272,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5424,7 +5294,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5455,10 +5326,10 @@
"gridPos": {
"h": 8,
"w": 12,
- "x": 12,
- "y": 29
+ "x": 0,
+ "y": 21
},
- "id": 133,
+ "id": 212,
"links": [
{
"targetBlank": true,
@@ -5522,13 +5393,14 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "description": "The number of on-going merges in storage nodes. It is expected to have high numbers for `storage/small` metric.",
+ "description": "Shows the number of concurrently executed read requests, where:\n* `max` - equal to `-search.maxConcurrentRequest` cmd-line flag;\n* `current` - current number of concurrent select requests executed by storage.\n\nEach concurrent select request requires RAM, CPU and disk IO resources during processing. Too many concurrent requests could result into OOM exceptions.\n\nWhen `current` hits `max` constantly, it means storage is overloaded and requires more CPU (see CPU usage) or disks with more IOPS (see disk writes and reads panels in Resource Usage row).\n\nSee more at https://docs.victoriametrics.com/cluster-victoriametrics/#resource-usage-limits",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5542,6 +5414,142 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "max"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#C4162A",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 21
+ },
+ "id": 133,
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true,
+ "sortBy": "Last *",
+ "sortDesc": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "max(\n max_over_time(vm_vmselect_concurrent_requests_current{job=~\"$job_storage\", \n instance=~\"$instance\"}[$__rate_interval])\n)",
+ "interval": "",
+ "legendFormat": "current",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "min(vm_vmselect_concurrent_requests_capacity{job=~\"$job_storage\", instance=~\"$instance\"})",
+ "hide": false,
+ "interval": "",
+ "legendFormat": "max",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Concurrent selects ($instance)",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "description": "The max number of on-going merges across storage nodes.\n The drastic change in number of merges could be a sign of on-going deduplication/downsampling activity.\n It is expected to have high numbers for `storage/small` metric.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5566,7 +5574,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5582,7 +5591,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 37
+ "y": 29
},
"id": 54,
"options": {
@@ -5611,7 +5620,7 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(max_over_time(vm_active_merges{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
+ "expr": "max(max_over_time(vm_active_merges{job=~\"$job_storage\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
"legendFormat": "__auto",
"range": true,
"refId": "A"
@@ -5632,6 +5641,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5645,6 +5655,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5669,7 +5680,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5685,7 +5697,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 37
+ "y": 29
},
"id": 55,
"options": {
@@ -5735,6 +5747,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5748,6 +5761,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5777,7 +5791,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5793,10 +5808,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 45
+ "y": 37
},
"id": 20,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5874,6 +5888,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5887,6 +5902,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5910,7 +5926,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -5926,10 +5943,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 45
+ "y": 37
},
"id": 22,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -5980,6 +5996,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5993,6 +6010,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6022,7 +6040,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
}
]
},
@@ -6034,10 +6053,9 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 53
+ "y": 45
},
"id": 202,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6101,6 +6119,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -6114,6 +6133,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6137,7 +6157,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -6170,10 +6191,9 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 53
+ "y": 45
},
"id": 14,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6238,6 +6258,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -6251,6 +6272,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -6273,7 +6295,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -6300,12 +6323,11 @@
},
"gridPos": {
"h": 8,
- "w": 24,
+ "w": 12,
"x": 0,
- "y": 61
+ "y": 53
},
"id": 206,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -6355,6 +6377,112 @@
],
"title": "Network usage ($instance)",
"type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "description": "Value > 0 means vmstorage is in readonly mode.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 53
+ },
+ "id": 141,
+ "links": [
+ {
+ "targetBlank": true,
+ "title": "Readonly mode",
+ "url": "https://docs.victoriametrics.com/cluster-victoriametrics/#readonly-mode"
+ }
+ ],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "vm_storage_is_read_only{job=~\"$job_storage\", instance=~\"$instance\"} > 0",
+ "interval": "",
+ "legendFormat": "{{ instance }}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Readonly mode",
+ "type": "timeseries"
}
],
"title": "vmstorage ($instance)",
@@ -9682,4 +9810,4 @@
"uid": "oS7Bi_0Wz_vm",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vm/victoriametrics.json b/dashboards/vm/victoriametrics.json
index 166bd255e..88094431c 100644
--- a/dashboards/vm/victoriametrics.json
+++ b/dashboards/vm/victoriametrics.json
@@ -7,7 +7,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -169,7 +169,7 @@
"content": "$version
",
"mode": "markdown"
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -203,8 +203,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -215,7 +214,6 @@
"y": 1
},
"id": 26,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -234,13 +232,14 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
"expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
"format": "time_series",
@@ -275,8 +274,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -287,7 +285,6 @@
"y": 1
},
"id": 107,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -306,7 +303,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -348,8 +345,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -360,7 +356,6 @@
"y": 1
},
"id": 108,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -379,7 +374,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -425,8 +420,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -437,7 +431,6 @@
"y": 1
},
"id": 77,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -456,7 +449,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -500,8 +493,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -529,7 +521,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -538,7 +530,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "vm_app_uptime_seconds{job=~\"$job\", instance=~\"$instance\"}",
+ "expr": "min(vm_app_uptime_seconds{job=~\"$job\", instance=~\"$instance\"})",
"instant": true,
"interval": "",
"legendFormat": "",
@@ -569,8 +561,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -581,7 +572,6 @@
"y": 3
},
"id": 38,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -600,15 +590,16 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}",
+ "expr": "sum(vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"})",
"format": "time_series",
"instant": true,
"interval": "",
@@ -641,8 +632,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -653,7 +643,6 @@
"y": 3
},
"id": 81,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -672,7 +661,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -714,8 +703,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -726,7 +714,6 @@
"y": 3
},
"id": 82,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -745,7 +732,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -754,7 +741,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) / sum(vm_rows{job=~\"$job\", instance=~\"$instance\"})",
+ "expr": "max(sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) / sum(vm_rows{job=~\"$job\", instance=~\"$instance\"}))",
"format": "time_series",
"instant": true,
"interval": "",
@@ -787,8 +774,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -799,7 +785,6 @@
"y": 3
},
"id": 78,
- "links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
@@ -818,7 +803,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -922,8 +907,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -934,7 +918,6 @@
"y": 6
},
"id": 106,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -959,16 +942,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0",
+ "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type, instance) > 0",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Datapoints ingestion rate ($instance)",
+ "title": "Datapoints ingestion rate",
"type": "timeseries"
},
{
@@ -1030,8 +1013,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1042,7 +1024,6 @@
"y": 6
},
"id": 12,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1069,16 +1050,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0",
+ "expr": "sum(rate(vm_http_requests_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path, instance) > 0",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{path}}",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Requests rate ($instance)",
+ "title": "Requests rate",
"type": "timeseries"
},
{
@@ -1140,8 +1121,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1182,14 +1162,16 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"expr": "vm_cache_entries{job=~\"$job\", instance=~\"$instance\", type=\"storage/hour_metric_ids\"}",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "Active time series",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Active time series ($instance)",
+ "title": "Active time series",
"type": "timeseries"
},
{
@@ -1251,8 +1233,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -1263,7 +1244,6 @@
"y": 14
},
"id": 22,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1290,15 +1270,15 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (path) > 0",
+ "expr": "max(vm_request_duration_seconds{job=~\"$job\", instance=~\"$instance\", quantile=\"0.99\"}) by (instance, path) > 0",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Query duration 0.99 quantile ($instance)",
+ "title": "Query duration 0.99 quantile",
"type": "timeseries"
},
{
@@ -1313,6 +1293,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -1326,6 +1307,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1349,7 +1331,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1368,7 +1351,6 @@
"y": 22
},
"id": 35,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1393,16 +1375,16 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (path) > 0",
+ "expr": "sum(rate(vm_http_request_errors_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, path) > 0",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{path}}",
"range": true,
"refId": "A"
}
],
- "title": "Requests error rate ($instance)",
+ "title": "Requests error rate",
"type": "timeseries"
},
{
@@ -1417,6 +1399,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -1430,6 +1413,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1451,7 +1435,8 @@
"mode": "absolute",
"steps": [
{
- "color": "green"
+ "color": "green",
+ "value": null
},
{
"color": "red",
@@ -1494,9 +1479,9 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (level, location) > 0",
+ "expr": "sum(rate(vm_log_messages_total{job=~\"$job\", instance=~\"$instance\", level!=\"info\"}[$__rate_interval])) by (instance, level, location) > 0",
"interval": "5m",
- "legendFormat": "{{level}}: {{location}}",
+ "legendFormat": "{{instance}} - {{level}}: {{location}}",
"range": true,
"refId": "A"
}
@@ -1568,8 +1553,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1586,7 +1570,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 3
+ "y": 31
},
"id": 112,
"links": [],
@@ -1624,7 +1608,7 @@
"refId": "A"
}
],
- "title": "RSS memory % usage ($instance)",
+ "title": "RSS memory % usage",
"type": "timeseries"
},
{
@@ -1677,8 +1661,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1695,7 +1678,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 3
+ "y": 31
},
"id": 44,
"links": [],
@@ -1724,11 +1707,13 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_sys_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "requested from system",
+ "legendFormat": "{{instance}} - requested from system",
+ "range": true,
"refId": "A"
},
{
@@ -1736,11 +1721,13 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_heap_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance) + sum(vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "heap inuse",
+ "legendFormat": "{{instance}} - heap inuse",
+ "range": true,
"refId": "B"
},
{
@@ -1748,11 +1735,13 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(go_memstats_stack_inuse_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "stack inuse",
+ "legendFormat": "{{instance}} - stack inuse",
+ "range": true,
"refId": "C"
},
{
@@ -1760,12 +1749,14 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "resident",
+ "legendFormat": "{{instance}} - resident",
+ "range": true,
"refId": "D"
},
{
@@ -1773,17 +1764,19 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"})",
+ "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "resident anonymous",
+ "legendFormat": "{{instance}} - resident anonymous",
+ "range": true,
"refId": "E"
}
],
- "title": "Memory usage ($instance)",
+ "title": "Memory usage",
"type": "timeseries"
},
{
@@ -1836,8 +1829,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1854,7 +1846,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 11
+ "y": 39
},
"id": 123,
"links": [],
@@ -1892,7 +1884,7 @@
"refId": "A"
}
],
- "title": "RSS anonymous memory % usage ($instance)",
+ "title": "RSS anonymous memory % usage",
"type": "timeseries"
},
{
@@ -1944,8 +1936,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1962,7 +1953,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 11
+ "y": 39
},
"id": 114,
"links": [],
@@ -2002,7 +1993,7 @@
"refId": "A"
}
],
- "title": "CPU % usage ($instance)",
+ "title": "CPU % usage",
"type": "timeseries"
},
{
@@ -2056,8 +2047,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2090,7 +2080,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 19
+ "y": 47
},
"id": 75,
"links": [],
@@ -2130,7 +2120,7 @@
"refId": "A"
}
],
- "title": "Open FDs ($instance)",
+ "title": "Open FDs",
"type": "timeseries"
},
{
@@ -2138,7 +2128,7 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "description": "",
+ "description": "CPU cores used by instance",
"fieldConfig": {
"defaults": {
"color": {
@@ -2183,8 +2173,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2217,7 +2206,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 19
+ "y": 47
},
"id": 57,
"links": [],
@@ -2246,11 +2235,13 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"expr": "rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "CPU cores used",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
},
{
@@ -2258,17 +2249,19 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "editorMode": "code",
"exemplar": false,
- "expr": "process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"}",
+ "expr": "min(process_cpu_cores_available{job=~\"$job\", instance=~\"$instance\"})",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "Limit",
+ "range": true,
"refId": "B"
}
],
- "title": "CPU ($instance)",
+ "title": "CPU",
"type": "timeseries"
},
{
@@ -2321,8 +2314,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2339,7 +2331,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 27
+ "y": 55
},
"id": 47,
"links": [],
@@ -2377,7 +2369,7 @@
"refId": "A"
}
],
- "title": "Goroutines ($instance)",
+ "title": "Goroutines",
"type": "timeseries"
},
{
@@ -2429,8 +2421,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2444,8 +2435,8 @@
"overrides": [
{
"matcher": {
- "id": "byName",
- "options": "read"
+ "id": "byRegexp",
+ "options": "/.*read/"
},
"properties": [
{
@@ -2460,7 +2451,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 27
+ "y": 55
},
"id": 76,
"links": [],
@@ -2489,12 +2480,14 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(process_io_storage_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "read",
+ "legendFormat": "{{instance}} - read",
+ "range": true,
"refId": "A"
},
{
@@ -2502,16 +2495,18 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(process_io_storage_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "write",
+ "legendFormat": "{{instance}} - write",
+ "range": true,
"refId": "B"
}
],
- "title": "Disk writes/reads ($instance)",
+ "title": "Disk writes/reads",
"type": "timeseries"
},
{
@@ -2564,8 +2559,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2582,7 +2576,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 35
+ "y": 63
},
"id": 48,
"links": [],
@@ -2620,7 +2614,7 @@
"refId": "A"
}
],
- "title": "Threads ($instance)",
+ "title": "Threads",
"type": "timeseries"
},
{
@@ -2672,8 +2666,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2687,8 +2680,8 @@
"overrides": [
{
"matcher": {
- "id": "byName",
- "options": "read calls"
+ "id": "byRegexp",
+ "options": "/.*read.*/"
},
"properties": [
{
@@ -2703,7 +2696,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 35
+ "y": 63
},
"id": 124,
"links": [],
@@ -2733,12 +2726,12 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(rate(process_io_read_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "read calls",
+ "legendFormat": "{{instance}} - read calls",
"range": true,
"refId": "A"
},
@@ -2748,17 +2741,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(rate(process_io_write_syscalls_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "write calls",
+ "legendFormat": "{{instance}} - write calls",
"range": true,
"refId": "B"
}
],
- "title": "Disk write/read calls ($instance)",
+ "title": "Disk write/read calls",
"type": "timeseries"
},
{
@@ -2811,8 +2804,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2829,7 +2821,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 43
+ "y": 71
},
"id": 49,
"links": [],
@@ -2868,7 +2860,7 @@
"refId": "A"
}
],
- "title": "TCP connections rate ($instance)",
+ "title": "TCP connections rate",
"type": "timeseries"
},
{
@@ -2921,8 +2913,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2939,7 +2930,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 43
+ "y": 71
},
"id": 37,
"links": [],
@@ -2978,7 +2969,142 @@
"refId": "A"
}
],
- "title": "TCP connections ($instance)",
+ "title": "TCP connections",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "description": "Shows network usage by VM:\n* Writes show traffic sent to clients\n* Reads show traffic received from clients",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "links": [],
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "decbits",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byRegexp",
+ "options": "/read.*/"
+ },
+ "properties": [
+ {
+ "id": "custom.transform",
+ "value": "negative-Y"
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 79
+ },
+ "id": 127,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true,
+ "sortBy": "Last *",
+ "sortDesc": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "9.1.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(vm_tcplistener_read_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(name) * 8 > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "read via {{name}}",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "victoriametrics-datasource",
+ "uid": "$ds"
+ },
+ "editorMode": "code",
+ "expr": "sum(rate(vm_tcplistener_written_bytes_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(name) * 8 > 0",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "write via {{name}}",
+ "range": true,
+ "refId": "B"
+ }
+ ],
+ "title": "Network usage",
"type": "timeseries"
},
{
@@ -3032,8 +3158,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3049,8 +3174,8 @@
"gridPos": {
"h": 8,
"w": 12,
- "x": 0,
- "y": 51
+ "x": 12,
+ "y": 79
},
"id": 125,
"links": [],
@@ -3087,7 +3212,7 @@
"refId": "A"
}
],
- "title": "CPU spent on GC ($instance)",
+ "title": "CPU spent on GC",
"type": "timeseries"
}
],
@@ -3129,6 +3254,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3142,6 +3268,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3173,7 +3300,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3181,7 +3309,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 16
+ "y": 4
},
"id": 66,
"options": {
@@ -3209,9 +3337,11 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"interval": "",
- "legendFormat": "churn rate",
+ "legendFormat": "{{instance}} - churn rate",
+ "range": true,
"refId": "A"
},
{
@@ -3219,13 +3349,15 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[24h]))",
+ "editorMode": "code",
+ "expr": "sum(increase(vm_new_timeseries_created_total{job=~\"$job\", instance=~\"$instance\"}[24h])) by (instance)",
"interval": "",
- "legendFormat": "new series over 24h",
+ "legendFormat": "{{instance}} - new series over 24h",
+ "range": true,
"refId": "B"
}
],
- "title": "Churn rate ($instance)",
+ "title": "Churn rate",
"type": "timeseries"
},
{
@@ -3240,6 +3372,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3253,6 +3386,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3285,7 +3419,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3293,7 +3428,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 16
+ "y": 4
},
"id": 68,
"links": [],
@@ -3323,17 +3458,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job\"}[$__rate_interval])\n)",
+ "expr": "max(\n rate(vm_slow_row_inserts_total{job=~\"$job\"}[$__rate_interval]) \n / rate(vm_rows_added_to_storage_total{job=~\"$job\"}[$__rate_interval])\n) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "slow inserts percentage",
+ "legendFormat": "{{instance}}",
"range": true,
"refId": "A"
}
],
- "title": "Slow inserts ($instance)",
+ "title": "Slow inserts %",
"type": "timeseries"
},
{
@@ -3348,6 +3483,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3361,6 +3497,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3392,7 +3529,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3400,7 +3538,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 24
+ "y": 12
},
"id": 116,
"links": [],
@@ -3429,16 +3567,16 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type) > 0",
+ "expr": "sum(increase(vm_assisted_merges_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance, type) > 0",
"format": "time_series",
"interval": "5m",
"intervalFactor": 1,
- "legendFormat": "__auto",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Assisted merges ($instance)",
+ "title": "Assisted merges",
"type": "timeseries"
},
{
@@ -3453,6 +3591,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3466,6 +3605,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3497,7 +3637,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3505,7 +3646,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 24
+ "y": 12
},
"id": 60,
"links": [],
@@ -3534,15 +3675,17 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(rate(vm_slow_queries_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_slow_queries_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "slow queries rate",
+ "legendFormat": "{{instance}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Slow queries rate ($instance)",
+ "title": "Slow queries rate",
"type": "timeseries"
},
{
@@ -3557,6 +3700,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3570,6 +3714,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3599,7 +3744,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3607,7 +3753,7 @@
"h": 9,
"w": 12,
"x": 0,
- "y": 32
+ "y": 20
},
"id": 90,
"options": {
@@ -3639,12 +3785,12 @@
"exemplar": false,
"expr": "vm_cache_size_bytes{job=~\"$job\", instance=~\"$instance\"} / vm_cache_size_max_bytes{job=~\"$job\", instance=~\"$instance\"}",
"interval": "",
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Cache usage % by type ($instance)",
+ "title": "Cache usage % by type",
"type": "timeseries"
},
{
@@ -3659,6 +3805,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3672,6 +3819,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3704,7 +3852,8 @@
}
]
},
- "unit": "percentunit"
+ "unit": "percentunit",
+ "unitScale": true
},
"overrides": []
},
@@ -3712,7 +3861,7 @@
"h": 9,
"w": 12,
"x": 12,
- "y": 32
+ "y": 20
},
"id": 118,
"links": [],
@@ -3748,12 +3897,12 @@
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Cache miss ratio ($instance)",
+ "title": "Cache miss ratio",
"type": "timeseries"
},
{
@@ -3761,6 +3910,7 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
+ "description": "Flags explicitly set to non-default values",
"fieldConfig": {
"defaults": {
"color": {
@@ -3785,9 +3935,22 @@
"value": 80
}
]
- }
+ },
+ "unitScale": true
},
"overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Time"
+ },
+ "properties": [
+ {
+ "id": "custom.hidden",
+ "value": true
+ }
+ ]
+ },
{
"matcher": {
"id": "byName",
@@ -3803,7 +3966,7 @@
{
"matcher": {
"id": "byName",
- "options": "Time"
+ "options": "job"
},
"properties": [
{
@@ -3818,26 +3981,22 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 41
+ "y": 29
},
- "id": 120,
+ "id": 126,
"options": {
+ "cellHeight": "sm",
"footer": {
+ "countRows": false,
"fields": "",
"reducer": [
"sum"
],
"show": false
},
- "showHeader": true,
- "sortBy": [
- {
- "desc": true,
- "displayName": "job"
- }
- ]
+ "showHeader": true
},
- "pluginVersion": "9.1.0",
+ "pluginVersion": "10.3.1",
"targets": [
{
"datasource": {
@@ -3855,29 +4014,6 @@
}
],
"title": "Non-default flags",
- "transformations": [
- {
- "id": "groupBy",
- "options": {
- "fields": {
- "instance": {
- "aggregations": []
- },
- "job": {
- "aggregations": []
- },
- "name": {
- "aggregations": [],
- "operation": "groupby"
- },
- "value": {
- "aggregations": [],
- "operation": "groupby"
- }
- }
- }
- }
- ],
"type": "table"
},
{
@@ -3892,6 +4028,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -3905,6 +4042,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -3937,7 +4075,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -3945,7 +4084,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 41
+ "y": 29
},
"id": 74,
"links": [],
@@ -3973,16 +4112,17 @@
"uid": "$ds"
},
"exemplar": false,
- "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
+ "expr": "sum(increase(vm_metrics_with_dropped_labels_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "limit exceeded",
+ "legendFormat": "{{instance}} - limit exceeded",
+ "range": true,
"refId": "A"
}
],
- "title": "Labels limit exceeded ($instance)",
+ "title": "Labels limit exceeded",
"type": "timeseries"
}
],
@@ -4024,6 +4164,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4037,6 +4178,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4068,7 +4210,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4076,7 +4219,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 41
+ "y": 5
},
"id": 10,
"links": [],
@@ -4106,16 +4249,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (type) > 0",
+ "expr": "sum(rate(vm_rows_inserted_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by (instance, type) > 0",
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
"range": true,
"refId": "A"
}
],
- "title": "Datapoints ingestion rate ($instance)",
+ "title": "Datapoints ingestion rate",
"type": "timeseries"
},
{
@@ -4130,6 +4273,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4143,6 +4287,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4174,7 +4319,8 @@
}
]
},
- "unit": "s"
+ "unit": "s",
+ "unitScale": true
},
"overrides": []
},
@@ -4182,7 +4328,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 41
+ "y": 5
},
"id": 73,
"links": [],
@@ -4222,7 +4368,7 @@
"refId": "A"
}
],
- "title": "Storage full ETA ($instance)",
+ "title": "Storage full ETA",
"type": "timeseries"
},
{
@@ -4237,6 +4383,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4250,6 +4397,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4281,7 +4429,8 @@
}
]
},
- "unit": "bytes"
+ "unit": "bytes",
+ "unitScale": true
},
"overrides": []
},
@@ -4289,7 +4438,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 49
+ "y": 13
},
"id": 53,
"links": [],
@@ -4319,11 +4468,11 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Used (datapoints)",
+ "legendFormat": "{{instance}} - Used (datapoints)",
"range": true,
"refId": "A"
},
@@ -4336,7 +4485,8 @@
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Free",
+ "legendFormat": "{{instance}} - Free",
+ "range": true,
"refId": "B"
},
{
@@ -4345,17 +4495,17 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\", type=~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "Used (index)",
+ "legendFormat": "{{instance}} - Used (index)",
"range": true,
"refId": "C"
}
],
- "title": "Disk space usage - datapoints ($instance)",
+ "title": "Disk space usage - datapoints",
"type": "timeseries"
},
{
@@ -4370,6 +4520,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4383,6 +4534,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4414,7 +4566,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -4439,7 +4592,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 49
+ "y": 13
},
"id": 34,
"links": [],
@@ -4472,7 +4625,8 @@
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "pending datapoints",
+ "legendFormat": "{{instance}} - pending datapoints",
+ "range": true,
"refId": "A"
},
{
@@ -4484,11 +4638,12 @@
"format": "time_series",
"hide": false,
"intervalFactor": 1,
- "legendFormat": "pending index entries",
+ "legendFormat": "{{instance}} - pending index entries",
+ "range": true,
"refId": "B"
}
],
- "title": "Pending datapoints ($instance)",
+ "title": "Pending datapoints",
"type": "timeseries"
},
{
@@ -4503,6 +4658,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4516,6 +4672,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4547,7 +4704,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -4572,7 +4730,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 57
+ "y": 21
},
"id": 30,
"links": [],
@@ -4601,11 +4759,13 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "editorMode": "code",
+ "expr": "sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "total datapoints",
+ "legendFormat": "{{instance}} - total datapoints",
+ "range": true,
"refId": "A"
},
{
@@ -4614,16 +4774,16 @@
"uid": "$ds"
},
"editorMode": "code",
- "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) \n/ sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"})",
+ "expr": "sum(vm_data_size_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)\n/ sum(vm_rows{job=~\"$job\", instance=~\"$instance\", type!~\"indexdb.*\"}) by (instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "bytes-per-datapoint",
+ "legendFormat": "{{instance}} - bytes-per-datapoint",
"range": true,
"refId": "B"
}
],
- "title": "Datapoints ($instance)",
+ "title": "Datapoints",
"type": "timeseries"
},
{
@@ -4637,6 +4797,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4650,6 +4811,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4681,7 +4843,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4689,7 +4852,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 57
+ "y": 21
},
"id": 36,
"links": [],
@@ -4718,14 +4881,16 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(vm_parts{job=~\"$job\", instance=~\"$instance\"}) by (type)",
+ "editorMode": "code",
+ "expr": "sum(vm_parts{job=~\"$job\", instance=~\"$instance\"}) by (instance, type)",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "{{type}}",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "LSM parts ($instance)",
+ "title": "LSM parts",
"type": "timeseries"
},
{
@@ -4740,6 +4905,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4753,6 +4919,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4784,7 +4951,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4792,7 +4960,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 65
+ "y": 29
},
"id": 58,
"links": [],
@@ -4821,17 +4989,17 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job\", instance=~\"$instance\"}[1h])) by (reason)",
+ "expr": "sum(increase(vm_rows_ignored_total{job=~\"$job\", instance=~\"$instance\"}[1h])) by (instance, reason)",
"format": "time_series",
"hide": false,
"interval": "",
"intervalFactor": 1,
- "legendFormat": "{{reason}}",
+ "legendFormat": "{{instance}} - {{reason}}",
"range": true,
"refId": "A"
}
],
- "title": "Rows ignored for last 1h ($instance)",
+ "title": "Rows ignored for last 1h",
"type": "timeseries"
},
{
@@ -4846,6 +5014,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4859,6 +5028,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4891,7 +5061,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -4899,7 +5070,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 65
+ "y": 29
},
"id": 62,
"options": {
@@ -4925,12 +5096,14 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(vm_active_merges{job=~\"$job\", instance=~\"$instance\"}) by(type)",
- "legendFormat": "{{type}}",
+ "editorMode": "code",
+ "expr": "sum(vm_active_merges{job=~\"$job\", instance=~\"$instance\"}) by(instance, type)",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Active merges ($instance)",
+ "title": "Active merges",
"type": "timeseries"
},
{
@@ -4945,6 +5118,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -4958,6 +5132,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -4990,7 +5165,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": [
{
@@ -5014,7 +5190,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 73
+ "y": 37
},
"id": 59,
"links": [],
@@ -5045,7 +5221,7 @@
"format": "time_series",
"interval": "",
"intervalFactor": 1,
- "legendFormat": "max",
+ "legendFormat": "{{instance}} - max",
"range": true,
"refId": "A"
},
@@ -5054,14 +5230,16 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"})",
+ "editorMode": "code",
+ "expr": "sum(vm_concurrent_insert_current{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
"format": "time_series",
"intervalFactor": 1,
- "legendFormat": "current",
+ "legendFormat": "{{instance}} - current",
+ "range": true,
"refId": "B"
}
],
- "title": "Concurrent flushes on disk ($instance)",
+ "title": "Concurrent flushes on disk",
"type": "timeseries"
},
{
@@ -5076,6 +5254,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5089,6 +5268,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5121,7 +5301,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5129,7 +5310,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 73
+ "y": 37
},
"id": 64,
"options": {
@@ -5157,12 +5338,14 @@
"type": "victoriametrics-datasource",
"uid": "$ds"
},
- "expr": "sum(rate(vm_rows_merged_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(type)",
- "legendFormat": "{{type}}",
+ "editorMode": "code",
+ "expr": "sum(rate(vm_rows_merged_total{job=~\"$job\", instance=~\"$instance\"}[$__rate_interval])) by(instance, type)",
+ "legendFormat": "{{instance}} - {{type}}",
+ "range": true,
"refId": "A"
}
],
- "title": "Merge speed ($instance)",
+ "title": "Merge speed",
"type": "timeseries"
},
{
@@ -5177,6 +5360,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5190,6 +5374,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5222,7 +5407,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5230,7 +5416,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 81
+ "y": 45
},
"id": 99,
"links": [],
@@ -5269,7 +5455,7 @@
"refId": "A"
}
],
- "title": "Series read per query ($instance)",
+ "title": "Series read per query",
"type": "timeseries"
},
{
@@ -5284,6 +5470,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5297,6 +5484,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5329,7 +5517,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5337,7 +5526,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 81
+ "y": 45
},
"id": 103,
"links": [],
@@ -5376,7 +5565,7 @@
"refId": "A"
}
],
- "title": "Datapoints read per series ($instance)",
+ "title": "Datapoints read per series",
"type": "timeseries"
},
{
@@ -5391,6 +5580,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5404,6 +5594,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5436,7 +5627,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5444,7 +5636,7 @@
"h": 8,
"w": 12,
"x": 0,
- "y": 89
+ "y": 53
},
"id": 122,
"links": [],
@@ -5483,7 +5675,7 @@
"refId": "A"
}
],
- "title": "Datapoints read per query ($instance)",
+ "title": "Datapoints read per query",
"type": "timeseries"
},
{
@@ -5498,6 +5690,7 @@
"mode": "palette-classic"
},
"custom": {
+ "axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
@@ -5511,6 +5704,7 @@
"tooltip": false,
"viz": false
},
+ "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -5543,7 +5737,8 @@
}
]
},
- "unit": "short"
+ "unit": "short",
+ "unitScale": true
},
"overrides": []
},
@@ -5551,7 +5746,7 @@
"h": 8,
"w": 12,
"x": 12,
- "y": 89
+ "y": 53
},
"id": 105,
"links": [],
@@ -5590,7 +5785,7 @@
"refId": "A"
}
],
- "title": "Datapoints scanned per query ($instance)",
+ "title": "Datapoints scanned per query",
"type": "timeseries"
}
],
@@ -5675,7 +5870,7 @@
"refId": "VictoriaMetrics-version-Variable-Query"
},
"refresh": 1,
- "regex": "/.*-tags-(v\\d+\\.\\d+\\.\\d+)/",
+ "regex": "/.*-(?:tags|heads)-(.*)-(?:0|dirty)-.*/",
"skipUrlSync": false,
"sort": 2,
"tagValuesQuery": "",
@@ -5684,6 +5879,7 @@
"useTags": false
},
{
+ "allValue": ".*",
"current": {},
"datasource": {
"type": "victoriametrics-datasource",
@@ -5691,8 +5887,8 @@
},
"definition": "label_values(vm_app_version{job=~\"$job\"}, instance)",
"hide": 0,
- "includeAll": false,
- "multi": false,
+ "includeAll": true,
+ "multi": true,
"name": "instance",
"options": [],
"query": {
@@ -5754,4 +5950,4 @@
"uid": "wNf0q_kZk_vm",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vm/vmagent.json b/dashboards/vm/vmagent.json
index 81a0d85c4..cb9aa74d4 100644
--- a/dashboards/vm/vmagent.json
+++ b/dashboards/vm/vmagent.json
@@ -7,7 +7,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -151,8 +151,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -186,7 +185,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -221,8 +220,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -256,7 +254,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -292,8 +290,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -304,7 +301,6 @@
"y": 1
},
"id": 134,
- "links": [],
"options": {
"colorMode": "value",
"graphMode": "none",
@@ -322,7 +318,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -357,8 +353,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -417,7 +412,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -471,8 +466,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -507,7 +501,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -545,8 +539,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -574,7 +567,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -621,8 +614,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -670,7 +662,7 @@
},
"showHeader": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -747,8 +739,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -883,8 +874,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": [
{
@@ -1022,8 +1012,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -1136,8 +1125,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1148,7 +1136,6 @@
"y": 18
},
"id": 107,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1248,8 +1235,7 @@
}
]
},
- "unit": "decbytes",
- "unitScale": true
+ "unit": "decbytes"
},
"overrides": []
},
@@ -1351,8 +1337,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1372,7 +1357,6 @@
"y": 26
},
"id": 15,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1457,8 +1441,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1637,8 +1620,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1754,8 +1736,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1868,8 +1849,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2006,8 +1986,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2139,8 +2118,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2247,8 +2225,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2356,8 +2333,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2464,8 +2440,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3583,8 +3558,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3691,8 +3665,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3797,8 +3770,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3905,8 +3877,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4012,8 +3983,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4118,8 +4088,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4223,8 +4192,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4328,8 +4296,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -6402,4 +6369,4 @@
"uid": "G7Z9GzMGz_vm",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vm/vmalert.json b/dashboards/vm/vmalert.json
index f6a548721..f8c4f0071 100644
--- a/dashboards/vm/vmalert.json
+++ b/dashboards/vm/vmalert.json
@@ -7,7 +7,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -179,8 +179,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -208,7 +207,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -242,8 +241,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -271,7 +269,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -305,8 +303,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -334,7 +331,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -372,8 +369,7 @@
"value": 1
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -401,7 +397,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -439,8 +435,7 @@
"value": 1
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -468,7 +463,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -518,8 +513,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -567,7 +561,7 @@
},
"showHeader": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -644,8 +638,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -775,8 +768,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -881,8 +873,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -987,8 +978,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1091,8 +1081,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1430,8 +1419,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1545,8 +1533,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1660,8 +1647,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1777,8 +1763,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1911,8 +1896,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2020,8 +2004,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2129,8 +2112,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3271,7 +3253,7 @@
"list": [
{
"current": {
- "selected": true,
+ "selected": false,
"text": "VictoriaMetrics",
"value": "P4169E866C3094E38"
},
@@ -3425,4 +3407,4 @@
"uid": "LzldHAVnz_vm",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vmagent.json b/dashboards/vmagent.json
index 8e992a551..7b235eaf7 100644
--- a/dashboards/vmagent.json
+++ b/dashboards/vmagent.json
@@ -6,7 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -150,8 +150,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -185,7 +184,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -220,8 +219,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -255,7 +253,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -291,8 +289,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -303,7 +300,6 @@
"y": 1
},
"id": 134,
- "links": [],
"options": {
"colorMode": "value",
"graphMode": "none",
@@ -321,7 +317,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -356,8 +352,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -416,7 +411,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -470,8 +465,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -506,7 +500,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -544,8 +538,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -573,7 +566,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -620,8 +613,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -669,7 +661,7 @@
},
"showHeader": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -746,8 +738,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -882,8 +873,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": [
{
@@ -1021,8 +1011,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -1135,8 +1124,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1147,7 +1135,6 @@
"y": 18
},
"id": 107,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1247,8 +1234,7 @@
}
]
},
- "unit": "decbytes",
- "unitScale": true
+ "unit": "decbytes"
},
"overrides": []
},
@@ -1350,8 +1336,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1371,7 +1356,6 @@
"y": 26
},
"id": 15,
- "links": [],
"options": {
"legend": {
"calcs": [
@@ -1456,8 +1440,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1636,8 +1619,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1753,8 +1735,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1867,8 +1848,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2005,8 +1985,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2138,8 +2117,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2246,8 +2224,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2355,8 +2332,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2463,8 +2439,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3582,8 +3557,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3690,8 +3664,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3796,8 +3769,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3904,8 +3876,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4011,8 +3982,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4117,8 +4087,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4222,8 +4191,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -4327,8 +4295,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -6401,4 +6368,4 @@
"uid": "G7Z9GzMGz",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/dashboards/vmalert.json b/dashboards/vmalert.json
index 0fca1823d..2fcf86306 100644
--- a/dashboards/vmalert.json
+++ b/dashboards/vmalert.json
@@ -6,7 +6,7 @@
"type": "grafana",
"id": "grafana",
"name": "Grafana",
- "version": "10.3.1"
+ "version": "10.4.2"
},
{
"type": "datasource",
@@ -178,8 +178,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -207,7 +206,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -241,8 +240,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -270,7 +268,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -304,8 +302,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -333,7 +330,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -371,8 +368,7 @@
"value": 1
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -400,7 +396,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -438,8 +434,7 @@
"value": 1
}
]
- },
- "unitScale": true
+ }
},
"overrides": []
},
@@ -467,7 +462,7 @@
"textMode": "auto",
"wideLayout": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -517,8 +512,7 @@
"value": 80
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -566,7 +560,7 @@
},
"showHeader": true
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
@@ -643,8 +637,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -774,8 +767,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -880,8 +872,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -986,8 +977,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1090,8 +1080,7 @@
}
]
},
- "unit": "short",
- "unitScale": true
+ "unit": "short"
},
"overrides": []
},
@@ -1429,8 +1418,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1544,8 +1532,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1659,8 +1646,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1776,8 +1762,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -1910,8 +1895,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2019,8 +2003,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -2128,8 +2111,7 @@
"mode": "absolute",
"steps": [
{
- "color": "green",
- "value": null
+ "color": "green"
},
{
"color": "red",
@@ -3270,7 +3252,7 @@
"list": [
{
"current": {
- "selected": true,
+ "selected": false,
"text": "VictoriaMetrics",
"value": "P4169E866C3094E38"
},
@@ -3424,4 +3406,4 @@
"uid": "LzldHAVnz",
"version": 1,
"weekStart": ""
-}
+}
\ No newline at end of file
diff --git a/deployment/docker/Makefile b/deployment/docker/Makefile
index d9d2de7bd..929166cd3 100644
--- a/deployment/docker/Makefile
+++ b/deployment/docker/Makefile
@@ -5,7 +5,7 @@ DOCKER_NAMESPACE ?= victoriametrics
ROOT_IMAGE ?= alpine:3.19.1
CERTS_IMAGE := alpine:3.19.1
-GO_BUILDER_IMAGE := golang:1.22.2-alpine
+GO_BUILDER_IMAGE := golang:1.22.3-alpine
BUILDER_IMAGE := local/builder:2.0.0-$(shell echo $(GO_BUILDER_IMAGE) | tr :/ __)-1
BASE_IMAGE := local/base:1.1.4-$(shell echo $(ROOT_IMAGE) | tr :/ __)-$(shell echo $(CERTS_IMAGE) | tr :/ __)
DOCKER ?= docker
@@ -102,24 +102,23 @@ run-via-docker: package-via-docker
app-via-docker-goos-goarch:
APP_SUFFIX='-$(GOOS)-$(GOARCH)' \
- DOCKER_OPTS='--env CGO_ENABLED=$(CGO_ENABLED) --env GOOS=$(GOOS) --env GOARCH=$(GOARCH)' \
+ DOCKER_OPTS='--env CGO_ENABLED=$(CGO_ENABLED) --env GOOS=$(GOOS) --env GOARCH=$(GOARCH) $(foreach v,$(EXTRA_ENVS),--env $(v))' \
$(MAKE) app-via-docker
app-via-docker-pure:
APP_SUFFIX='-pure' DOCKER_OPTS='--env CGO_ENABLED=0' $(MAKE) app-via-docker
app-via-docker-linux-amd64:
+ EXTRA_ENVS='CC=/opt/cross-builder/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc' \
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 $(MAKE) app-via-docker-goos-goarch
app-via-docker-linux-arm:
- APP_SUFFIX='-linux-arm' \
- DOCKER_OPTS='--env CGO_ENABLED=0 --env GOOS=linux --env GOARCH=arm --env GOARM=5' \
- $(MAKE) app-via-docker
+ EXTRA_ENVS='GOARM=5' \
+ CGO_ENABLED=0 GOOS=linux GOARCH=arm $(MAKE) app-via-docker-goos-goarch
app-via-docker-linux-arm64:
- APP_SUFFIX='-linux-arm64' \
- DOCKER_OPTS='--env CGO_ENABLED=1 --env GOOS=linux --env GOARCH=arm64 --env CC=/opt/cross-builder/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc' \
- $(MAKE) app-via-docker
+ EXTRA_ENVS='CC=/opt/cross-builder/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc' \
+ CGO_ENABLED=1 GOOS=linux GOARCH=arm64 $(MAKE) app-via-docker-goos-goarch
app-via-docker-linux-ppc64le:
CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le $(MAKE) app-via-docker-goos-goarch
@@ -146,37 +145,28 @@ app-via-docker-windows-amd64:
package-via-docker-goarch:
APP_SUFFIX='-$(GOARCH)' \
- DOCKER_OPTS='--env CGO_ENABLED=$(CGO_ENABLED) --env GOOS=linux --env GOARCH=$(GOARCH)' \
+ DOCKER_OPTS='--env CGO_ENABLED=$(CGO_ENABLED) --env GOOS=linux --env GOARCH=$(GOARCH) $(foreach v,$(EXTRA_ENVS),--env $(v))' \
$(MAKE) package-via-docker
-package-via-docker-goarch-arm64:
- APP_SUFFIX='-arm64' \
- DOCKER_OPTS='--env CGO_ENABLED=1 --env GOOS=linux --env GOARCH=arm64 --env CC=/opt/cross-builder/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc' \
- $(MAKE) package-via-docker
-
-package-via-docker-goarch-cgo:
- CGO_ENABLED=1 $(MAKE) package-via-docker-goarch
-
-package-via-docker-goarch-nocgo:
- CGO_ENABLED=0 $(MAKE) package-via-docker-goarch
-
package-via-docker-pure:
APP_SUFFIX='-pure' DOCKER_OPTS='--env CGO_ENABLED=0' $(MAKE) package-via-docker
package-via-docker-amd64:
- GOARCH=amd64 $(MAKE) package-via-docker-goarch-cgo
+ EXTRA_ENVS='CC=/opt/cross-builder/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc' \
+ GOARCH=amd64 GOARCH=amd64 $(MAKE) package-via-docker-goarch
package-via-docker-arm:
- GOARCH=arm $(MAKE) package-via-docker-goarch-nocgo
+ GOARCH=arm CGO_ENABLED=0 $(MAKE) package-via-docker-goarch
package-via-docker-arm64:
- $(MAKE) package-via-docker-goarch-arm64
+ EXTRA_ENVS='CC=/opt/cross-builder/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc' \
+ CGO_ENABLED=1 GOARCH=arm64 $(MAKE) package-via-docker-goarch
package-via-docker-ppc64le:
- GOARCH=ppc64le $(MAKE) package-via-docker-goarch-nocgo
+ GOARCH=ppc64le CGO_ENABLED=0 $(MAKE) package-via-docker-goarch
package-via-docker-386:
- GOARCH=386 $(MAKE) package-via-docker-goarch-nocgo
+ GOARCH=386 CGO_ENABLED=0 $(MAKE) package-via-docker-goarch
remove-docker-images:
docker image ls --format '{{.ID}}' | xargs docker image rm -f
diff --git a/deployment/docker/alerts.yml b/deployment/docker/alerts.yml
index 13e69abe7..f20122eae 100644
--- a/deployment/docker/alerts.yml
+++ b/deployment/docker/alerts.yml
@@ -43,7 +43,7 @@ groups:
dashboard: "http://localhost:3000/d/wNf0q_kZk?viewPanel=53&var-instance={{ $labels.instance }}"
summary: "Instance {{ $labels.instance }} (job={{ $labels.job }}) will run out of disk space soon"
description: "Disk utilisation on instance {{ $labels.instance }} is more than 80%.\n
- Having less than 20% of free disk space could cripple merges processes and overall performance.
+ Having less than 20% of free disk space could cripple merge processes and overall performance.
Consider to limit the ingestion rate, decrease retention or scale the disk space if possible."
- alert: RequestErrorsToAPI
@@ -129,5 +129,5 @@ groups:
dashboard: "http://localhost:3000/d/wNf0q_kZk?viewPanel=74&var-instance={{ $labels.instance }}"
summary: "Metrics ingested in ({{ $labels.instance }}) are exceeding labels limit"
description: "VictoriaMetrics limits the number of labels per each metric with `-maxLabelsPerTimeseries` command-line flag.\n
- This prevents from ingesting metrics with too many labels. Please verify that `-maxLabelsPerTimeseries` is configured
+ This prevents ingestion of metrics with too many labels. Please verify that `-maxLabelsPerTimeseries` is configured
correctly or that clients which send these metrics aren't misbehaving."
diff --git a/deployment/docker/builder/Dockerfile b/deployment/docker/builder/Dockerfile
index 0efb33b91..20543b7d5 100644
--- a/deployment/docker/builder/Dockerfile
+++ b/deployment/docker/builder/Dockerfile
@@ -3,7 +3,12 @@ FROM $go_builder_image
STOPSIGNAL SIGINT
RUN apk add git gcc musl-dev make wget --no-cache && \
mkdir /opt/cross-builder && \
- wget https://musl.cc/aarch64-linux-musl-cross.tgz -O /opt/cross-builder/aarch64-musl.tgz --no-verbose && \
cd /opt/cross-builder && \
- tar zxf aarch64-musl.tgz -C ./ && \
- rm /opt/cross-builder/aarch64-musl.tgz
+ for arch in aarch64 x86_64; do \
+ wget \
+ https://musl.cc/${arch}-linux-musl-cross.tgz \
+ -O /opt/cross-builder/${arch}-musl.tgz \
+ --no-verbose && \
+ tar zxf ${arch}-musl.tgz -C ./ && \
+ rm /opt/cross-builder/${arch}-musl.tgz; \
+ done
diff --git a/deployment/docker/docker-compose-cluster.yml b/deployment/docker/docker-compose-cluster.yml
index b18021b53..6194de252 100644
--- a/deployment/docker/docker-compose-cluster.yml
+++ b/deployment/docker/docker-compose-cluster.yml
@@ -5,7 +5,7 @@ services:
# And forward them to --remoteWrite.url
vmagent:
container_name: vmagent
- image: victoriametrics/vmagent:v1.100.1
+ image: victoriametrics/vmagent:v1.101.0
depends_on:
- "vminsert"
ports:
@@ -21,7 +21,7 @@ services:
# Grafana instance configured with VictoriaMetrics as datasource
grafana:
container_name: grafana
- image: grafana/grafana:10.3.1
+ image: grafana/grafana:10.4.2
depends_on:
- "vmauth"
ports:
@@ -39,7 +39,7 @@ services:
# where N is number of vmstorages (2 in this case).
vmstorage-1:
container_name: vmstorage-1
- image: victoriametrics/vmstorage:v1.100.1-cluster
+ image: victoriametrics/vmstorage:v1.101.0-cluster
ports:
- 8482
- 8400
@@ -51,7 +51,7 @@ services:
restart: always
vmstorage-2:
container_name: vmstorage-2
- image: victoriametrics/vmstorage:v1.100.1-cluster
+ image: victoriametrics/vmstorage:v1.101.0-cluster
ports:
- 8482
- 8400
@@ -66,7 +66,7 @@ services:
# pre-process them and distributes across configured vmstorage shards.
vminsert:
container_name: vminsert
- image: victoriametrics/vminsert:v1.100.1-cluster
+ image: victoriametrics/vminsert:v1.101.0-cluster
depends_on:
- "vmstorage-1"
- "vmstorage-2"
@@ -81,7 +81,7 @@ services:
# vmselect collects results from configured `--storageNode` shards.
vmselect-1:
container_name: vmselect-1
- image: victoriametrics/vmselect:v1.100.1-cluster
+ image: victoriametrics/vmselect:v1.101.0-cluster
depends_on:
- "vmstorage-1"
- "vmstorage-2"
@@ -94,7 +94,7 @@ services:
restart: always
vmselect-2:
container_name: vmselect-2
- image: victoriametrics/vmselect:v1.100.1-cluster
+ image: victoriametrics/vmselect:v1.101.0-cluster
depends_on:
- "vmstorage-1"
- "vmstorage-2"
@@ -112,7 +112,7 @@ services:
# It can be used as an authentication proxy.
vmauth:
container_name: vmauth
- image: victoriametrics/vmauth:v1.100.1
+ image: victoriametrics/vmauth:v1.101.0
depends_on:
- "vmselect-1"
- "vmselect-2"
@@ -127,7 +127,7 @@ services:
# vmalert executes alerting and recording rules
vmalert:
container_name: vmalert
- image: victoriametrics/vmalert:v1.100.1
+ image: victoriametrics/vmalert:v1.101.0
depends_on:
- "vmauth"
ports:
diff --git a/deployment/docker/docker-compose-victorialogs.yml b/deployment/docker/docker-compose-victorialogs.yml
index 8a38339e3..4dcebb7d6 100644
--- a/deployment/docker/docker-compose-victorialogs.yml
+++ b/deployment/docker/docker-compose-victorialogs.yml
@@ -3,7 +3,7 @@ services:
# Grafana instance configured with VictoriaLogs as datasource
grafana:
container_name: grafana
- image: grafana/grafana:10.3.1
+ image: grafana/grafana:10.4.2
depends_on:
- "victoriametrics"
- "victorialogs"
@@ -58,7 +58,7 @@ services:
# scraping, storing metrics and serve read requests.
victoriametrics:
container_name: victoriametrics
- image: victoriametrics/victoria-metrics:v1.100.1
+ image: victoriametrics/victoria-metrics:v1.101.0
ports:
- 8428:8428
volumes:
diff --git a/deployment/docker/docker-compose.yml b/deployment/docker/docker-compose.yml
index 5b5a32592..e444bd654 100644
--- a/deployment/docker/docker-compose.yml
+++ b/deployment/docker/docker-compose.yml
@@ -5,7 +5,7 @@ services:
# And forward them to --remoteWrite.url
vmagent:
container_name: vmagent
- image: victoriametrics/vmagent:v1.100.1
+ image: victoriametrics/vmagent:v1.101.0
depends_on:
- "victoriametrics"
ports:
@@ -23,7 +23,7 @@ services:
# storing metrics and serve read requests.
victoriametrics:
container_name: victoriametrics
- image: victoriametrics/victoria-metrics:v1.100.1
+ image: victoriametrics/victoria-metrics:v1.101.0
ports:
- 8428:8428
- 8089:8089
@@ -47,7 +47,7 @@ services:
# Grafana instance configured with VictoriaMetrics as datasource
grafana:
container_name: grafana
- image: grafana/grafana:10.3.1
+ image: grafana/grafana:10.4.2
depends_on:
- "victoriametrics"
ports:
@@ -66,7 +66,7 @@ services:
# vmalert executes alerting and recording rules
vmalert:
container_name: vmalert
- image: victoriametrics/vmalert:v1.100.1
+ image: victoriametrics/vmalert:v1.101.0
depends_on:
- "victoriametrics"
- "alertmanager"
diff --git a/deployment/docker/victorialogs/fluentbit-docker/docker-compose.yml b/deployment/docker/victorialogs/fluentbit-docker/docker-compose.yml
index 12c57cfc5..343aa3d10 100644
--- a/deployment/docker/victorialogs/fluentbit-docker/docker-compose.yml
+++ b/deployment/docker/victorialogs/fluentbit-docker/docker-compose.yml
@@ -2,7 +2,7 @@ version: "3"
services:
fluentbit:
- image: cr.fluentbit.io/fluent/fluent-bit:2.1.4
+ image: cr.fluentbit.io/fluent/fluent-bit:3.0.2
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
diff --git a/deployment/docker/vmanomaly/vmanomaly-integration/docker-compose.yml b/deployment/docker/vmanomaly/vmanomaly-integration/docker-compose.yml
index 71bd37212..9a02f7032 100644
--- a/deployment/docker/vmanomaly/vmanomaly-integration/docker-compose.yml
+++ b/deployment/docker/vmanomaly/vmanomaly-integration/docker-compose.yml
@@ -1,7 +1,7 @@
services:
vmagent:
container_name: vmagent
- image: victoriametrics/vmagent:v1.100.1
+ image: victoriametrics/vmagent:v1.101.0
depends_on:
- "victoriametrics"
ports:
@@ -18,7 +18,7 @@ services:
victoriametrics:
container_name: victoriametrics
- image: victoriametrics/victoria-metrics:v1.100.1
+ image: victoriametrics/victoria-metrics:v1.101.0
ports:
- 8428:8428
volumes:
@@ -51,7 +51,7 @@ services:
vmalert:
container_name: vmalert
- image: victoriametrics/vmalert:v1.100.1
+ image: victoriametrics/vmalert:v1.101.0
depends_on:
- "victoriametrics"
ports:
diff --git a/deployment/logs-benchmark/docker-compose-elk.yml b/deployment/logs-benchmark/docker-compose-elk.yml
index 26fb5d9bf..40b02e50e 100644
--- a/deployment/logs-benchmark/docker-compose-elk.yml
+++ b/deployment/logs-benchmark/docker-compose-elk.yml
@@ -18,7 +18,7 @@ services:
- vlogs
generator:
- image: golang:1.22.2-alpine
+ image: golang:1.22.3-alpine
restart: always
working_dir: /go/src/app
volumes:
diff --git a/deployment/logs-benchmark/docker-compose-loki.yml b/deployment/logs-benchmark/docker-compose-loki.yml
index b090641f3..c20a8125c 100644
--- a/deployment/logs-benchmark/docker-compose-loki.yml
+++ b/deployment/logs-benchmark/docker-compose-loki.yml
@@ -2,7 +2,7 @@ version: '3'
services:
generator:
- image: golang:1.22.2-alpine
+ image: golang:1.22.3-alpine
restart: always
working_dir: /go/src/app
volumes:
diff --git a/deployment/logs-benchmark/docker-compose.yml b/deployment/logs-benchmark/docker-compose.yml
index b93ca83fa..ebb781957 100644
--- a/deployment/logs-benchmark/docker-compose.yml
+++ b/deployment/logs-benchmark/docker-compose.yml
@@ -46,7 +46,7 @@ services:
- '--config=/config.yml'
vmsingle:
- image: victoriametrics/victoria-metrics:v1.100.1
+ image: victoriametrics/victoria-metrics:v1.101.0
ports:
- '8428:8428'
command:
diff --git a/deployment/marketplace/digitialocean/one-click-droplet/files/etc/update-motd.d/99-one-click b/deployment/marketplace/digitialocean/one-click-droplet/files/etc/update-motd.d/99-one-click
index bac89dfd4..83a761004 100755
--- a/deployment/marketplace/digitialocean/one-click-droplet/files/etc/update-motd.d/99-one-click
+++ b/deployment/marketplace/digitialocean/one-click-droplet/files/etc/update-motd.d/99-one-click
@@ -19,8 +19,8 @@ On the server:
* VictoriaMetrics is running on ports: 8428, 8089, 4242, 2003 and they are bound to the local interface.
********************************************************************************
- # This image includes v1.100.1 release of VictoriaMetrics.
- # See Release notes https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.100.1
+ # This image includes v1.101.0 release of VictoriaMetrics.
+ # See Release notes https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0
# Welcome to VictoriaMetrics droplet!
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 7ea0e2715..0ec5a1665 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -30,27 +30,56 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
## tip
+* SECURITY: upgrade Go builder from Go1.22.2 to Go1.22.3. See [the list of issues addressed in Go1.22.3](https://github.com/golang/go/issues?q=milestone%3AGo1.22.3+label%3ACherryPickApproved).
+
+* FEATURE: [dashboards/single](https://grafana.com/grafana/dashboards/10229): support selecting of multiple instances on the dashboard. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5869) for details.
+* FEATURE: [dashboards/single](https://grafana.com/grafana/dashboards/10229): properly display version in the Stats row for the custom builds of VictoriaMetrics.
+* FEATURE: [dashboards/single](https://grafana.com/grafana/dashboards/10229): add `Network Usage` panel to `Resource Usage` row.
+* FEATURE: [dashboards/operator](https://grafana.com/grafana/dashboards/17869), [dashboards/backupmanager](https://grafana.com/grafana/dashboards/17798) and [dashboard/tenant-statistic](https://grafana.com/grafana/dashboards/16399): update dashboard to be compatible with Grafana 10+ version.
+* FEATURE: [dashboards/cluster](https://grafana.com/grafana/dashboards/11176): add new panel `Concurrent selects` to `vmstorage` row. The panel will show how many ongoing select queries are processed by vmstorage and should help to identify resource bottlenecks. See panel description for more details.
+* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): add service discovery support for [Vultr](https://www.vultr.com/). See [these docs](https://docs.victoriametrics.com/sd_configs/#vultr_sd_configs) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6041).
+* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): allow configuring `-remoteWrite.disableOnDiskQueue` and `-remoteWrite.dropSamplesOnOverload` cmd-line flags per each `-remoteWrite.url`. See this [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6065). Thanks to @rbizos for implementaion!
+* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): add labels `path` and `url` to metrics `vmagent_remotewrite_push_failures_total` and `vmagent_remotewrite_samples_dropped_total`. Now number of failed pushes and dropped samples can be tracked per `-remoteWrite.url`.
+
+* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix bug that prevents the first query trace from expanding on click event. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6186). The issue was introduced in [v1.100.0](https://docs.victoriametrics.com/changelog/#v11000) release.
+* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent/): prevent potential panic during [stream aggregation](https://docs.victoriametrics.com/stream-aggregation.html) if more than one `--remoteWrite.streamAggr.dedupInterval` is configured. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6205).
+* BUGFIX: [stream aggregation](https://docs.victoriametrics.com/stream-aggregation/): set correct suffix `_prometheus` for aggregation outputs [increase_prometheus](https://docs.victoriametrics.com/stream-aggregation/#increase_prometheus) and [total_prometheus](https://docs.victoriametrics.com/stream-aggregation/#total_prometheus). Before, outputs `total` and `total_prometheus` or `increase` and `increase_prometheus` had the same suffix.
+
+## [v1.101.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0)
+
+Released at 2024-04-26
+
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/metricsql/): support filtering by multiple numeric constants via `q == (C1, ..., CN)` and `q != (C1, ..., CN)` syntax. For example, `status_code == (200, 201, 300)` returns `status_code` metrics with any of `200`, `201` or `300` values, while `status_code != (400, 404, 500)` returns `status_code` metrics with all the values except of `400`, `404` and `500`.
* FEATURE: [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): add support for fault domain awareness to `vmselect`. It can be configured to return full responses if up to `-globalReplicationFactor - 1` fault domains (aka `vmstorage` groups) are unavailable. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6054) and [these docs](https://docs.victoriametrics.com/cluster-victoriametrics/#vmstorage-groups-at-vmselect).
* FEATURE: all VictoriaMetrics [enterprise](https://docs.victoriametrics.com/enterprise/) components: add support for automatic issuing of TLS certificates for HTTPS server at `-httpListenAddr` via [Let's Encrypt service](https://letsencrypt.org/). See [these docs](https://docs.victoriametrics.com/#automatic-issuing-of-tls-certificates) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5949).
+* FEATURE: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/): support disable or log [implicit conversions](https://docs.victoriametrics.com/metricsql/#implicit-query-conversions) for subquery with cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion`. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4338).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/): support data replication additionally to sharding among remote storage systems if `-remoteWrite.shardByURLReplicas=N` command-line flag is set additionally to `-remoteWrite.shardByURL` command-line flag, where `N` is desired replication factor. This allows setting up data replication among failure domains when the replication factor is smaller than the number of failure domains. See [these docs](https://docs.victoriametrics.com/vmagent/#sharding-among-remote-storages) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6054).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/): reduce CPU usage when [sharding among remote storage systems](https://docs.victoriametrics.com/vmagent/#sharding-among-remote-storages) is enabled.
+* FEATURE: [stream aggregation](https://docs.victoriametrics.com/stream-aggregation/): reduce memory usage during stream aggregation if multiple aggregation configs are used for the same set of data.
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent/): support [DNS SRV](https://en.wikipedia.org/wiki/SRV_record) addresses in `-remoteWrite.url` command-line option and in scrape target urls. For example, `-remoteWrite.url=http://srv+victoria-metrics/api/v1/write` automatically resolves the `victoria-metrics` DNS SRV to a list of hostnames with TCP ports and then sends the collected metrics to these TCP addresses. See [these docs](https://docs.victoriametrics.com/vmagent/#srv-urls) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6053).
+* FEATURE: [stream aggregation](https://docs.victoriametrics.com/stream-aggregation/): allow skipping first N aggregation intervals via cmd-line flag `-streamAggr.ignoreFirstIntervals` for [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) or `-remoteWrite.streamAggr.ignoreFirstIntervals` for [vmagent](https://docs.victoriametrics.com/vmagent/). See more details [here](https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start).
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): support automatic discovering and load balancing for TCP addresses behind DNS SRV addresses. These addresses can be put inside `url_prefix` urls in the form `http://srv+addr/path`, where the `addr` is the [DNS SRV](https://en.wikipedia.org/wiki/SRV_record) address, which is automatically resolved to hostnames with TCP ports. See [these docs](https://docs.victoriametrics.com/vmauth/#srv-urls) for details.
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): support specifying client TLS certificates and TLS ServerName for requests to HTTPS backends. See [these docs](https://docs.victoriametrics.com/vmauth/#backend-tls-setup).
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): support regex matching when routing incoming requests based on HTTP [query args](https://en.wikipedia.org/wiki/Query_string) via `src_query_args` option at `url_map`. See [these docs](https://docs.victoriametrics.com/vmauth/#generic-http-proxy-for-different-backends) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6070).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): optimize auto-suggestion performance for metric names when the database contains big number of unique time series.
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): in the Select component, user-entered values are now preserved on blur if they match options in the list.
+* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): auto-suggestion triggers at any cursor position in the query input. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5864).
+* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): update error messages on the Query page for enhanced clarity. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6177).
+* BUGFIX: [downsampling](https://docs.victoriametrics.com/#downsampling): skip unnecessary index lookups if downsampling wasn't set for ENT versions of VictoriaMetrics. Before, users of VictoriaMetrics ENT could have experience elevated CPU usage even if no downsampling was configured. The issue was introduced in [v1.100.0](https://docs.victoriametrics.com/changelog/#v11000).
+* BUGFIX: [downsampling](https://docs.victoriametrics.com/#downsampling): properly populate downsampling metadata for data parts created by VictoriaMetrics ENT versions lower than v1.100.0. The bug could trigger the downsampling actions for parts that were downsampled already. This bug doesn't have any negative effect apart from spending extra CPU resources on the repeated downsampling. The issue was introduced in [v1.100.0](https://docs.victoriametrics.com/changelog/#v11000).
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): supported any status codes from the range 200-299 from alertmanager. Previously, only 200 status code considered a successful action. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6110).
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): avoid blocking `/api/v1/rules`, `/api/v1/alerts`, `/metrics` APIs when alerting rule uses template functions `query`, which could takes a while to execute. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6079).
+* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert/): fix links with anchors in vmalert's UI. Starting from [v1.99.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.99.0) vmalert could ignore anchors pointing to specific rule groups if `search` param was present in URL.
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): don't treat concurrency limit hit as an error of the backend. Previously, hitting the concurrency limit would increment both `vmauth_concurrent_requests_limit_reached_total` and `vmauth_user_request_backend_errors_total` counters. Now, only concurrency limit counter is incremented. Updates [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5565).
## [v1.100.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.100.1)
Released at 2024-04-11
-**Update note 1: When upgrading to this release from [v1.99.0](https://docs.victoriametrics.com/changelog/#v1990) or [v1.100.0](https://docs.victoriametrics.com/changelog/#v11000) it is recommended to reset caches stored on disk according to [these](https://docs.victoriametrics.com/single-server-victoriametrics/#cache-removal) docs.**
+**Update note 1: This release contains the issue which could lead to extra CPU usage of storage component in ENT distribution of VictoriaMetrics. The issue is caused by [downsampling per distinct sets of time series](https://docs.victoriametrics.com/#downsampling) feature introduced in 1.100.0 ENT version. Please, upgrade to [v1.101.0](https://docs.victoriametrics.com/changelog/#v11010) or rollback to [v1.98.0](https://docs.victoriametrics.com/changelog/#v1980) ENT version if you're affected.**
+
+**Update note 2: When upgrading to this release from [v1.99.0](https://docs.victoriametrics.com/changelog/#v1990) or [v1.100.0](https://docs.victoriametrics.com/changelog/#v11000) it is recommended to reset caches stored on disk according to [these](https://docs.victoriametrics.com/single-server-victoriametrics/#cache-removal) docs.**
* FEATURE: [vmbackupmanager](https://docs.victoriametrics.com/vmbackupmanager/): allow specifying custom backup interval via `-backupInterval` command-line flag. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5966).
@@ -61,7 +90,7 @@ Released at 2024-04-11
Released at 2024-04-04
-**This release contains [the issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5959), which can prevent from storing data for new time series under high rate of search queries. Please rollback to [v1.98.0](https://docs.victoriametrics.com/changelog/#v1980) or upgrade to [v1.100.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.100.1).**
+**This release contains [the issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5959), which can prevent from storing data for new time series under high rate of search queries. Please rollback to [v1.98.0](https://docs.victoriametrics.com/changelog/#v1980) or upgrade to [v1.101.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0).**
**Update note 1: the `-datasource.lookback` command-line flag at `vmalert` is no-op starting from this release. This flag will be removed in the future, so please switch to [`eval_delay` option](https://docs.victoriametrics.com/vmalert/#groups). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5155) for more details.**
@@ -119,7 +148,7 @@ Released at 2024-04-04
Released at 2024-03-01
-**This release contains [the issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5959), which can prevent from storing data for new time series under high rate of search queries. Please rollback to [v1.98.0](https://docs.victoriametrics.com/changelog/#v1980) or upgrade to [v1.100.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.100.1).**
+**This release contains [the issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5959), which can prevent from storing data for new time series under high rate of search queries. Please rollback to [v1.98.0](https://docs.victoriametrics.com/changelog/#v1980) or upgrade to [v1.101.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0).**
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/metricsql/): propagate [label filters](https://docs.victoriametrics.com/keyconcepts/#filtering) via all the [label manipulation functions](https://docs.victoriametrics.com/metricsql/#label-manipulation-functions). For example, `label_del(some_metric{job="foo"}, "instance") + other_metric{pod="bar"}` is now transformed to `label_del(some_metric{job="foo",pod="bar"}, "instance") + other_metric{job="foo",pod="bar"}`. This should reduce the amounts of time series processed during query execution.
* FEATURE: [MetricsQL](https://docs.victoriametrics.com/metricsql/): add [count_values_over_time](https://docs.victoriametrics.com/metricsql/#count_values_over_time) function. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5847).
diff --git a/docs/Cluster-VictoriaMetrics.md b/docs/Cluster-VictoriaMetrics.md
index 6ae32aa6b..8e1816367 100644
--- a/docs/Cluster-VictoriaMetrics.md
+++ b/docs/Cluster-VictoriaMetrics.md
@@ -384,7 +384,7 @@ Check practical examples of VictoriaMetrics API [here](https://docs.victoriametr
- `datadog/api/v1/series` - for ingesting data with DataDog submit metrics API v1. See [these docs](https://docs.victoriametrics.com/url-examples/#datadogapiv1series) for details.
- `datadog/api/v2/series` - for ingesting data with [DataDog submit metrics API](https://docs.datadoghq.com/api/latest/metrics/#submit-metrics). See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-datadog-agent) for details.
- `datadog/api/beta/sketches` - for ingesting data with [DataDog lambda extension](https://docs.datadoghq.com/serverless/libraries_integrations/extension/).
- - `influx/write` and `influx/api/v2/write` - for ingesting data with [InfluxDB line protocol](https://docs.influxdata.com/influxdb/v1.7/write_protocols/line_protocol_tutorial/). See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf) for details.
+ - `influx/write` and `influx/api/v2/write` - for ingesting data with [InfluxDB line protocol](https://docs.influxdata.com/influxdb/v1.7/write_protocols/line_protocol_tutorial/). TCP and UDP receiver is disabled by default. It is exposed on a distinct TCP address set via `-influxListenAddr` command-line flag. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf) for details.
- `newrelic/infra/v2/metrics/events/bulk` - for accepting data from [NewRelic infrastructure agent](https://docs.newrelic.com/docs/infrastructure/install-infrastructure-agent). See [these docs](https://docs.victoriametrics.com/#how-to-send-data-from-newrelic-agent) for details.
- `opentsdb/api/put` - for accepting [OpenTSDB HTTP /api/put requests](http://opentsdb.net/docs/build/html/api_http/put.html). This handler is disabled by default. It is exposed on a distinct TCP address set via `-opentsdbHTTPListenAddr` command-line flag. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#sending-opentsdb-data-via-http-apiput-requests) for details.
diff --git a/docs/MetricsQL.md b/docs/MetricsQL.md
index cdfa3039f..fec10e5dc 100644
--- a/docs/MetricsQL.md
+++ b/docs/MetricsQL.md
@@ -2229,6 +2229,7 @@ Any [rollup function](#rollup-functions) for something other than [series select
Nested rollup functions can be implicit thanks to the [implicit query conversions](#implicit-query-conversions).
For example, `delta(sum(m))` is implicitly converted to `delta(sum(default_rollup(m))[1i:1i])`, so it becomes a subquery,
since it contains [default_rollup](#default_rollup) nested into [delta](#delta).
+This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
VictoriaMetrics performs subqueries in the following way:
@@ -2261,4 +2262,5 @@ VictoriaMetrics performs the following implicit conversions for incoming queries
For example, `avg_over_time(rate(http_requests_total[5m])[1h])` is automatically converted to `avg_over_time(rate(http_requests_total[5m])[1h:1i])`.
* If something other than [series selector](https://docs.victoriametrics.com/keyconcepts/#filtering)
is passed to [rollup function](#rollup-functions), then a [subquery](#subqueries) with `1i` lookbehind window and `1i` step is automatically formed.
- For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ For example, `rate(sum(up))` is automatically converted to `rate((sum(default_rollup(up)))[1i:1i])`.
+ This behavior can be disabled or logged via cmd-line flags `-search.disableImplicitConversion` and `-search.logImplicitConversion` since v1.101.0.
diff --git a/docs/README.md b/docs/README.md
index 50c148405..7362bb7c2 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -89,6 +89,7 @@ VictoriaMetrics has the following prominent features:
* [Prometheus exposition format](#how-to-import-data-in-prometheus-exposition-format).
* [InfluxDB line protocol](#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf) over HTTP, TCP and UDP.
* [Graphite plaintext protocol](#how-to-send-data-from-graphite-compatible-agents-such-as-statsd) with [tags](https://graphite.readthedocs.io/en/latest/tags.html#carbon).
+ * [Statsd plaintext protocol](#how-to-send-data-from-statsd-compatible-clients)
* [OpenTSDB put message](#sending-data-via-telnet-put-protocol).
* [HTTP OpenTSDB /api/put requests](#sending-opentsdb-data-via-http-apiput-requests).
* [JSON line format](#how-to-import-data-in-json-line-format).
@@ -704,6 +705,45 @@ The `/api/v1/export` endpoint should return the following response:
{"metric":{"__name__":"measurement_field2","tag1":"value1","tag2":"value2"},"values":[1.23],"timestamps":[1695902762311]}
```
+## How to send data from Statsd-compatible clients
+
+VictoriaMetrics supports extended statsd protocol with tags. Also it does not support sampling and metric types(it will be ignored).
+Enable Statsd receiver in VictoriaMetrics by setting `-statsdListenAddr` command line flag. For instance,
+the following command will enable Statsd receiver in VictoriaMetrics on TCP and UDP port `8125`:
+
+```console
+/path/to/victoria-metrics-prod -statsdListenAddr=:8125
+```
+
+Example for writing data with Statsd plaintext protocol to local VictoriaMetrics using `nc`:
+
+```console
+echo "foo.bar:123|g|#foo:bar" | nc -N localhost 8125
+```
+
+Explicit setting of timestamps is not supported for statsd protocol. Timestamp is set to the current time when VictoriaMetrics or vmagent receives it.
+
+An arbitrary number of lines delimited by `\n` (aka newline char) can be sent in one go.
+After that the data may be read via [/api/v1/export](#how-to-export-data-in-json-line-format) endpoint:
+
+
+
+```console
+curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz'
+```
+
+
+
+The `/api/v1/export` endpoint should return the following response:
+
+```json
+{"metric":{"__name__":"foo.bar.baz","tag1":"value1","tag2":"value2"},"values":[123],"timestamps":[1560277406000]}
+```
+
+Some examples of compatible statsd clients:
+- [statsd-instrument](https://github.com/Shopify/statsd-instrument)
+- [dogstatsd-ruby](https://github.com/DataDog/dogstatsd-ruby)
+- [go-statsd-client](https://github.com/cactus/go-statsd-client)
## How to send data from Graphite-compatible agents such as [StatsD](https://github.com/etsy/statsd)
Enable Graphite receiver in VictoriaMetrics by setting `-graphiteListenAddr` command line flag. For instance,
@@ -3165,6 +3205,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
An optional list of labels to drop from samples before stream de-duplication and aggregation . See https://docs.victoriametrics.com/stream-aggregation/#dropping-unneeded-labels
Supports an array of values separated by comma or specified via multiple flags.
Value can contain comma inside single-quoted or double-quoted string, {}, [] and () braces.
+ -streamAggr.ignoreFirstIntervals int
+ Number of aggregation intervals to skip after the start. Increase this value if you observe incorrect aggregation results after restarts. It could be caused by receiving unordered delayed data from clients pushing data into the database. See https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start
-streamAggr.ignoreOldSamples
Whether to ignore input samples with old timestamps outside the current aggregation interval. See https://docs.victoriametrics.com/stream-aggregation/#ignoring-old-samples
-streamAggr.keepInput
diff --git a/docs/Release-Guide.md b/docs/Release-Guide.md
index f73bf55b3..e19d9b464 100644
--- a/docs/Release-Guide.md
+++ b/docs/Release-Guide.md
@@ -38,11 +38,6 @@ docker buildx create --use --name=qemu
docker buildx inspect --bootstrap
```
-For ARM arch (M1/M2 processors) additionally configure docker with preferred platform:
-```
-export DOCKER_DEFAULT_PLATFORM=linux/amd64
-```
-
By default, docker on MacOS has limited amount of resources (CPU, mem) to use.
Bumping the limits may significantly improve build speed.
diff --git a/docs/Single-server-VictoriaMetrics.md b/docs/Single-server-VictoriaMetrics.md
index f5c474f51..8c1b28346 100644
--- a/docs/Single-server-VictoriaMetrics.md
+++ b/docs/Single-server-VictoriaMetrics.md
@@ -97,6 +97,7 @@ VictoriaMetrics has the following prominent features:
* [Prometheus exposition format](#how-to-import-data-in-prometheus-exposition-format).
* [InfluxDB line protocol](#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf) over HTTP, TCP and UDP.
* [Graphite plaintext protocol](#how-to-send-data-from-graphite-compatible-agents-such-as-statsd) with [tags](https://graphite.readthedocs.io/en/latest/tags.html#carbon).
+ * [Statsd plaintext protocol](#how-to-send-data-from-statsd-compatible-clients)
* [OpenTSDB put message](#sending-data-via-telnet-put-protocol).
* [HTTP OpenTSDB /api/put requests](#sending-opentsdb-data-via-http-apiput-requests).
* [JSON line format](#how-to-import-data-in-json-line-format).
@@ -712,6 +713,45 @@ The `/api/v1/export` endpoint should return the following response:
{"metric":{"__name__":"measurement_field2","tag1":"value1","tag2":"value2"},"values":[1.23],"timestamps":[1695902762311]}
```
+## How to send data from Statsd-compatible clients
+
+VictoriaMetrics supports extended statsd protocol with tags. Also it does not support sampling and metric types(it will be ignored).
+Enable Statsd receiver in VictoriaMetrics by setting `-statsdListenAddr` command line flag. For instance,
+the following command will enable Statsd receiver in VictoriaMetrics on TCP and UDP port `8125`:
+
+```console
+/path/to/victoria-metrics-prod -statsdListenAddr=:8125
+```
+
+Example for writing data with Statsd plaintext protocol to local VictoriaMetrics using `nc`:
+
+```console
+echo "foo.bar:123|g|#foo:bar" | nc -N localhost 8125
+```
+
+Explicit setting of timestamps is not supported for statsd protocol. Timestamp is set to the current time when VictoriaMetrics or vmagent receives it.
+
+An arbitrary number of lines delimited by `\n` (aka newline char) can be sent in one go.
+After that the data may be read via [/api/v1/export](#how-to-export-data-in-json-line-format) endpoint:
+
+
+
+```console
+curl -G 'http://localhost:8428/api/v1/export' -d 'match=foo.bar.baz'
+```
+
+
+
+The `/api/v1/export` endpoint should return the following response:
+
+```json
+{"metric":{"__name__":"foo.bar.baz","tag1":"value1","tag2":"value2"},"values":[123],"timestamps":[1560277406000]}
+```
+
+Some examples of compatible statsd clients:
+- [statsd-instrument](https://github.com/Shopify/statsd-instrument)
+- [dogstatsd-ruby](https://github.com/DataDog/dogstatsd-ruby)
+- [go-statsd-client](https://github.com/cactus/go-statsd-client)
## How to send data from Graphite-compatible agents such as [StatsD](https://github.com/etsy/statsd)
Enable Graphite receiver in VictoriaMetrics by setting `-graphiteListenAddr` command line flag. For instance,
@@ -3173,6 +3213,8 @@ Pass `-help` to VictoriaMetrics in order to see the list of supported command-li
An optional list of labels to drop from samples before stream de-duplication and aggregation . See https://docs.victoriametrics.com/stream-aggregation/#dropping-unneeded-labels
Supports an array of values separated by comma or specified via multiple flags.
Value can contain comma inside single-quoted or double-quoted string, {}, [] and () braces.
+ -streamAggr.ignoreFirstIntervals int
+ Number of aggregation intervals to skip after the start. Increase this value if you observe incorrect aggregation results after restarts. It could be caused by receiving unordered delayed data from clients pushing data into the database. See https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start
-streamAggr.ignoreOldSamples
Whether to ignore input samples with old timestamps outside the current aggregation interval. See https://docs.victoriametrics.com/stream-aggregation/#ignoring-old-samples
-streamAggr.keepInput
diff --git a/docs/operator/CHANGELOG.md b/docs/operator/CHANGELOG.md
index a7d0d10a6..6829ecaa1 100644
--- a/docs/operator/CHANGELOG.md
+++ b/docs/operator/CHANGELOG.md
@@ -16,6 +16,44 @@ aliases:
## Next release
+## [v0.44.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.44.0) - 9 May 2024
+
+- [vmagent](./api.md#vmagent): adds new fields into `streamAggrConfig`: `dedup_interval`, `ignore_old_samples`, `keep_metric_names`, `no_align_flush_to_interval`. It's only possible to use it with v1.100+ version of `vmagent`. See this [issue](https://github.com/VictoriaMetrics/operator/issues/936) for details.
+- [operator](./README.md): use `Patch` for `finalizers` set/unset operations. It must fix possible issues with `CRD` objects mutations. See this [issue](https://github.com/VictoriaMetrics/operator/issues/946) for details.
+- [operator](./README.md): adds `spec.pause` field to `VMAgent`, `VMAlert`, `VMAuth`, `VMCluster`, `VMAlertmanager` and `VMSingle`. It allows to suspend object reconcile by operator. See this [issue](https://github.com/VictoriaMetrics/operator/issues/943) for details. Thanks @just1900
+- [vmagent](./api.md#vmagent): set `status.selector` field. It allows correctly use `VPA` with `vmagent`. See this [issue](https://github.com/VictoriaMetrics/operator/issues/693) for details.
+- [prometheus-converter](./README.md): fixes bug with prometheus-operator ScrapeConfig converter. Only copy `spec` field for it. See this [issue](https://github.com/VictoriaMetrics/operator/issues/942) for details.
+- [vmscrapeconfig](./resources/vmscrapeconfig.md): `authorization` section in sd configs works properly with empty `type` field (default value for this field is `Bearer`).
+- [prometheus-converter](./README.md): fixes owner reference type on VMScrapeConfig objects
+- [vmauth&vmuser](./api.md#vmauth): sync config fields from [upstream](https://docs.victoriametrics.com/vmauth/), e.g., src_query_args, discover_backend_ips.
+
+
+
+## [v0.43.5](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.5) - 26 Apr 2024
+
+- Update VictoriaMetrics image tags to [v1.101.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0).
+
+
+
+## [v0.43.4](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.4) - 25 Apr 2024
+
+- [operator](./README.md): properly set status to `expanding` for `VMCluster` during initial creation. Previously, it was always `operational`.
+- [operator](./README.md): adds more context to `Deployment` and `Statefulset` watch ready functions. Now, it reports state of unhealthy pod. It allows to find issue with it faster.
+
+
+
+## [v0.43.3](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.3) - 23 Apr 2024
+
+- [operator](./README.md): fix conversion from `ServiceMonitor` to `VMServiceScrape`, `bearerTokenSecret` is dropped mistakenly since [v0.43.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.0). See [this issue](https://github.com/VictoriaMetrics/operator/issues/932).
+- [operator](./README.md): fix selector match for config resources like VMUser, VMRule... , before it could be ignored when update resource labels.
+
+
+
+## [v0.43.2](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.2) - 22 Apr 2024
+
+- [vmagent](./api.md#vmagent): fixes bug with `ServiceAccount` not found with `ingestOnlyMode`.
+- [vmagent](./api.md#vmagent): fixes `unknown long flag '--rules-dir'` for prometheus-config-reloader.
+
## [v0.43.1](https://github.com/VictoriaMetrics/operator/releases/tag/v0.43.1) - 18 Apr 2024
diff --git a/docs/operator/api.md b/docs/operator/api.md
index 2a34beb26..46f9aff02 100644
--- a/docs/operator/api.md
+++ b/docs/operator/api.md
@@ -136,11 +136,13 @@ This Document documents the types introduced by the VictoriaMetrics to be consum
* [VMUserList](#vmuserlist)
* [VMUserSpec](#vmuserspec)
* [EmbeddedIngress](#embeddedingress)
+* [URLMapCommon](#urlmapcommon)
+* [UnauthorizedAccessConfigURLMap](#unauthorizedaccessconfigurlmap)
+* [UserConfigOption](#userconfigoption)
* [VMAuth](#vmauth)
* [VMAuthList](#vmauthlist)
* [VMAuthSpec](#vmauthspec)
* [VMAuthStatus](#vmauthstatus)
-* [VMAuthUnauthorizedPath](#vmauthunauthorizedpath)
* [TargetEndpoint](#targetendpoint)
* [VMStaticScrape](#vmstaticscrape)
* [VMStaticScrapeList](#vmstaticscrapelist)
@@ -925,6 +927,7 @@ VMAgentSpec defines the desired state of VMAgent
| useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
| ingestOnlyMode | IngestOnlyMode switches vmagent into unmanaged mode it disables any config generation for scraping Currently it prevents vmagent from managing tls and auth options for remote write | bool | false |
| license | License allows to configure license key to be used for enterprise features. Using license key is supported starting from VictoriaMetrics v1.94.0. See: https://docs.victoriametrics.com/enterprise.html | *[License](#license) | false |
+| paused | Paused If set to true all actions on the underlaying managed objects are not going to be performed, except for delete actions. | bool | false |
[Back to TOC](#table-of-contents)
@@ -951,7 +954,7 @@ ServiceSpec defines additional service for CRD with user-defined params. by defa
| Field | Description | Scheme | Required |
| ----- | ----------- | ------ | -------- |
-| useAsDefault | UseAsDefault applies changes from given service definition to the main object Service Chaning from headless service to clusterIP or loadbalancer may break cross-component communication | bool | false |
+| useAsDefault | UseAsDefault applies changes from given service definition to the main object Service Changing from headless service to clusterIP or loadbalancer may break cross-component communication | bool | false |
| metadata | EmbeddedObjectMetadata defines objectMeta for additional service. | [EmbeddedObjectMetadata](#embeddedobjectmetadata) | false |
| spec | ServiceSpec describes the attributes that a user creates on a service. More info: https://kubernetes.io/docs/concepts/services-networking/service/ | v1.ServiceSpec | true |
@@ -1132,11 +1135,16 @@ StreamAggrRule defines the rule in stream aggregation config
| ----- | ----------- | ------ | -------- |
| match | Match is a label selector (or list of label selectors) for filtering time series for the given selector.\n\nIf the match isn't set, then all the input time series are processed. | StringOrArray | false |
| interval | Interval is the interval between aggregations. | string | true |
-| staleness_interval | StalenessInterval defines an interval after which the series state will be reset if no samples have been sent during it. | string | false |
+| no_align_flush_to_interval | NoAlighFlushToInterval disables aligning of flushes to multiples of Interval. By default flushes are aligned to Interval. | *bool | false |
| flush_on_shutdown | FlushOnShutdown defines whether to flush the aggregation state on process termination or config reload. Is `false` by default. It is not recommended changing this setting, unless unfinished aggregations states are preferred to missing data points. | bool | false |
+| dedup_interval | DedupInterval is an optional interval for deduplication. | string | false |
+| staleness_interval | Staleness interval is interval after which the series state will be reset if no samples have been sent during it. The parameter is only relevant for outputs: total, total_prometheus, increase, increase_prometheus and histogram_bucket. | string | false |
| outputs | Outputs is a list of output aggregate functions to produce.\n\nThe following names are allowed:\n\n- total - aggregates input counters - increase - counts the increase over input counters - count_series - counts the input series - count_samples - counts the input samples - sum_samples - sums the input samples - last - the last biggest sample value - min - the minimum sample value - max - the maximum sample value - avg - the average value across all the samples - stddev - standard deviation across all the samples - stdvar - standard variance across all the samples - histogram_bucket - creates VictoriaMetrics histogram for input samples - quantiles(phi1, ..., phiN) - quantiles' estimation for phi in the range [0..1]\n\nThe output time series will have the following names:\n\n input_name:aggr_<interval>_<output> | []string | true |
+| keep_metric_names | KeepMetricNames instructs to leave metric names as is for the output time series without adding any suffix. | *bool | false |
+| ignore_old_samples | IgnoreOldSamples instructs to ignore samples with old timestamps outside the current aggregation interval. | *bool | false |
| by | By is an optional list of labels for grouping input series.\n\nSee also Without.\n\nIf neither By nor Without are set, then the Outputs are calculated individually per each input time series. | []string | false |
| without | Without is an optional list of labels, which must be excluded when grouping input series.\n\nSee also By.\n\nIf neither By nor Without are set, then the Outputs are calculated individually per each input time series. | []string | false |
+| drop_input_labels | DropInputLabels is an optional list with labels, which must be dropped before further processing of input samples.\n\nLabels are dropped before de-duplication and aggregation. | *[]string | false |
| input_relabel_configs | InputRelabelConfigs is an optional relabeling rules, which are applied on the input before aggregation. | [][RelabelConfig](#relabelconfig) | false |
| output_relabel_configs | OutputRelabelConfigs is an optional relabeling rules, which are applied on the aggregated output before being sent to remote storage. | [][RelabelConfig](#relabelconfig) | false |
@@ -1297,6 +1305,7 @@ VMAlertSpec defines the desired state of VMAlert
| readinessGates | ReadinessGates defines pod readiness gates | []v1.PodReadinessGate | false |
| useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
| license | License allows to configure license key to be used for enterprise features. Using license key is supported starting from VictoriaMetrics v1.94.0. See: https://docs.victoriametrics.com/enterprise.html | *[License](#license) | false |
+| paused | Paused If set to true all actions on the underlaying managed objects are not going to be performed, except for delete actions. | bool | false |
[Back to TOC](#table-of-contents)
@@ -1391,6 +1400,7 @@ VMSingleSpec defines the desired state of VMSingle
| readinessGates | ReadinessGates defines pod readiness gates | []v1.PodReadinessGate | false |
| streamAggrConfig | StreamAggrConfig defines stream aggregation configuration for VMSingle | *[StreamAggrConfig](#streamaggrconfig) | false |
| useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
+| paused | Paused If set to true all actions on the underlaying managed objects are not going to be performed, except for delete actions. | bool | false |
[Back to TOC](#table-of-contents)
@@ -1877,6 +1887,7 @@ VMClusterSpec defines the desired state of VMCluster
| vmselect | | *[VMSelect](#vmselect) | false |
| vminsert | | *[VMInsert](#vminsert) | false |
| vmstorage | | *[VMStorage](#vmstorage) | false |
+| paused | Paused If set to true all actions on the underlaying managed objects are not going to be performed, except for delete actions. | bool | false |
| useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
[Back to TOC](#table-of-contents)
@@ -2160,12 +2171,8 @@ TargetRef describes target for user traffic forwarding. one of target types can
| static | Static - user defined url for traffic forward, for instance http://vmsingle:8429 | *[StaticRef](#staticref) | false |
| paths | Paths - matched path to route. | []string | false |
| hosts | | []string | false |
-| target_path_suffix | QueryParams []string `json:\"queryParams,omitempty\"` TargetPathSuffix allows to add some suffix to the target path It allows to hide tenant configuration from user with crd as ref. it also may contain any url encoded params. | string | false |
-| headers | Headers represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
-| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
-| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries Can be defined per target or at VMUser.spec level e.g. [429,503] | []int | false |
-| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
-| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
+| URLMapCommon | | [URLMapCommon](#urlmapcommon) | false |
+| target_path_suffix | TargetPathSuffix allows to add some suffix to the target path It allows to hide tenant configuration from user with crd as ref. it also may contain any url encoded params. | string | false |
| targetRefBasicAuth | TargetRefBasicAuth allow an target endpoint to authenticate over basic authentication | *[TargetRefBasicAuth](#targetrefbasicauth) | false |
[Back to TOC](#table-of-contents)
@@ -2230,14 +2237,15 @@ VMUserSpec defines the desired state of VMUser
| bearerToken | BearerToken Authorization header value for accessing protected endpoint. | *string | false |
| targetRefs | TargetRefs - reference to endpoints, which user may access. | [][TargetRef](#targetref) | true |
| default_url | DefaultURLs backend url for non-matching paths filter usually used for default backend with error message | []string | false |
+| tlsConfig | | *[TLSConfig](#tlsconfig) | false |
| ip_filters | IPFilters defines per target src ip filters supported only with enterprise version of vmauth https://docs.victoriametrics.com/vmauth.html#ip-filters | [VMUserIPFilters](#vmuseripfilters) | false |
+| discover_backend_ips | DiscoverBackendIPs instructs discovering URLPrefix backend IPs via DNS. | *bool | false |
| headers | Headers represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries e.g. [429,503] | []int | false |
| max_concurrent_requests | MaxConcurrentRequests defines max concurrent requests per user 300 is default value for vmauth | *int | false |
| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
-| tls_insecure_skip_verify | TLSInsecureSkipVerify - whether to skip TLS verification when connecting to backend over HTTPS. See https://docs.victoriametrics.com/vmauth.html#backend-tls-setup | bool | false |
| metric_labels | MetricLabels - additional labels for metrics exported by vmauth for given user. | map[string]string | false |
| disable_secret_creation | DisableSecretCreation skips related secret creation for vmuser | bool | false |
@@ -2261,6 +2269,55 @@ EmbeddedIngress describes ingress configuration options.
[Back to TOC](#table-of-contents)
+## URLMapCommon
+
+URLMapCommon contains common fields for unauthorized user and user in vmuser
+
+| Field | Description | Scheme | Required |
+| ----- | ----------- | ------ | -------- |
+| src_query_args | SrcQueryArgs is an optional list of query args, which must match request URL query args. | []string | false |
+| src_headers | SrcHeaders is an optional list of headers, which must match request headers. | []string | false |
+| discover_backend_ips | DiscoverBackendIPs instructs discovering URLPrefix backend IPs via DNS. | *bool | false |
+| headers | RequestHeaders represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
+| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
+| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries Can be defined per target or at VMUser.spec level e.g. [429,503] | []int | false |
+| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
+| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
+
+[Back to TOC](#table-of-contents)
+
+## UnauthorizedAccessConfigURLMap
+
+
+
+| Field | Description | Scheme | Required |
+| ----- | ----------- | ------ | -------- |
+| src_paths | SrcPaths is an optional list of regular expressions, which must match the request path. | []string | false |
+| src_hosts | SrcHosts is an optional list of regular expressions, which must match the request hostname. | []string | false |
+| url_prefix | UrlPrefix contains backend url prefixes for the proxied request url. | []string | false |
+| URLMapCommon | | [URLMapCommon](#urlmapcommon) | false |
+
+[Back to TOC](#table-of-contents)
+
+## UserConfigOption
+
+
+
+| Field | Description | Scheme | Required |
+| ----- | ----------- | ------ | -------- |
+| default_url | DefaultURLs backend url for non-matching paths filter usually used for default backend with error message | []string | false |
+| tlsConfig | | *[TLSConfig](#tlsconfig) | false |
+| ip_filters | IPFilters defines per target src ip filters supported only with enterprise version of vmauth https://docs.victoriametrics.com/vmauth.html#ip-filters | [VMUserIPFilters](#vmuseripfilters) | false |
+| discover_backend_ips | DiscoverBackendIPs instructs discovering URLPrefix backend IPs via DNS. | *bool | false |
+| headers | Headers represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
+| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
+| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries e.g. [429,503] | []int | false |
+| max_concurrent_requests | MaxConcurrentRequests defines max concurrent requests per user 300 is default value for vmauth | *int | false |
+| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
+| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
+
+[Back to TOC](#table-of-contents)
+
## VMAuth
VMAuth is the Schema for the vmauths API
@@ -2334,10 +2391,21 @@ VMAuthSpec defines the desired state of VMAuth
| nodeSelector | NodeSelector Define which Nodes the Pods are scheduled on. | map[string]string | false |
| terminationGracePeriodSeconds | TerminationGracePeriodSeconds period for container graceful termination | *int64 | false |
| readinessGates | ReadinessGates defines pod readiness gates | []v1.PodReadinessGate | false |
-| unauthorizedAccessConfig | UnauthorizedAccessConfig configures access for un authorized users | [][VMAuthUnauthorizedPath](#vmauthunauthorizedpath) | false |
+| unauthorizedAccessConfig | UnauthorizedAccessConfig configures access for un authorized users | [][UnauthorizedAccessConfigURLMap](#unauthorizedaccessconfigurlmap) | false |
+| default_url | DefaultURLs backend url for non-matching paths filter usually used for default backend with error message | []string | false |
+| tlsConfig | | *[TLSConfig](#tlsconfig) | false |
+| ip_filters | IPFilters defines per target src ip filters supported only with enterprise version of vmauth https://docs.victoriametrics.com/vmauth.html#ip-filters | [VMUserIPFilters](#vmuseripfilters) | false |
+| discover_backend_ips | DiscoverBackendIPs instructs discovering URLPrefix backend IPs via DNS. | *bool | false |
+| headers | Headers represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
+| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
+| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries e.g. [429,503] | []int | false |
+| max_concurrent_requests | MaxConcurrentRequests defines max concurrent requests per user 300 is default value for vmauth | *int | false |
+| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
+| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
| useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
| license | License allows to configure license key to be used for enterprise features. Using license key is supported starting from VictoriaMetrics v1.94.0. See: https://docs.victoriametrics.com/enterprise.html | *[License](#license) | false |
| configSecret | ConfigSecret is the name of a Kubernetes Secret in the same namespace as the VMAuth object, which contains auth configuration for vmauth, configuration must be inside secret key: config.yaml. It must be created and managed manually. If it's defined, configuration for vmauth becomes unmanaged and operator'll not create any related secrets/config-reloaders | string | false |
+| paused | Paused If set to true all actions on the underlaying managed objects are not going to be performed, except for delete actions. | bool | false |
[Back to TOC](#table-of-contents)
@@ -2352,24 +2420,6 @@ VMAuthStatus defines the observed state of VMAuth
[Back to TOC](#table-of-contents)
-## VMAuthUnauthorizedPath
-
-VMAuthUnauthorizedPath defines url_map for unauthorized access
-
-| Field | Description | Scheme | Required |
-| ----- | ----------- | ------ | -------- |
-| src_paths | Paths src request paths | []string | false |
-| url_prefix | URLs defines url_prefix for dst routing | []string | false |
-| ip_filters | IPFilters defines filter for src ip address enterprise only | [VMUserIPFilters](#vmuseripfilters) | false |
-| src_hosts | SrcHosts is the list of regular expressions, which match the request hostname. | []string | false |
-| headers | Headers represent additional http headers, that vmauth uses in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.68.0 version of vmauth | []string | false |
-| response_headers | ResponseHeaders represent additional http headers, that vmauth adds for request response in form of [\"header_key: header_value\"] multiple values for header key: [\"header_key: value1,value2\"] it's available since 1.93.0 version of vmauth | []string | false |
-| retry_status_codes | RetryStatusCodes defines http status codes in numeric format for request retries e.g. [429,503] | []int | false |
-| load_balancing_policy | LoadBalancingPolicy defines load balancing policy to use for backend urls. Supported policies: least_loaded, first_available. See https://docs.victoriametrics.com/vmauth.html#load-balancing for more details (default \"least_loaded\") | *string | false |
-| drop_src_path_prefix_parts | DropSrcPathPrefixParts is the number of `/`-delimited request path prefix parts to drop before proxying the request to backend. See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. | *int | false |
-
-[Back to TOC](#table-of-contents)
-
## TargetEndpoint
TargetEndpoint defines single static target endpoint.
diff --git a/docs/operator/resources/vmauth.md b/docs/operator/resources/vmauth.md
index cac3df05c..6146d454e 100644
--- a/docs/operator/resources/vmauth.md
+++ b/docs/operator/resources/vmauth.md
@@ -33,7 +33,7 @@ The CRD specifies which `VMUser`s should be covered by the deployed `VMAuth` ins
The Operator then generates a configuration based on the included `VMUser`s and updates the `Configmaps` containing
the configuration. It continuously does so for all changes that are made to `VMUser`s or to the `VMAuth` resource itself.
-[VMUser](./vmrule.md) objects generate part of `VMAuth` configuration.
+[VMUser](./vmuser.md) objects generate part of `VMAuth` configuration.
For filtering users `VMAuth` uses selectors `userNamespaceSelector` and `userSelector`.
It allows configuring rules access control across namespaces and different environments.
@@ -101,8 +101,8 @@ metadata:
name: vmauth-unauthorized-example
spec:
unauthorizedAccessConfig:
- - paths: ["/metrics"]
- urls:
+ - src_paths: ["/metrics"]
+ url_prefix:
- http://vmsingle-example.default.svc:8428
```
@@ -245,8 +245,8 @@ spec:
- 5.6.7.8
# allow read vmsingle metrics without authorization for users from internal network
unauthorizedAccessConfig:
- - paths: ["/metrics"]
- urls: ["http://vmsingle-example.default.svc:8428"]
+ - src_paths: ["/metrics"]
+ url_prefix: ["http://vmsingle-example.default.svc:8428"]
ip_filters:
allow_list:
- 192.168.0.0/16
diff --git a/docs/operator/vars.md b/docs/operator/vars.md
index f293cefe3..b36cccee2 100644
--- a/docs/operator/vars.md
+++ b/docs/operator/vars.md
@@ -10,7 +10,7 @@ menu:
# Auto Generated vars for package config
- updated at Thu Apr 18 19:07:23 UTC 2024
+ updated at Thu May 9 16:51:28 UTC 2024
| varible name | variable default value | variable required | variable description |
@@ -20,7 +20,7 @@ menu:
| VM_CUSTOMCONFIGRELOADERIMAGE | victoriametrics/operator:config-reloader-v0.43.0 | false | - |
| VM_PSPAUTOCREATEENABLED | false | false | - |
| VM_VMALERTDEFAULT_IMAGE | victoriametrics/vmalert | false | - |
-| VM_VMALERTDEFAULT_VERSION | v1.100.1 | false | - |
+| VM_VMALERTDEFAULT_VERSION | v1.101.0 | false | - |
| VM_VMALERTDEFAULT_PORT | 8080 | false | - |
| VM_VMALERTDEFAULT_USEDEFAULTRESOURCES | true | false | - |
| VM_VMALERTDEFAULT_RESOURCE_LIMIT_MEM | 500Mi | false | - |
@@ -31,7 +31,7 @@ menu:
| VM_VMALERTDEFAULT_CONFIGRELOADERMEMORY | 25Mi | false | - |
| VM_VMALERTDEFAULT_CONFIGRELOADIMAGE | jimmidyson/configmap-reload:v0.3.0 | false | - |
| VM_VMAGENTDEFAULT_IMAGE | victoriametrics/vmagent | false | - |
-| VM_VMAGENTDEFAULT_VERSION | v1.100.1 | false | - |
+| VM_VMAGENTDEFAULT_VERSION | v1.101.0 | false | - |
| VM_VMAGENTDEFAULT_CONFIGRELOADIMAGE | quay.io/prometheus-operator/prometheus-config-reloader:v0.68.0 | false | - |
| VM_VMAGENTDEFAULT_PORT | 8429 | false | - |
| VM_VMAGENTDEFAULT_USEDEFAULTRESOURCES | true | false | - |
@@ -42,7 +42,7 @@ menu:
| VM_VMAGENTDEFAULT_CONFIGRELOADERCPU | 100m | false | - |
| VM_VMAGENTDEFAULT_CONFIGRELOADERMEMORY | 25Mi | false | - |
| VM_VMSINGLEDEFAULT_IMAGE | victoriametrics/victoria-metrics | false | - |
-| VM_VMSINGLEDEFAULT_VERSION | v1.100.1 | false | - |
+| VM_VMSINGLEDEFAULT_VERSION | v1.101.0 | false | - |
| VM_VMSINGLEDEFAULT_PORT | 8429 | false | - |
| VM_VMSINGLEDEFAULT_USEDEFAULTRESOURCES | true | false | - |
| VM_VMSINGLEDEFAULT_RESOURCE_LIMIT_MEM | 1500Mi | false | - |
@@ -53,14 +53,14 @@ menu:
| VM_VMSINGLEDEFAULT_CONFIGRELOADERMEMORY | 25Mi | false | - |
| VM_VMCLUSTERDEFAULT_USEDEFAULTRESOURCES | true | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_IMAGE | victoriametrics/vmselect | false | - |
-| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_VERSION | v1.100.1-cluster | false | - |
+| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_VERSION | v1.101.0-cluster | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_PORT | 8481 | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_LIMIT_MEM | 1000Mi | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_LIMIT_CPU | 500m | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_REQUEST_MEM | 500Mi | false | - |
| VM_VMCLUSTERDEFAULT_VMSELECTDEFAULT_RESOURCE_REQUEST_CPU | 100m | false | - |
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_IMAGE | victoriametrics/vmstorage | false | - |
-| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VERSION | v1.100.1-cluster | false | - |
+| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VERSION | v1.101.0-cluster | false | - |
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VMINSERTPORT | 8400 | false | - |
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_VMSELECTPORT | 8401 | false | - |
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_PORT | 8482 | false | - |
@@ -69,7 +69,7 @@ menu:
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_RESOURCE_REQUEST_MEM | 500Mi | false | - |
| VM_VMCLUSTERDEFAULT_VMSTORAGEDEFAULT_RESOURCE_REQUEST_CPU | 250m | false | - |
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_IMAGE | victoriametrics/vminsert | false | - |
-| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_VERSION | v1.100.1-cluster | false | - |
+| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_VERSION | v1.101.0-cluster | false | - |
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_PORT | 8480 | false | - |
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_RESOURCE_LIMIT_MEM | 500Mi | false | - |
| VM_VMCLUSTERDEFAULT_VMINSERTDEFAULT_RESOURCE_LIMIT_CPU | 500m | false | - |
@@ -88,7 +88,7 @@ menu:
| VM_VMALERTMANAGER_RESOURCE_REQUEST_CPU | 30m | false | - |
| VM_DISABLESELFSERVICESCRAPECREATION | false | false | - |
| VM_VMBACKUP_IMAGE | victoriametrics/vmbackupmanager | false | - |
-| VM_VMBACKUP_VERSION | v1.100.1-enterprise | false | - |
+| VM_VMBACKUP_VERSION | v1.101.0-enterprise | false | - |
| VM_VMBACKUP_PORT | 8300 | false | - |
| VM_VMBACKUP_USEDEFAULTRESOURCES | true | false | - |
| VM_VMBACKUP_RESOURCE_LIMIT_MEM | 500Mi | false | - |
@@ -97,7 +97,7 @@ menu:
| VM_VMBACKUP_RESOURCE_REQUEST_CPU | 150m | false | - |
| VM_VMBACKUP_LOGLEVEL | INFO | false | - |
| VM_VMAUTHDEFAULT_IMAGE | victoriametrics/vmauth | false | - |
-| VM_VMAUTHDEFAULT_VERSION | v1.100.1 | false | - |
+| VM_VMAUTHDEFAULT_VERSION | v1.101.0 | false | - |
| VM_VMAUTHDEFAULT_CONFIGRELOADIMAGE | quay.io/prometheus-operator/prometheus-config-reloader:v0.68.0 | false | - |
| VM_VMAUTHDEFAULT_PORT | 8427 | false | - |
| VM_VMAUTHDEFAULT_USEDEFAULTRESOURCES | true | false | - |
diff --git a/docs/scrape_config_examples.md b/docs/scrape_config_examples.md
index 26f476b8d..d292722fb 100644
--- a/docs/scrape_config_examples.md
+++ b/docs/scrape_config_examples.md
@@ -250,7 +250,7 @@ scrape_configs:
# If node-exporter containers have another name in your Kubernetes cluster,
# then adjust the regex value accordingly.
#
- - soruce_labels: [__meta_kubernetes_pod_container_name]
+ - source_labels: [__meta_kubernetes_pod_container_name]
regex: node-exporter
action: keep
diff --git a/docs/sd_configs.md b/docs/sd_configs.md
index f2357d020..eda9a4a8c 100644
--- a/docs/sd_configs.md
+++ b/docs/sd_configs.md
@@ -35,6 +35,7 @@ supports the following Prometheus-compatible service discovery options for Prome
* `nomad_sd_configs` is for discovering and scraping targets registered in [HashiCorp Nomad](https://www.nomadproject.io/). See [these docs](#nomad_sd_configs).
* `openstack_sd_configs` is for discovering and scraping OpenStack targets. See [these docs](#openstack_sd_configs).
* `static_configs` is for scraping statically defined targets. See [these docs](#static_configs).
+* `vultr_sd_configs` is for discovering and scraping [Vultr](https://www.vultr.com/) targets. See [these docs](#vultr_sd_configs).
* `yandexcloud_sd_configs` is for discovering and scraping [Yandex Cloud](https://cloud.yandex.com/en/) targets. See [these docs](#yandexcloud_sd_configs).
Note that the `refresh_interval` option isn't supported for these scrape configs. Use the corresponding `-promscrape.*CheckInterval`
@@ -1498,6 +1499,79 @@ scrape_configs:
See [these examples](https://docs.victoriametrics.com/scrape_config_examples/#static-configs) on how to configure scraping for static targets.
+## vultr_sd_configs
+Vultr SD configuration discovers scrape targets from [Vultr](https://www.vultr.com/) Instances.
+
+Configuration example:
+
+```yaml
+scrape_configs:
+- job_name: vultr
+ vultr_sd_configs:
+
+ # bearer_token is a Bearer token to send in every HTTP API request during service discovery (mandatory).
+ # See: https://my.vultr.com/settings/#settingsapi
+ - bearer_token: "..."
+
+ # Vultr provides query arguments to filter instances.
+ # See: https://www.vultr.com/api/#tag/instances
+
+ # label is an optional query arguments to filter instances by label.
+ #
+ # label: "..."
+
+ # main_ip is an optional query arguments to filter instances by main ip address.
+ #
+ # main_ip: "..."
+
+ # region is an optional query arguments to filter instances by region id.
+ #
+ # region: "..."
+
+ # firewall_group_id is an optional query arguments to filter instances by firewall group id.
+ #
+ # firewall_group_id: "..."
+
+ # hostname is an optional query arguments to filter instances by hostname.
+ #
+ # hostname: "..."
+
+ # port is an optional port to scrape metrics from.
+ # By default, port 80 is used.
+ #
+ # port: ...
+
+ # Additional HTTP API client options can be specified here.
+ # See https://docs.victoriametrics.com/sd_configs.html#http-api-client-options
+
+
+```
+
+Each discovered target has an [`__address__`](https://docs.victoriametrics.com/relabeling.html#how-to-modify-scrape-urls-in-targets) label set
+to `:`, where FQDN is discovered instance address and `` is the port from the `vultr_sd_configs` (default port is `80`).
+
+The following meta labels are available on discovered targets during [relabeling](https://docs.victoriametrics.com/vmagent.html#relabeling):
+
+* `__meta_vultr_instance_id`: A unique ID for the VPS Instance.
+* `__meta_vultr_instance_label`: The user-supplied label for this instance.
+* `__meta_vultr_instance_os`: The [Operating System name](https://www.vultr.com/api/#operation/list-os).
+* `__meta_vultr_instance_os_id`: The [Operating System id](https://www.vultr.com/api/#operation/list-os) used by this instance.
+* `__meta_vultr_instance_region`: The [Region id](https://www.vultr.com/api/#operation/list-regions) where the Instance is located.
+* `__meta_vultr_instance_plan`: A unique ID for the Plan.
+* `__meta_vultr_instance_main_ip`: The main IPv4 address.
+* `__meta_vultr_instance_internal_ip`: The internal IP used by this instance, if set. Only relevant when a VPC is attached.
+* `__meta_vultr_instance_main_ipv6`: The main IPv6 network address.
+* `__meta_vultr_instance_hostname`: The hostname for this instance.
+* `__meta_vultr_instance_server_status`: The server health status, which could be `none`, `locked`, `installingbooting`, `ok`.
+* `__meta_vultr_instance_vcpu_count`: Number of vCPUs.
+* `__meta_vultr_instance_ram_mb`: The amount of RAM in MB.
+* `__meta_vultr_instance_allowed_bandwidth_gb`: Monthly bandwidth quota in GB.
+* `__meta_vultr_instance_disk_gb`: The size of the disk in GB.
+* `__meta_vultr_instance_features`: "auto_backups", "ipv6", "ddos_protection".
+* `__meta_vultr_instance_tags`: Tags to apply to the instance.
+
+The list of discovered Vultr targets is refreshed at the interval, which can be configured via `-promscrape.vultrSDCheckInterval` command-line flag, default: 30s.
+
## yandexcloud_sd_configs
[Yandex Cloud](https://cloud.yandex.com/en/) SD configurations allow retrieving scrape targets from accessible folders.
diff --git a/docs/stream-aggregation.md b/docs/stream-aggregation.md
index 5b7027c2f..820ca4eef 100644
--- a/docs/stream-aggregation.md
+++ b/docs/stream-aggregation.md
@@ -19,7 +19,7 @@ The aggregation is applied to all the metrics received via any [supported data i
and/or scraped from [Prometheus-compatible targets](https://docs.victoriametrics.com/#how-to-scrape-prometheus-exporters-such-as-node-exporter)
after applying all the configured [relabeling stages](https://docs.victoriametrics.com/vmagent/#relabeling).
-By default stream aggregation ignores timestamps associated with the input [samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples).
+By default, stream aggregation ignores timestamps associated with the input [samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples).
It expects that the ingested samples have timestamps close to the current time. See [how to ignore old samples](#ignoring-old-samples).
Stream aggregation can be configured via the following command-line flags:
@@ -82,7 +82,7 @@ The online de-duplication uses the same logic as [`-dedup.minScrapeInterval` com
## Ignoring old samples
-By default all the input samples are taken into account during stream aggregation. If samples with old timestamps outside the current [aggregation interval](#stream-aggregation-config)
+By default, all the input samples are taken into account during stream aggregation. If samples with old timestamps outside the current [aggregation interval](#stream-aggregation-config)
must be ignored, then the following options can be used:
- To pass `-remoteWrite.streamAggr.ignoreOldSamples` command-line flag to [vmagent](https://docs.victoriametrics.com/vmagent/)
@@ -92,9 +92,25 @@ must be ignored, then the following options can be used:
- To set `ignore_old_samples: true` option at the particular [aggregation config](#stream-aggregation-config).
This enables ignoring old samples for that particular aggregation config.
+## Ignore aggregation intervals on start
+
+Stream aggregation may yield inaccurate results if it processes incomplete data. This issue can arise when data is
+received from clients that maintain a queue of unsent data, such as Prometheus or vmagent. If the queue isn't fully
+cleared within the aggregation `interval`, only a portion of the time series may be processed, leading to distorted
+calculations. To mitigate this, consider the following options:
+
+- Set `-remoteWrite.streamAggr.ignoreFirstIntervals=` command-line flag to [vmagent](https://docs.victoriametrics.com/vmagent/)
+ or `-streamAggr.ignoreFirstIntervals=` command-line flag to [single-node VictoriaMetrics](https://docs.victoriametrics.com/)
+ to skip first `` [aggregation intervals](#stream-aggregation-config)
+ from persisting to the storage. It is expected that all incomplete or queued data will be processed during
+ specified `` and all subsequent aggregation intervals will produce correct data.
+
+- Set `ignore_first_intervals: ` option individually per [aggregation config](#stream-aggregation-config).
+ This enables ignoring first `` aggregation intervals for that particular aggregation config.
+
## Flush time alignment
-By default the time for aggregated data flush is aligned by the `interval` option specified in [aggregate config](#stream-aggregation-config).
+By default, the time for aggregated data flush is aligned by the `interval` option specified in [aggregate config](#stream-aggregation-config).
For example:
- if `interval: 1m` is set, then the aggregated data is flushed to the storage at the end of every minute
- if `interval: 1h` is set, then the aggregated data is flushed to the storage at the end of every hour
@@ -117,7 +133,7 @@ Stream aggregation can be used in the following cases:
### Statsd alternative
-Stream aggregation can be used as [statsd](https://github.com/statsd/statsd) alternative in the following cases:
+Stream aggregation can be used as [statsd](https://github.com/statsd/statsd) drop-in replacement in the following cases:
* [Counting input samples](#counting-input-samples)
* [Summing input metrics](#summing-input-metrics)
@@ -125,9 +141,6 @@ Stream aggregation can be used as [statsd](https://github.com/statsd/statsd) alt
* [Histograms over input metrics](#histograms-over-input-metrics)
* [Aggregating histograms](#aggregating-histograms)
-Currently, streaming aggregation is available only for [supported data ingestion protocols](https://docs.victoriametrics.com/#how-to-import-time-series-data)
-and not available for [Statsd metrics format](https://github.com/statsd/statsd/blob/master/docs/metric_types.md).
-
### Recording rules alternative
Sometimes [alerting queries](https://docs.victoriametrics.com/vmalert/#alerting-rules) may require non-trivial amounts of CPU, RAM,
@@ -582,9 +595,6 @@ some_counter:5m_increase / 5m
This is similar to `rate(some_counter[5m])`.
-Please note, opposite to [rate](https://docs.victoriametrics.com/metricsql/#rate), `increase` aggregations can be
-combined safely afterwards. This is helpful when the aggregation is calculated by more than one vmagent.
-
Aggregating irregular and sporadic metrics (received from [Lambdas](https://aws.amazon.com/lambda/)
or [Cloud Functions](https://cloud.google.com/functions)) can be controlled via [staleness_interval](#staleness) option.
@@ -875,7 +885,7 @@ at [single-node VictoriaMetrics](https://docs.victoriametrics.com/single-server-
# Samples are de-duplicated on a per-series basis. See https://docs.victoriametrics.com/keyconcepts/#time-series
# and https://docs.victoriametrics.com/#deduplication
# The deduplication is performed after input_relabel_configs relabeling is applied.
- # By default the deduplication is disabled unless -remoteWrite.streamAggr.dedupInterval or -streamAggr.dedupInterval
+ # By default, the deduplication is disabled unless -remoteWrite.streamAggr.dedupInterval or -streamAggr.dedupInterval
# command-line flags are set.
#
# dedup_interval: 30s
@@ -892,7 +902,7 @@ at [single-node VictoriaMetrics](https://docs.victoriametrics.com/single-server-
# staleness_interval: 2m
# no_align_flush_to_interval disables aligning of flush times for the aggregated data to multiples of interval.
- # By default flush times for the aggregated data is aligned to multiples of interval.
+ # By default, flush times for the aggregated data is aligned to multiples of interval.
# For example:
# - if `interval: 1m` is set, then flushes happen at the end of every minute,
# - if `interval: 1h` is set, then flushes happen at the end of every hour
@@ -922,16 +932,23 @@ at [single-node VictoriaMetrics](https://docs.victoriametrics.com/single-server-
# keep_metric_names instructs keeping the original metric names for the aggregated samples.
# This option can be set only if outputs list contains only a single output.
- # By default a special suffix is added to original metric names in the aggregated samples.
+ # By default, a special suffix is added to original metric names in the aggregated samples.
# See https://docs.victoriametrics.com/stream-aggregation/#output-metric-names
#
# keep_metric_names: false
# ignore_old_samples instructs ignoring input samples with old timestamps outside the current aggregation interval.
+ # See https://docs.victoriametrics.com/stream-aggregation/#ignoring-old-samples
# See also -streamAggr.ignoreOldSamples command-line flag.
#
# ignore_old_samples: false
+ # ignore_first_intervals instructs ignoring first N aggregation intervals after process start.
+ # See https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start
+ # See also -remoteWrite.streamAggr.ignoreFirstIntervals or -streamAggr.ignoreFirstIntervals
+ #
+ # ignore_first_intervals: false
+
# drop_input_labels instructs dropping the given labels from input samples.
# The labels' dropping is performed before input_relabel_configs are applied.
# This also means that the labels are dropped before de-duplication ( https://docs.victoriametrics.com/stream-aggregation/#deduplication )
@@ -1004,7 +1021,7 @@ These issues can be be fixed in the following ways:
- By increasing the `interval` option at [stream aggregation config](#stream-aggregation-config), so it covers the expected
delays in data ingestion pipelines.
- By specifying the `staleness_interval` option at [stream aggregation config](#stream-aggregation-config), so it covers the expected
- delays in data ingestion pipelines. By default the `staleness_interval` equals to `2 x interval`.
+ delays in data ingestion pipelines. By default, the `staleness_interval` equals to `2 x interval`.
### High resource usage
diff --git a/docs/vmagent.md b/docs/vmagent.md
index ecc2f0e07..5c77e4f35 100644
--- a/docs/vmagent.md
+++ b/docs/vmagent.md
@@ -107,6 +107,7 @@ additionally to pull-based Prometheus-compatible targets' scraping:
* DataDog "submit metrics" API. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-datadog-agent).
* InfluxDB line protocol via `http://:8429/write`. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf).
* Graphite plaintext protocol if `-graphiteListenAddr` command-line flag is set. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-graphite-compatible-agents-such-as-statsd).
+* Statsd plaintext protocol if `-statsdListenAddr` command-line flag is set. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-statsd-compatible-clients).
* OpenTelemetry http API. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#sending-data-via-opentelemetry).
* NewRelic API. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-newrelic-agent).
* OpenTSDB telnet and http protocols if `-opentsdbListenAddr` command-line flag is set. See [these docs](https://docs.victoriametrics.com/single-server-victoriametrics/#how-to-send-data-from-opentsdb-compatible-agents).
@@ -1186,7 +1187,7 @@ If you have suggestions for improvements or have found a bug - please open an is
with `-remoteWrite.maxDiskUsagePerURL` command-line flag.
If you don't want to send all the buffered data from the directory to remote storage then simply stop `vmagent` and delete the directory.
-* If `vmagent` runs on a host with slow persistent storage, which cannot keep up with the volume of processed samples, then is is possible to disable
+* If `vmagent` runs on a host with slow persistent storage, which cannot keep up with the volume of processed samples, then is possible to disable
the persistent storage with `-remoteWrite.disableOnDiskQueue` command-line flag. See [these docs](#disabling-on-disk-persistence) for more details.
* By default `vmagent` masks `-remoteWrite.url` with `secret-url` values in logs and at `/metrics` page because
@@ -1707,6 +1708,10 @@ See the docs at https://docs.victoriametrics.com/vmagent/ .
Whether to use proxy protocol for connections accepted at -graphiteListenAddr . See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
-graphiteTrimTimestamp duration
Trim timestamps for Graphite data to this duration. Minimum practical duration is 1s. Higher duration (i.e. 1m) may be used for reducing disk space usage for timestamp data (default 1s)
+ -statsdListenAddr string
+ TCP and UDP address to listen for Statsd plaintext data. Usually :8125 must be set. Doesn't work if empty. See also -statsdListenAddr.useProxyProtocol
+ -statsdListenAddr.useProxyProtocol
+ Whether to use proxy protocol for connections accepted at -statsdListenAddr . See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
-http.connTimeout duration
Incoming connections to -httpListenAddr are closed after the configured timeout. This may help evenly spreading load among a cluster of services behind TCP-level load balancer. Zero value disables closing of incoming connections (default 2m0s)
-http.disableResponseCompression
@@ -1977,6 +1982,8 @@ See the docs at https://docs.victoriametrics.com/vmagent/ .
Whether to suppress scrape errors logging. The last error for each target is always available at '/targets' page even if scrape errors logging is suppressed. See also -promscrape.suppressScrapeErrorsDelay
-promscrape.suppressScrapeErrorsDelay duration
The delay for suppressing repeated scrape errors logging per each scrape targets. This may be used for reducing the number of log lines related to scrape errors. See also -promscrape.suppressScrapeErrors
+ -promscrape.vultrSDCheckInterval duration
+ Interval for checking for changes in Vultr. This works only if vultr_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs.html#vultr_sd_configs for details (default 30s)
-promscrape.yandexcloudSDCheckInterval duration
Interval for checking for changes in Yandex Cloud API. This works only if yandexcloud_sd_configs is configured in '-promscrape.config' file. See https://docs.victoriametrics.com/sd_configs/#yandexcloud_sd_configs for details (default 30s)
-pushmetrics.disableCompression
@@ -2050,10 +2057,14 @@ See the docs at https://docs.victoriametrics.com/vmagent/ .
Optional path to bearer token file to use for the corresponding -remoteWrite.url. The token is re-read from the file every second
Supports an array of values separated by comma or specified via multiple flags.
Value can contain comma inside single-quoted or double-quoted string, {}, [] and () braces.
- -remoteWrite.disableOnDiskQueue
- Whether to disable storing pending data to -remoteWrite.tmpDataPath when the configured remote storage systems cannot keep up with the data ingestion rate. See https://docs.victoriametrics.com/vmagent/#disabling-on-disk-persistence .See also -remoteWrite.dropSamplesOnOverload
- -remoteWrite.dropSamplesOnOverload
- Whether to drop samples when -remoteWrite.disableOnDiskQueue is set and if the samples cannot be pushed into the configured remote storage systems in a timely manner. See https://docs.victoriametrics.com/vmagent/#disabling-on-disk-persistence
+ -remoteWrite.disableOnDiskQueue array
+ Whether to disable storing pending data to -remoteWrite.tmpDataPath when the configured remote storage systems cannot keep up with the data ingestion rate. See https://docs.victoriametrics.com/vmagent#disabling-on-disk-persistence .See also -remoteWrite.dropSamplesOnOverload
+ Supports array of values separated by comma or specified via multiple flags.
+ Empty values are set to false.
+ -remoteWrite.dropSamplesOnOverload array
+ Whether to drop samples when -remoteWrite.disableOnDiskQueue is set and if the samples cannot be pushed into the configured remote storage systems in a timely manner. See https://docs.victoriametrics.com/vmagent#disabling-on-disk-persistence
+ Supports array of values separated by comma or specified via multiple flags.
+ Empty values are set to false.
-remoteWrite.flushInterval duration
Interval for flushing the data to remote storage. This option takes effect only when less than 10K data points per second are pushed to -remoteWrite.url (default 1s)
-remoteWrite.forcePromProto array
@@ -2166,6 +2177,8 @@ See the docs at https://docs.victoriametrics.com/vmagent/ .
Whether to drop all the input samples after the aggregation with -remoteWrite.streamAggr.config. By default, only aggregates samples are dropped, while the remaining samples are written to the corresponding -remoteWrite.url . See also -remoteWrite.streamAggr.keepInput and https://docs.victoriametrics.com/stream-aggregation/
Supports array of values separated by comma or specified via multiple flags.
Empty values are set to false.
+ -remoteWrite.streamAggr.ignoreFirstIntervals int
+ Number of aggregation intervals to skip after the start. Increase this value if you observe incorrect aggregation results after vmagent restarts. It could be caused by receiving unordered delayed data from clients pushing data into the vmagent. See https://docs.victoriametrics.com/stream-aggregation/#ignore-aggregation-intervals-on-start
-remoteWrite.streamAggr.ignoreOldSamples array
Whether to ignore input samples with old timestamps outside the current aggregation interval for the corresponding -remoteWrite.streamAggr.config . See https://docs.victoriametrics.com/stream-aggregation/#ignoring-old-samples
Supports array of values separated by comma or specified via multiple flags.
diff --git a/docs/vmalert.md b/docs/vmalert.md
index 1534ee835..e8c79b264 100644
--- a/docs/vmalert.md
+++ b/docs/vmalert.md
@@ -902,6 +902,25 @@ max(vmalert_alerting_rules_last_evaluation_series_fetched) by(group, alertname)
See more details [here](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4039).
This feature is available only if vmalert is using VictoriaMetrics v1.90 or higher as a datasource.
+### Series with the same labelset
+
+vmalert can produce the following error message:
+```
+result contains metrics with the same labelset during evaluation
+```
+
+The error means there is a collision between [time series](https://docs.victoriametrics.com/keyConcepts.html#time-series)
+during evaluation.
+
+For example, a rule with `expr: {__name__=~"vmalert_alerts_.*"} > 0` returns two distinct time series in response:
+```
+{__name__="vmalert_alerts_pending",job="vmalert",alertname="HostContextSwitching"} 12
+{__name__="vmalert_alerts_firing",job="vmalert",alertname="HostContextSwitching"} 0
+```
+
+As label `__name__` will be dropped during evaluation, leads to duplicated time series.
+To fix this, one could use function like [label_replace](https://docs.victoriametrics.com/metricsql/#label_replace) to preserve the distinct labelset.
+
## mTLS protection
By default `vmalert` accepts http requests at `8880` port (this port can be changed via `-httpListenAddr` command-line flags),
@@ -1362,14 +1381,11 @@ The shortlist of configuration flags is the following:
-rule="http:///path/to/rules". HTTP URL to a page with alerting rules.
-rule="dir/*.yaml" -rule="/*.yaml" -rule="gcs://vmalert-rules/tenant_%{TENANT_ID}/prod".
-rule="dir/**/*.yaml". Includes all the .yaml files in "dir" subfolders recursively.
- Rule files may contain %{ENV_VAR} placeholders, which are substituted by the corresponding env vars.
-
+ Rule files may contain %{ENV_VAR} placeholders, which are substituted by the corresponding env vars.
Enterprise version of vmalert supports S3 and GCS paths to rules.
For example: gs://bucket/path/to/rules, s3://bucket/path/to/rules
S3 and GCS paths support only matching by prefix, e.g. s3://bucket/dir/rule_ matches
all files with prefix rule_ in folder dir.
- See https://docs.victoriametrics.com/vmalert/#reading-rules-from-object-storage
-
Supports an array of values separated by comma or specified via multiple flags.
Value can contain comma inside single-quoted or double-quoted string, {}, [] and () braces.
-rule.evalDelay time
@@ -1386,8 +1402,7 @@ The shortlist of configuration flags is the following:
-rule.templates="/path/to/file". Path to a single file with go templates
-rule.templates="dir/*.tpl" -rule.templates="/*.tpl". Relative path to all .tpl files in "dir" folder,
absolute path to all .tpl files in root.
- -rule.templates="dir/**/*.tpl". Includes all the .tpl files in "dir" subfolders recursively.
-
+ -rule.templates="dir/**/*.tpl". Includes all the .tpl files in "dir" subfolders recursively.
Supports an array of values separated by comma or specified via multiple flags.
Value can contain comma inside single-quoted or double-quoted string, {}, [] and () braces.
-rule.updateEntriesLimit int
diff --git a/lib/ingestserver/statsd/server.go b/lib/ingestserver/statsd/server.go
new file mode 100644
index 000000000..533d2ed1b
--- /dev/null
+++ b/lib/ingestserver/statsd/server.go
@@ -0,0 +1,173 @@
+package statsd
+
+import (
+ "errors"
+ "io"
+ "net"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/ingestserver"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
+ "github.com/VictoriaMetrics/metrics"
+)
+
+var (
+ writeRequestsTCP = metrics.NewCounter(`vm_ingestserver_requests_total{type="statsd", name="write", net="tcp"}`)
+ writeErrorsTCP = metrics.NewCounter(`vm_ingestserver_request_errors_total{type="statsd", name="write", net="tcp"}`)
+
+ writeRequestsUDP = metrics.NewCounter(`vm_ingestserver_requests_total{type="statsd", name="write", net="udp"}`)
+ writeErrorsUDP = metrics.NewCounter(`vm_ingestserver_request_errors_total{type="statsd", name="write", net="udp"}`)
+)
+
+// Server accepts Statsd plaintext lines over TCP and UDP.
+type Server struct {
+ addr string
+ lnTCP net.Listener
+ lnUDP net.PacketConn
+ wg sync.WaitGroup
+ cm ingestserver.ConnsMap
+}
+
+// MustStart starts statsd server on the given addr.
+//
+// The incoming connections are processed with insertHandler.
+//
+// If useProxyProtocol is set to true, then the incoming connections are accepted via proxy protocol.
+// See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
+//
+// MustStop must be called on the returned server when it is no longer needed.
+func MustStart(addr string, useProxyProtocol bool, insertHandler func(r io.Reader) error) *Server {
+ logger.Infof("starting TCP Statsd server at %q", addr)
+ lnTCP, err := netutil.NewTCPListener("statsd", addr, useProxyProtocol, nil)
+ if err != nil {
+ logger.Fatalf("cannot start TCP Statsd server at %q: %s", addr, err)
+ }
+
+ logger.Infof("starting UDP Statsd server at %q", addr)
+ lnUDP, err := net.ListenPacket(netutil.GetUDPNetwork(), addr)
+ if err != nil {
+ logger.Fatalf("cannot start UDP Statsd server at %q: %s", addr, err)
+ }
+
+ s := &Server{
+ addr: addr,
+ lnTCP: lnTCP,
+ lnUDP: lnUDP,
+ }
+ s.cm.Init("statsd")
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+ s.serveTCP(insertHandler)
+ logger.Infof("stopped TCP Statsd server at %q", addr)
+ }()
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+ s.serveUDP(insertHandler)
+ logger.Infof("stopped UDP Statsd server at %q", addr)
+ }()
+ return s
+}
+
+// MustStop stops the server.
+func (s *Server) MustStop() {
+ logger.Infof("stopping TCP Statsd server at %q...", s.addr)
+ if err := s.lnTCP.Close(); err != nil {
+ logger.Errorf("cannot close TCP Statsd server: %s", err)
+ }
+ logger.Infof("stopping UDP Statsd server at %q...", s.addr)
+ if err := s.lnUDP.Close(); err != nil {
+ logger.Errorf("cannot close UDP Statsd server: %s", err)
+ }
+ s.cm.CloseAll(0)
+ s.wg.Wait()
+ logger.Infof("TCP and UDP Statsd servers at %q have been stopped", s.addr)
+}
+
+func (s *Server) serveTCP(insertHandler func(r io.Reader) error) {
+ var wg sync.WaitGroup
+ for {
+ c, err := s.lnTCP.Accept()
+ if err != nil {
+ var ne net.Error
+ if errors.As(err, &ne) {
+ if ne.Temporary() {
+ logger.Errorf("statsd: temporary error when listening for TCP addr %q: %s", s.lnTCP.Addr(), err)
+ time.Sleep(time.Second)
+ continue
+ }
+ if strings.Contains(err.Error(), "use of closed network connection") {
+ break
+ }
+ logger.Fatalf("unrecoverable error when accepting TCP Statsd connections: %s", err)
+ }
+ logger.Fatalf("unexpected error when accepting TCP Statsd connections: %s", err)
+ }
+ if !s.cm.Add(c) {
+ _ = c.Close()
+ break
+ }
+ wg.Add(1)
+ go func() {
+ defer func() {
+ s.cm.Delete(c)
+ _ = c.Close()
+ wg.Done()
+ }()
+ writeRequestsTCP.Inc()
+ if err := insertHandler(c); err != nil {
+ writeErrorsTCP.Inc()
+ logger.Errorf("error in TCP Statsd conn %q<->%q: %s", c.LocalAddr(), c.RemoteAddr(), err)
+ }
+ }()
+ }
+ wg.Wait()
+}
+
+func (s *Server) serveUDP(insertHandler func(r io.Reader) error) {
+ gomaxprocs := cgroup.AvailableCPUs()
+ var wg sync.WaitGroup
+ for i := 0; i < gomaxprocs; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ var bb bytesutil.ByteBuffer
+ bb.B = bytesutil.ResizeNoCopyNoOverallocate(bb.B, 64*1024)
+ for {
+ bb.Reset()
+ bb.B = bb.B[:cap(bb.B)]
+ n, addr, err := s.lnUDP.ReadFrom(bb.B)
+ if err != nil {
+ writeErrorsUDP.Inc()
+ var ne net.Error
+ if errors.As(err, &ne) {
+ if ne.Temporary() {
+ logger.Errorf("statsd: temporary error when listening for UDP addr %q: %s", s.lnUDP.LocalAddr(), err)
+ time.Sleep(time.Second)
+ continue
+ }
+ if strings.Contains(err.Error(), "use of closed network connection") {
+ break
+ }
+ }
+ logger.Errorf("cannot read Statsd UDP data: %s", err)
+ continue
+ }
+ bb.B = bb.B[:n]
+ writeRequestsUDP.Inc()
+ if err := insertHandler(bb.NewReader()); err != nil {
+ writeErrorsUDP.Inc()
+ logger.Errorf("error in UDP Statsd conn %q<->%q: %s", s.lnUDP.LocalAddr(), addr, err)
+ continue
+ }
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/lib/mergeset/table.go b/lib/mergeset/table.go
index 52cc74ea8..628634c3d 100644
--- a/lib/mergeset/table.go
+++ b/lib/mergeset/table.go
@@ -167,7 +167,7 @@ var rawItemsShardsPerTable = func() int {
return cpus * multiplier
}()
-const maxBlocksPerShard = 256
+var maxBlocksPerShard = 256
func (riss *rawItemsShards) init() {
riss.shards = make([]rawItemsShard, rawItemsShardsPerTable)
diff --git a/lib/mergeset/table_test.go b/lib/mergeset/table_test.go
index e044ab34a..810dd5a04 100644
--- a/lib/mergeset/table_test.go
+++ b/lib/mergeset/table_test.go
@@ -176,6 +176,66 @@ func TestTableCreateSnapshotAt(t *testing.T) {
_ = os.RemoveAll(path)
}
+func TestTableAddItemsConcurrentStress(t *testing.T) {
+ const path = "TestTableAddItemsConcurrentStress"
+ if err := os.RemoveAll(path); err != nil {
+ t.Fatalf("cannot remove %q: %s", path, err)
+ }
+ defer func() {
+ _ = os.RemoveAll(path)
+ }()
+
+ rawItemsShardsPerTableOrig := rawItemsShardsPerTable
+ maxBlocksPerShardOrig := maxBlocksPerShard
+ rawItemsShardsPerTable = 10
+ maxBlocksPerShard = 3
+ defer func() {
+ rawItemsShardsPerTable = rawItemsShardsPerTableOrig
+ maxBlocksPerShard = maxBlocksPerShardOrig
+ }()
+
+ var flushes atomic.Uint64
+ flushCallback := func() {
+ flushes.Add(1)
+ }
+ prepareBlock := func(data []byte, items []Item) ([]byte, []Item) {
+ return data, items
+ }
+
+ blocksNeeded := rawItemsShardsPerTable * maxBlocksPerShard * 10
+ testAddItems := func(tb *Table) {
+ itemsBatch := make([][]byte, 0)
+
+ for j := 0; j < blocksNeeded; j++ {
+ item := bytes.Repeat([]byte{byte(j)}, maxInmemoryBlockSize-10)
+ itemsBatch = append(itemsBatch, item)
+ }
+ tb.AddItems(itemsBatch)
+ }
+
+ var isReadOnly atomic.Bool
+ tb := MustOpenTable(path, flushCallback, prepareBlock, &isReadOnly)
+
+ testAddItems(tb)
+
+ // Verify items count after pending items flush.
+ tb.DebugFlush()
+ if flushes.Load() == 0 {
+ t.Fatalf("unexpected zero flushes")
+ }
+
+ var m TableMetrics
+ tb.UpdateMetrics(&m)
+ if n := m.TotalItemsCount(); n != uint64(blocksNeeded) {
+ t.Fatalf("unexpected itemsCount; got %d; want %v", n, blocksNeeded)
+ }
+
+ tb.MustClose()
+
+ // Re-open the table and make sure itemsCount remains the same.
+ testReopenTable(t, path, blocksNeeded)
+}
+
func TestTableAddItemsConcurrent(t *testing.T) {
const path = "TestTableAddItemsConcurrent"
if err := os.RemoveAll(path); err != nil {
diff --git a/lib/persistentqueue/fastqueue.go b/lib/persistentqueue/fastqueue.go
index a2d597411..3c194f7ba 100644
--- a/lib/persistentqueue/fastqueue.go
+++ b/lib/persistentqueue/fastqueue.go
@@ -63,7 +63,7 @@ func MustOpenFastQueue(path, name string, maxInmemoryBlocks int, maxPendingBytes
return float64(n)
})
pendingBytes := fq.GetPendingBytes()
- logger.Infof("opened fast persistent queue at %q with maxInmemoryBlocks=%d, it contains %d pending bytes", path, maxInmemoryBlocks, pendingBytes)
+ logger.Infof("opened fast persistent queue at %q with maxInmemoryBlocks=%d isPQDisabled=%t, it contains %d pending bytes", path, maxInmemoryBlocks, isPQDisabled, pendingBytes)
return fq
}
diff --git a/lib/prompb/prompb.go b/lib/prompb/prompb.go
index 34a1c5716..adc8935e2 100644
--- a/lib/prompb/prompb.go
+++ b/lib/prompb/prompb.go
@@ -9,10 +9,11 @@ import (
// WriteRequest represents Prometheus remote write API request.
type WriteRequest struct {
// Timeseries is a list of time series in the given WriteRequest
- Timeseries []TimeSeries
-
- labelsPool []Label
- samplesPool []Sample
+ Timeseries []TimeSeries
+ labelsPool []Label
+ exemplarLabelsPool []Label
+ samplesPool []Sample
+ exemplarsPool []Exemplar
}
// Reset resets wr for subsequent re-use.
@@ -29,11 +30,33 @@ func (wr *WriteRequest) Reset() {
}
wr.labelsPool = labelsPool[:0]
+ exemplarLabelsPool := wr.exemplarLabelsPool
+ for i := range exemplarLabelsPool {
+ exemplarLabelsPool[i] = Label{}
+ }
+ wr.labelsPool = labelsPool[:0]
samplesPool := wr.samplesPool
for i := range samplesPool {
samplesPool[i] = Sample{}
}
wr.samplesPool = samplesPool[:0]
+ exemplarsPool := wr.exemplarsPool
+ for i := range exemplarsPool {
+ exemplarsPool[i] = Exemplar{}
+ }
+ wr.exemplarsPool = exemplarsPool[:0]
+}
+
+// Exemplar is an exemplar
+type Exemplar struct {
+ // Labels a list of labels that uniquely identifies exemplar
+ // Optional, can be empty.
+ Labels []Label
+ // Value: the value of the exemplar
+ Value float64
+ // timestamp is in ms format, see model/timestamp/timestamp.go for
+ // conversion from time.Time to Prometheus timestamp.
+ Timestamp int64
}
// TimeSeries is a timeseries.
@@ -42,7 +65,8 @@ type TimeSeries struct {
Labels []Label
// Samples is a list of samples for the given TimeSeries
- Samples []Sample
+ Samples []Sample
+ Exemplars []Exemplar
}
// Sample is a timeseries sample.
@@ -74,7 +98,10 @@ func (wr *WriteRequest) UnmarshalProtobuf(src []byte) (err error) {
// }
tss := wr.Timeseries
labelsPool := wr.labelsPool
+ exemplarLabelsPool := wr.exemplarLabelsPool
samplesPool := wr.samplesPool
+ exemplarsPool := wr.exemplarsPool
+
var fc easyproto.FieldContext
for len(src) > 0 {
src, err = fc.NextField(src)
@@ -93,7 +120,7 @@ func (wr *WriteRequest) UnmarshalProtobuf(src []byte) (err error) {
tss = append(tss, TimeSeries{})
}
ts := &tss[len(tss)-1]
- labelsPool, samplesPool, err = ts.unmarshalProtobuf(data, labelsPool, samplesPool)
+ labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, err = ts.unmarshalProtobuf(data, labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool)
if err != nil {
return fmt.Errorf("cannot unmarshal timeseries: %w", err)
}
@@ -102,28 +129,31 @@ func (wr *WriteRequest) UnmarshalProtobuf(src []byte) (err error) {
wr.Timeseries = tss
wr.labelsPool = labelsPool
wr.samplesPool = samplesPool
+ wr.exemplarsPool = exemplarsPool
return nil
}
-func (ts *TimeSeries) unmarshalProtobuf(src []byte, labelsPool []Label, samplesPool []Sample) ([]Label, []Sample, error) {
+func (ts *TimeSeries) unmarshalProtobuf(src []byte, labelsPool []Label, exemplarLabelsPool []Label, samplesPool []Sample, exemplarsPool []Exemplar) ([]Label, []Label, []Sample, []Exemplar, error) {
// message TimeSeries {
// repeated Label labels = 1;
// repeated Sample samples = 2;
+ // repeated Exemplar exemplars = 3
// }
labelsPoolLen := len(labelsPool)
samplesPoolLen := len(samplesPool)
+ exemplarsPoolLen := len(exemplarsPool)
var fc easyproto.FieldContext
for len(src) > 0 {
var err error
src, err = fc.NextField(src)
if err != nil {
- return labelsPool, samplesPool, fmt.Errorf("cannot read the next field: %w", err)
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot read the next field: %w", err)
}
switch fc.FieldNum {
case 1:
data, ok := fc.MessageData()
if !ok {
- return labelsPool, samplesPool, fmt.Errorf("cannot read label data")
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot read label data")
}
if len(labelsPool) < cap(labelsPool) {
labelsPool = labelsPool[:len(labelsPool)+1]
@@ -132,12 +162,12 @@ func (ts *TimeSeries) unmarshalProtobuf(src []byte, labelsPool []Label, samplesP
}
label := &labelsPool[len(labelsPool)-1]
if err := label.unmarshalProtobuf(data); err != nil {
- return labelsPool, samplesPool, fmt.Errorf("cannot unmarshal label: %w", err)
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot unmarshal label: %w", err)
}
case 2:
data, ok := fc.MessageData()
if !ok {
- return labelsPool, samplesPool, fmt.Errorf("cannot read the sample data")
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot read the sample data")
}
if len(samplesPool) < cap(samplesPool) {
samplesPool = samplesPool[:len(samplesPool)+1]
@@ -146,15 +176,78 @@ func (ts *TimeSeries) unmarshalProtobuf(src []byte, labelsPool []Label, samplesP
}
sample := &samplesPool[len(samplesPool)-1]
if err := sample.unmarshalProtobuf(data); err != nil {
- return labelsPool, samplesPool, fmt.Errorf("cannot unmarshal sample: %w", err)
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot unmarshal sample: %w", err)
+ }
+ case 3:
+ data, ok := fc.MessageData()
+ if !ok {
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot read the exemplar data")
+ }
+ if len(exemplarsPool) < cap(exemplarsPool) {
+ exemplarsPool = exemplarsPool[:len(exemplarsPool)+1]
+ } else {
+ exemplarsPool = append(exemplarsPool, Exemplar{})
+ }
+ exemplar := &exemplarsPool[len(exemplarsPool)-1]
+ if exemplarLabelsPool, err = exemplar.unmarshalProtobuf(data, exemplarLabelsPool); err != nil {
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, fmt.Errorf("cannot unmarshal exemplar: %w", err)
}
}
}
ts.Labels = labelsPool[labelsPoolLen:]
ts.Samples = samplesPool[samplesPoolLen:]
- return labelsPool, samplesPool, nil
+ ts.Exemplars = exemplarsPool[exemplarsPoolLen:]
+ return labelsPool, exemplarLabelsPool, samplesPool, exemplarsPool, nil
}
+func (exemplar *Exemplar) unmarshalProtobuf(src []byte, labelsPool []Label) ([]Label, error) {
+ // message Exemplar {
+ // repeated Label Labels = 1;
+ // float64 Value = 2;
+ // int64 Timestamp = 3;
+ // }
+ var fc easyproto.FieldContext
+
+ labelsPoolLen := len(labelsPool)
+
+ for len(src) > 0 {
+ var err error
+ src, err = fc.NextField(src)
+ if err != nil {
+ return labelsPool, fmt.Errorf("cannot read the next field: %w", err)
+ }
+ switch fc.FieldNum {
+ case 1:
+ data, ok := fc.MessageData()
+ if !ok {
+ return labelsPool, fmt.Errorf("cannot read label data")
+ }
+ if len(labelsPool) < cap(labelsPool) {
+ labelsPool = labelsPool[:len(labelsPool)+1]
+ } else {
+ labelsPool = append(labelsPool, Label{})
+ }
+ label := &labelsPool[len(labelsPool)-1]
+ if err := label.unmarshalProtobuf(data); err != nil {
+ return labelsPool, fmt.Errorf("cannot unmarshal label: %w", err)
+ }
+ case 2:
+ value, ok := fc.Double()
+ if !ok {
+ return labelsPool, fmt.Errorf("cannot read exemplar value")
+ }
+ exemplar.Value = value
+ case 3:
+ timestamp, ok := fc.Int64()
+ if !ok {
+ return labelsPool, fmt.Errorf("cannot read exemplar timestamp")
+ }
+ exemplar.Timestamp = timestamp
+ }
+ }
+ exemplar.Labels = labelsPool[labelsPoolLen:]
+ return labelsPool, nil
+}
func (lbl *Label) unmarshalProtobuf(src []byte) (err error) {
// message Label {
// string name = 1;
diff --git a/lib/prompb/prompb_test.go b/lib/prompb/prompb_test.go
index 727101206..b1d6e02bc 100644
--- a/lib/prompb/prompb_test.go
+++ b/lib/prompb/prompb_test.go
@@ -36,9 +36,25 @@ func TestWriteRequestUnmarshalProtobuf(t *testing.T) {
Timestamp: sample.Timestamp,
})
}
+ var exemplars []prompbmarshal.Exemplar
+ for _, exemplar := range ts.Exemplars {
+ exemplarLabels := make([]prompbmarshal.Label, len(exemplar.Labels))
+ for i, label := range exemplar.Labels {
+ exemplarLabels[i] = prompbmarshal.Label{
+ Name: label.Name,
+ Value: label.Value,
+ }
+ }
+ exemplars = append(exemplars, prompbmarshal.Exemplar{
+ Labels: exemplarLabels,
+ Value: exemplar.Value,
+ Timestamp: exemplar.Timestamp,
+ })
+ }
wrm.Timeseries = append(wrm.Timeseries, prompbmarshal.TimeSeries{
- Labels: labels,
- Samples: samples,
+ Labels: labels,
+ Samples: samples,
+ Exemplars: exemplars,
})
}
dataResult := wrm.MarshalProtobuf(nil)
@@ -121,6 +137,19 @@ func TestWriteRequestUnmarshalProtobuf(t *testing.T) {
Timestamp: 18939432423,
},
},
+ Exemplars: []prompbmarshal.Exemplar{
+ {
+ Labels: []prompbmarshal.Label{
+ {Name: "trace-id",
+ Value: "123456",
+ },
+ {Name: "log_id",
+ Value: "987664"},
+ },
+ Value: 12345.6,
+ Timestamp: 456,
+ },
+ },
},
}
data = wrm.MarshalProtobuf(data[:0])
@@ -153,6 +182,18 @@ func TestWriteRequestUnmarshalProtobuf(t *testing.T) {
Timestamp: 18939432423,
},
},
+ Exemplars: []prompbmarshal.Exemplar{
+ {
+ Labels: []prompbmarshal.Label{
+ {
+ Name: "trace-id",
+ Value: "123456",
+ },
+ },
+ Value: 12345.6,
+ Timestamp: 456,
+ },
+ },
},
{
Labels: []prompbmarshal.Label{
@@ -166,6 +207,22 @@ func TestWriteRequestUnmarshalProtobuf(t *testing.T) {
Value: 9873,
},
},
+ Exemplars: []prompbmarshal.Exemplar{
+ {
+ Labels: []prompbmarshal.Label{
+ {
+ Name: "trace-id",
+ Value: "123456",
+ },
+ {
+ Name: "log_id",
+ Value: "987654",
+ },
+ },
+ Value: 12345.6,
+ Timestamp: 456,
+ },
+ },
},
}
data = wrm.MarshalProtobuf(data[:0])
diff --git a/lib/prompbmarshal/prompbmarshal_test.go b/lib/prompbmarshal/prompbmarshal_test.go
index 99fb28c10..42716fdb2 100644
--- a/lib/prompbmarshal/prompbmarshal_test.go
+++ b/lib/prompbmarshal/prompbmarshal_test.go
@@ -36,6 +36,22 @@ func TestWriteRequestMarshalProtobuf(t *testing.T) {
Timestamp: 18939432423,
},
},
+ Exemplars: []prompbmarshal.Exemplar{
+ {
+ Labels: []prompbmarshal.Label{
+ {
+ Name: "trace-id",
+ Value: "123456",
+ },
+ {
+ Name: "log_id",
+ Value: "987654",
+ },
+ },
+ Value: 12345.6,
+ Timestamp: 456,
+ },
+ },
},
},
}
@@ -64,9 +80,25 @@ func TestWriteRequestMarshalProtobuf(t *testing.T) {
Timestamp: sample.Timestamp,
})
}
+ var exemplars []prompbmarshal.Exemplar
+ for _, exemplar := range ts.Exemplars {
+ exemplarLabels := make([]prompbmarshal.Label, len(exemplar.Labels))
+ for i, label := range exemplar.Labels {
+ exemplarLabels[i] = prompbmarshal.Label{
+ Name: label.Name,
+ Value: label.Value,
+ }
+ }
+ exemplars = append(exemplars, prompbmarshal.Exemplar{
+ Labels: exemplarLabels,
+ Value: exemplar.Value,
+ Timestamp: exemplar.Timestamp,
+ })
+ }
wrm.Timeseries = append(wrm.Timeseries, prompbmarshal.TimeSeries{
- Labels: labels,
- Samples: samples,
+ Labels: labels,
+ Samples: samples,
+ Exemplars: exemplars,
})
}
dataResult := wrm.MarshalProtobuf(nil)
diff --git a/lib/prompbmarshal/types.pb.go b/lib/prompbmarshal/types.pb.go
index ca2b62f1b..d5295ddd0 100644
--- a/lib/prompbmarshal/types.pb.go
+++ b/lib/prompbmarshal/types.pb.go
@@ -13,10 +13,70 @@ type Sample struct {
Timestamp int64
}
+type Exemplar struct {
+ // Optional, can be empty.
+ Labels []Label
+ Value float64
+ // timestamp is in ms format, see model/timestamp/timestamp.go for
+ // conversion from time.Time to Prometheus timestamp.
+ Timestamp int64
+}
+
+func (m *Exemplar) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ if m.Timestamp != 0 {
+ i = encodeVarint(dAtA, i, uint64(m.Timestamp))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.Value != 0 {
+ i -= 8
+ binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value))))
+ i--
+ dAtA[i] = 0x11
+ }
+ if len(m.Labels) > 0 {
+ for iNdEx := len(m.Labels) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Labels[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarint(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ }
+ return len(dAtA) - i, nil
+}
+func (m *Exemplar) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Labels) > 0 {
+ for _, e := range m.Labels {
+ l = e.Size()
+ n += 1 + l + sov(uint64(l))
+ }
+ }
+ if m.Value != 0 {
+ n += 9
+ }
+ if m.Timestamp != 0 {
+ n += 1 + sov(uint64(m.Timestamp))
+ }
+ return n
+}
+
// TimeSeries represents samples and labels for a single time series.
type TimeSeries struct {
- Labels []Label
- Samples []Sample
+ Labels []Label
+ Samples []Sample
+ Exemplars []Exemplar
}
type Label struct {
@@ -42,6 +102,16 @@ func (m *Sample) MarshalToSizedBuffer(dst []byte) (int, error) {
func (m *TimeSeries) MarshalToSizedBuffer(dst []byte) (int, error) {
i := len(dst)
+ for j := len(m.Exemplars) - 1; j >= 0; j-- {
+ size, err := m.Exemplars[j].MarshalToSizedBuffer(dst[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarint(dst, i, uint64(size))
+ i--
+ dst[i] = 0x1a
+ }
for j := len(m.Samples) - 1; j >= 0; j-- {
size, err := m.Samples[j].MarshalToSizedBuffer(dst[:i])
if err != nil {
@@ -109,6 +179,10 @@ func (m *TimeSeries) Size() (n int) {
l := e.Size()
n += 1 + l + sov(uint64(l))
}
+ for _, e := range m.Exemplars {
+ l := e.Size()
+ n += 1 + l + sov(uint64(l))
+ }
return n
}
diff --git a/lib/promscrape/client.go b/lib/promscrape/client.go
index e5f7b4a5e..31457911a 100644
--- a/lib/promscrape/client.go
+++ b/lib/promscrape/client.go
@@ -30,6 +30,7 @@ var (
streamParse = flag.Bool("promscrape.streamParse", false, "Whether to enable stream parsing for metrics obtained from scrape targets. This may be useful "+
"for reducing memory usage when millions of metrics are exposed per each scrape target. "+
"It is possible to set 'stream_parse: true' individually per each 'scrape_config' section in '-promscrape.config' for fine-grained control")
+ scrapeExemplars = flag.Bool("promscrape.scrapeExemplars", false, "Whether to enable scraping of exemplars from scrape targets.")
)
type client struct {
@@ -107,6 +108,12 @@ func (c *client) ReadData(dst *bytesutil.ByteBuffer) error {
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/608 for details.
// Do not bloat the `Accept` header with OpenMetrics shit, since it looks like dead standard now.
req.Header.Set("Accept", "text/plain;version=0.0.4;q=1,*/*;q=0.1")
+ // We set to support exemplars to be compatible with Prometheus Exposition format which uses
+ // Open Metrics Specification
+ // See https://github.com/prometheus/docs/blob/main/content/docs/instrumenting/exposition_formats.md#openmetrics-text-format
+ if *scrapeExemplars {
+ req.Header.Set("Accept", "application/openmetrics-text")
+ }
// Set X-Prometheus-Scrape-Timeout-Seconds like Prometheus does, since it is used by some exporters such as PushProx.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1179#issuecomment-813117162
req.Header.Set("X-Prometheus-Scrape-Timeout-Seconds", c.scrapeTimeoutSecondsStr)
diff --git a/lib/promscrape/config.go b/lib/promscrape/config.go
index 5516b60f1..b0ea9603f 100644
--- a/lib/promscrape/config.go
+++ b/lib/promscrape/config.go
@@ -36,6 +36,7 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/kuma"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/nomad"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/openstack"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/vultr"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/yandexcloud"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/proxy"
@@ -308,6 +309,7 @@ type ScrapeConfig struct {
NomadSDConfigs []nomad.SDConfig `yaml:"nomad_sd_configs,omitempty"`
OpenStackSDConfigs []openstack.SDConfig `yaml:"openstack_sd_configs,omitempty"`
StaticConfigs []StaticConfig `yaml:"static_configs,omitempty"`
+ VultrConfigs []vultr.SDConfig `yaml:"vultr_configs,omitempty"`
YandexCloudSDConfigs []yandexcloud.SDConfig `yaml:"yandexcloud_sd_configs,omitempty"`
// These options are supported only by lib/promscrape.
@@ -388,6 +390,9 @@ func (sc *ScrapeConfig) mustStop() {
for i := range sc.OpenStackSDConfigs {
sc.OpenStackSDConfigs[i].MustStop()
}
+ for i := range sc.VultrConfigs {
+ sc.VultrConfigs[i].MustStop()
+ }
}
// FileSDConfig represents file-based service discovery config.
@@ -745,6 +750,16 @@ func (cfg *Config) getOpenStackSDScrapeWork(prev []*ScrapeWork) []*ScrapeWork {
return cfg.getScrapeWorkGeneric(visitConfigs, "openstack_sd_config", prev)
}
+// getVultrSDScrapeWork returns `vultr_sd_configs` ScrapeWork from cfg.
+func (cfg *Config) getVultrSDScrapeWork(prev []*ScrapeWork) []*ScrapeWork {
+ visitConfigs := func(sc *ScrapeConfig, visitor func(sdc targetLabelsGetter)) {
+ for i := range sc.VultrConfigs {
+ visitor(&sc.VultrConfigs[i])
+ }
+ }
+ return cfg.getScrapeWorkGeneric(visitConfigs, "vultr_sd_config", prev)
+}
+
// getYandexCloudSDScrapeWork returns `yandexcloud_sd_configs` ScrapeWork from cfg.
func (cfg *Config) getYandexCloudSDScrapeWork(prev []*ScrapeWork) []*ScrapeWork {
visitConfigs := func(sc *ScrapeConfig, visitor func(sdc targetLabelsGetter)) {
diff --git a/lib/promscrape/discovery/vultr/api.go b/lib/promscrape/discovery/vultr/api.go
new file mode 100644
index 000000000..86e82df3a
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/api.go
@@ -0,0 +1,76 @@
+package vultr
+
+import (
+ "fmt"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+)
+
+// apiConfig contains config for API server.
+type apiConfig struct {
+ c *discoveryutils.Client
+ port int
+
+ listParams
+}
+
+// listParams is the query params of vultr ListInstance API.
+type listParams struct {
+ // paging params are not exposed to user, they will be filled
+ // dynamically during request. See `getInstances`.
+ // perPage int
+ // cursor string
+
+ // API query params for filtering.
+ label string
+ mainIP string
+ region string
+ firewallGroupID string
+ hostname string
+}
+
+// getAPIConfig get or create API config from configMap.
+func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
+ v, err := configMap.Get(sdc, func() (interface{}, error) { return newAPIConfig(sdc, baseDir) })
+ if err != nil {
+ return nil, err
+ }
+ return v.(*apiConfig), nil
+}
+
+// newAPIConfig create API Config.
+func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
+ port := sdc.Port
+ if port == 0 {
+ port = 80
+ }
+
+ // See: https://www.vultr.com/api/
+ apiServer := "https://api.vultr.com"
+
+ ac, err := sdc.HTTPClientConfig.NewConfig(baseDir)
+ if err != nil {
+ return nil, fmt.Errorf("cannot parse auth config: %w", err)
+ }
+ proxyAC, err := sdc.ProxyClientConfig.NewConfig(baseDir)
+ if err != nil {
+ return nil, fmt.Errorf("cannot parse proxy auth config: %w", err)
+ }
+
+ c, err := discoveryutils.NewClient(apiServer, ac, sdc.ProxyURL, proxyAC, &sdc.HTTPClientConfig)
+ if err != nil {
+ return nil, fmt.Errorf("cannot create client for %q: %w", apiServer, err)
+ }
+ cfg := &apiConfig{
+ c: c,
+ port: port,
+ listParams: listParams{
+ label: sdc.Label,
+ mainIP: sdc.MainIP,
+ region: sdc.Region,
+ firewallGroupID: sdc.FirewallGroupID,
+ hostname: sdc.Hostname,
+ },
+ }
+ return cfg, nil
+}
diff --git a/lib/promscrape/discovery/vultr/api_test.go b/lib/promscrape/discovery/vultr/api_test.go
new file mode 100644
index 000000000..06e491446
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/api_test.go
@@ -0,0 +1,16 @@
+package vultr
+
+import (
+ "testing"
+)
+
+func TestNewAPIConfig(t *testing.T) {
+
+ sdc := &SDConfig{}
+ baseDir := "."
+ _, err := newAPIConfig(sdc, baseDir)
+ if err != nil {
+ t.Errorf("newAPIConfig failed with, err: %v", err)
+ return
+ }
+}
diff --git a/lib/promscrape/discovery/vultr/instance.go b/lib/promscrape/discovery/vultr/instance.go
new file mode 100644
index 000000000..e510b7353
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/instance.go
@@ -0,0 +1,109 @@
+package vultr
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/url"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
+)
+
+// ListInstanceResponse is the response structure of Vultr ListInstance API.
+type ListInstanceResponse struct {
+ Instances []Instance `json:"instances"`
+ Meta *Meta `json:"Meta"`
+}
+
+// Instance represents Vultr Instance (VPS).
+// See: https://github.com/vultr/govultr/blob/5125e02e715ae6eb3ce854f0e7116c7ce545a710/instance.go#L81
+type Instance struct {
+ ID string `json:"id"`
+ Os string `json:"os"`
+ RAM int `json:"ram"`
+ Disk int `json:"disk"`
+ MainIP string `json:"main_ip"`
+ VCPUCount int `json:"vcpu_count"`
+ Region string `json:"region"`
+ ServerStatus string `json:"server_status"`
+ AllowedBandwidth int `json:"allowed_bandwidth"`
+ V6MainIP string `json:"v6_main_ip"`
+ Hostname string `json:"hostname"`
+ Label string `json:"label"`
+ InternalIP string `json:"internal_ip"`
+ OsID int `json:"os_id"`
+ Features []string `json:"features"`
+ Plan string `json:"plan"`
+ Tags []string `json:"tags"`
+
+ // The following fields are defined in the response but are not used during service discovery.
+ //DefaultPassword string `json:"default_password,omitempty"`
+ //DateCreated string `json:"date_created"`
+ //Status string `json:"status"`
+ //PowerStatus string `json:"power_status"`
+ //NetmaskV4 string `json:"netmask_v4"`
+ //GatewayV4 string `json:"gateway_v4"`
+ //V6Network string `json:"v6_network"`
+ //V6NetworkSize int `json:"v6_network_size"`
+ //// Deprecated: Tag should no longer be used. Instead, use Tags.
+ //Tag string `json:"tag"`
+ //KVM string `json:"kvm"`
+ //AppID int `json:"app_id"`
+ //ImageID string `json:"image_id"`
+ //FirewallGroupID string `json:"firewall_group_id"`
+ //UserScheme string `json:"user_scheme"`
+}
+
+// Meta represents the available pagination information
+type Meta struct {
+ Total int `json:"total"`
+ Links *Links
+}
+
+// Links represent the next/previous cursor in your pagination calls
+type Links struct {
+ Next string `json:"next"`
+ Prev string `json:"prev"`
+}
+
+// getInstances retrieve instance from Vultr HTTP API.
+func getInstances(cfg *apiConfig) ([]Instance, error) {
+ var instances []Instance
+
+ // prepare GET params
+ params := url.Values{}
+ params.Set("per_page", "100")
+ params.Set("label", cfg.label)
+ params.Set("main_ip", cfg.mainIP)
+ params.Set("region", cfg.region)
+ params.Set("firewall_group_id", cfg.firewallGroupID)
+ params.Set("hostname", cfg.hostname)
+
+ // send request to vultr API
+ for {
+ // See: https://www.vultr.com/api/#tag/instances/operation/list-instances
+ path := fmt.Sprintf("/v2/instances?%s", params.Encode())
+ resp, err := cfg.c.GetAPIResponse(path)
+ if err != nil {
+ logger.Errorf("get response from vultr failed, path:%s, err: %v", path, err)
+ return nil, err
+ }
+
+ var listInstanceResp ListInstanceResponse
+ if err = json.Unmarshal(resp, &listInstanceResp); err != nil {
+ logger.Errorf("unmarshal response from vultr failed, err: %v", err)
+ return nil, err
+ }
+
+ instances = append(instances, listInstanceResp.Instances...)
+
+ if listInstanceResp.Meta != nil && listInstanceResp.Meta.Links != nil && listInstanceResp.Meta.Links.Next != "" {
+ // if `next page` is available, set the cursor param and request again.
+ params.Set("cursor", listInstanceResp.Meta.Links.Next)
+ } else {
+ // otherwise exit the loop
+ break
+ }
+ }
+
+ return instances, nil
+}
diff --git a/lib/promscrape/discovery/vultr/instance_test.go b/lib/promscrape/discovery/vultr/instance_test.go
new file mode 100644
index 000000000..b888c1a13
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/instance_test.go
@@ -0,0 +1,301 @@
+package vultr
+
+import (
+ "errors"
+ "reflect"
+ "testing"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+)
+
+// TestGetInstances runs general test cases for GetInstances
+func TestGetInstances(t *testing.T) {
+ testCases := []struct {
+ name string
+ apiResponse string
+ apiError bool
+ expectError bool
+ expectResponse []Instance
+ }{
+ {
+ name: "success response",
+ apiResponse: mockListInstanceSuccessResp,
+ apiError: false,
+ expectError: false,
+ expectResponse: expectSuccessInstances,
+ },
+ {
+ name: "failed response",
+ apiResponse: mockListInstanceFailedResp,
+ apiError: true,
+ expectError: true,
+ expectResponse: nil,
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ // Prepare a mock Vultr server.
+ mockServer := newMockVultrServer(func() ([]byte, error) {
+ var e error
+ if tt.apiError {
+ e = errors.New("mock error")
+ }
+ return []byte(tt.apiResponse), e
+ })
+
+ // Prepare a discovery HTTP client who calls mock server.
+ client, _ := discoveryutils.NewClient(mockServer.URL, nil, nil, nil, &promauth.HTTPClientConfig{})
+ cfg := &apiConfig{
+ c: client,
+ }
+
+ // execute `getInstances`
+ instances, err := getInstances(cfg)
+
+ // evaluate test result
+ if tt.expectError != (err != nil) {
+ t.Errorf("getInstances expect (error != nil): %t, got error: %v", tt.expectError, err)
+ }
+
+ if !reflect.DeepEqual(tt.expectResponse, instances) {
+ t.Errorf("getInstances expect result: %v, got: %v", tt.expectResponse, instances)
+ }
+ })
+ }
+}
+
+// TestGetInstancesPaging run test cases for response with multiple pages.
+func TestGetInstancesPaging(t *testing.T) {
+ // Prepare a mock Vultr server.
+ // requestCount control the mock response for different page request.
+ requestCount := 0
+
+ mockServer := newMockVultrServer(func() ([]byte, error) {
+ // for the 1st request, response with `next` cursor
+ if requestCount == 0 {
+ requestCount++
+ return []byte(mockListInstanceSuccessPage0Resp), nil
+ }
+ // for the 2nd+ request, response with `prev` cursor and empty `next`.
+ return []byte(mockListInstanceSuccessPage1Resp), nil
+ })
+
+ // Prepare a discovery HTTP client who calls mock server.
+ client, _ := discoveryutils.NewClient(mockServer.URL, nil, nil, nil, &promauth.HTTPClientConfig{})
+ cfg := &apiConfig{
+ c: client,
+ }
+
+ // execute `getInstances`
+ instances, err := getInstances(cfg)
+
+ // evaluate test result
+ if err != nil {
+ t.Errorf("getInstances expect error: %v, got error: %v", nil, err)
+ }
+
+ if !reflect.DeepEqual(expectSuccessPagingInstances, instances) {
+ t.Errorf("getInstances expect result: %v, got: %v", expectSuccessPagingInstances, instances)
+ }
+}
+
+// ------------ Test dataset ------------
+var (
+ // mockListInstanceSuccessResp is crawled from a real-world response of ListInstance API
+ // with sensitive info removed/modified.
+ mockListInstanceSuccessResp = `{
+ "instances": [{
+ "id": "fake-id-07f7-4b68-88ac-fake-id",
+ "os": "Ubuntu 22.04 x64",
+ "ram": 1024,
+ "disk": 25,
+ "main_ip": "64.176.84.27",
+ "vcpu_count": 1,
+ "region": "sgp",
+ "plan": "vc2-1c-1gb",
+ "date_created": "2024-04-05T05:41:28+00:00",
+ "status": "active",
+ "allowed_bandwidth": 1,
+ "netmask_v4": "255.255.254.0",
+ "gateway_v4": "64.176.63.2",
+ "power_status": "running",
+ "server_status": "installingbooting",
+ "v6_network": "2002:18f0:4100:263a::",
+ "v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ "v6_network_size": 64,
+ "label": "vultr-sd",
+ "internal_ip": "",
+ "kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
+ "hostname": "vultr-sd",
+ "tag": "",
+ "tags": [],
+ "os_id": 1743,
+ "app_id": 0,
+ "image_id": "",
+ "firewall_group_id": "",
+ "features": ["ipv6"],
+ "user_scheme": "root"
+ }],
+ "meta": {
+ "total": 1,
+ "links": {
+ "next": "",
+ "prev": ""
+ }
+ }
+}`
+ expectSuccessInstances = []Instance{
+ {
+ ID: "fake-id-07f7-4b68-88ac-fake-id",
+ Os: "Ubuntu 22.04 x64",
+ RAM: 1024,
+ Disk: 25,
+ MainIP: "64.176.84.27",
+ VCPUCount: 1,
+ Region: "sgp",
+ Plan: "vc2-1c-1gb",
+ AllowedBandwidth: 1,
+ ServerStatus: "installingbooting",
+ V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ Label: "vultr-sd",
+ InternalIP: "",
+ Hostname: "vultr-sd",
+ Tags: []string{},
+ OsID: 1743,
+ Features: []string{"ipv6"},
+ },
+ }
+)
+
+var (
+ mockListInstanceFailedResp = `{"error":"Invalid API token.","status":401}`
+)
+
+var (
+ // mockListInstanceSuccessPage0Resp contains `next` cursor
+ mockListInstanceSuccessPage0Resp = `{
+ "instances": [{
+ "id": "fake-id-07f7-4b68-88ac-fake-id",
+ "os": "Ubuntu 22.04 x64",
+ "ram": 1024,
+ "disk": 25,
+ "main_ip": "64.176.84.27",
+ "vcpu_count": 1,
+ "region": "sgp",
+ "plan": "vc2-1c-1gb",
+ "date_created": "2024-04-05T05:41:28+00:00",
+ "status": "active",
+ "allowed_bandwidth": 1,
+ "netmask_v4": "255.255.254.0",
+ "gateway_v4": "64.176.63.2",
+ "power_status": "running",
+ "server_status": "installingbooting",
+ "v6_network": "2002:18f0:4100:263a::",
+ "v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ "v6_network_size": 64,
+ "label": "vultr-sd",
+ "internal_ip": "",
+ "kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
+ "hostname": "vultr-sd",
+ "tag": "",
+ "tags": [],
+ "os_id": 1743,
+ "app_id": 0,
+ "image_id": "",
+ "firewall_group_id": "",
+ "features": ["ipv6"],
+ "user_scheme": "root"
+ }],
+ "meta": {
+ "total": 2,
+ "links": {
+ "next": "fake-cursor-string",
+ "prev": ""
+ }
+ }
+}`
+ // mockListInstanceSuccessPage1Resp contains `prev` cursor
+ mockListInstanceSuccessPage1Resp = `{
+ "instances": [{
+ "id": "fake-id-07f7-4b68-88ac-fake-id",
+ "os": "Ubuntu 22.04 x64",
+ "ram": 1024,
+ "disk": 25,
+ "main_ip": "64.176.84.27",
+ "vcpu_count": 1,
+ "region": "sgp",
+ "plan": "vc2-1c-1gb",
+ "date_created": "2024-04-05T05:41:28+00:00",
+ "status": "active",
+ "allowed_bandwidth": 1,
+ "netmask_v4": "255.255.254.0",
+ "gateway_v4": "64.176.63.2",
+ "power_status": "running",
+ "server_status": "installingbooting",
+ "v6_network": "2002:18f0:4100:263a::",
+ "v6_main_ip": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ "v6_network_size": 64,
+ "label": "vultr-sd",
+ "internal_ip": "",
+ "kvm": "https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=secret_data_string",
+ "hostname": "vultr-sd",
+ "tag": "",
+ "tags": [],
+ "os_id": 1743,
+ "app_id": 0,
+ "image_id": "",
+ "firewall_group_id": "",
+ "features": ["ipv6"],
+ "user_scheme": "root"
+ }],
+ "meta": {
+ "total": 2,
+ "links": {
+ "next": "",
+ "prev": "fake-cursor-string"
+ }
+ }
+}`
+ expectSuccessPagingInstances = []Instance{
+ {
+ ID: "fake-id-07f7-4b68-88ac-fake-id",
+ Os: "Ubuntu 22.04 x64",
+ RAM: 1024,
+ Disk: 25,
+ MainIP: "64.176.84.27",
+ VCPUCount: 1,
+ Region: "sgp",
+ Plan: "vc2-1c-1gb",
+ AllowedBandwidth: 1,
+ ServerStatus: "installingbooting",
+ V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ Label: "vultr-sd",
+ InternalIP: "",
+ Hostname: "vultr-sd",
+ Tags: []string{},
+ OsID: 1743,
+ Features: []string{"ipv6"},
+ },
+ {
+ ID: "fake-id-07f7-4b68-88ac-fake-id",
+ Os: "Ubuntu 22.04 x64",
+ RAM: 1024,
+ Disk: 25,
+ MainIP: "64.176.84.27",
+ VCPUCount: 1,
+ Region: "sgp",
+ Plan: "vc2-1c-1gb",
+ AllowedBandwidth: 1,
+ ServerStatus: "installingbooting",
+ V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ Label: "vultr-sd",
+ InternalIP: "",
+ Hostname: "vultr-sd",
+ Tags: []string{},
+ OsID: 1743,
+ Features: []string{"ipv6"},
+ },
+ }
+)
diff --git a/lib/promscrape/discovery/vultr/mock_server_test.go b/lib/promscrape/discovery/vultr/mock_server_test.go
new file mode 100644
index 000000000..c0dd79e46
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/mock_server_test.go
@@ -0,0 +1,40 @@
+package vultr
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+)
+
+func newMockVultrServer(jsonResponse func() ([]byte, error)) *vultrServer {
+ rw := &vultrServer{}
+ rw.Server = httptest.NewServer(http.HandlerFunc(rw.handler))
+ rw.jsonResponse = jsonResponse
+ return rw
+}
+
+type vultrServer struct {
+ *httptest.Server
+ jsonResponse func() ([]byte, error)
+}
+
+func (rw *vultrServer) err(w http.ResponseWriter, err error) {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(err.Error()))
+}
+
+func (rw *vultrServer) handler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet {
+ rw.err(w, fmt.Errorf("bad method %q", r.Method))
+ return
+ }
+
+ resp, err := rw.jsonResponse()
+ if err != nil {
+ rw.err(w, err)
+ return
+ }
+
+ w.Write(resp)
+ w.WriteHeader(http.StatusOK)
+}
diff --git a/lib/promscrape/discovery/vultr/vultr.go b/lib/promscrape/discovery/vultr/vultr.go
new file mode 100644
index 000000000..d8999b2bb
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/vultr.go
@@ -0,0 +1,105 @@
+package vultr
+
+import (
+ "flag"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/proxy"
+)
+
+const (
+ separator = ","
+)
+
+// SDCheckInterval defines interval for docker targets refresh.
+var SDCheckInterval = flag.Duration("promscrape.vultrSDCheckInterval", 30*time.Second, "Interval for checking for changes in Vultr. "+
+ "This works only if vultr_sd_configs is configured in '-promscrape.config' file. "+
+ "See https://docs.victoriametrics.com/sd_configs.html#vultr_sd_configs for details")
+
+// SDConfig represents service discovery config for Vultr.
+// See: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#vultr_sd_config
+// Additional query params are supported, while Prometheus only supports `Port` and HTTP auth.
+type SDConfig struct {
+ // API query params for filtering. All of them are optional.
+ // See: https://www.vultr.com/api/#tag/instances/operation/list-instances
+ Label string `yaml:"label,omitempty"`
+ MainIP string `yaml:"main_ip,omitempty"`
+ Region string `yaml:"region,omitempty"`
+ FirewallGroupID string `yaml:"firewall_group_id,omitempty"`
+ Hostname string `yaml:"hostname,omitempty"`
+
+ // The port to scrape metrics from. Default 80.
+ Port int `yaml:"port"`
+
+ // General HTTP / Auth configs.
+ HTTPClientConfig promauth.HTTPClientConfig `yaml:",inline"`
+ ProxyURL *proxy.URL `yaml:"proxy_url,omitempty"`
+ ProxyClientConfig promauth.ProxyClientConfig `yaml:",inline"`
+
+ // refresh_interval is obtained from `-promscrape.vultrSDCheckInterval` command-line option.
+}
+
+var configMap = discoveryutils.NewConfigMap()
+
+// GetLabels returns gce labels according to sdc.
+func (sdc *SDConfig) GetLabels(baseDir string) ([]*promutils.Labels, error) {
+ ac, err := getAPIConfig(sdc, baseDir)
+ if err != nil {
+ return nil, fmt.Errorf("cannot get API config: %w", err)
+ }
+ instances, err := getInstances(ac)
+ if err != nil {
+ return nil, err
+ }
+ return getInstanceLabels(instances, ac.port), nil
+}
+
+// MustStop stops further usage for sdc.
+func (sdc *SDConfig) MustStop() {
+ configMap.Delete(sdc)
+}
+
+// getInstanceLabels returns labels for vultr instances obtained from the given cfg
+func getInstanceLabels(instances []Instance, port int) []*promutils.Labels {
+ ms := make([]*promutils.Labels, 0, len(instances))
+
+ for _, instance := range instances {
+ m := promutils.NewLabels(18)
+ m.Add("__address__", discoveryutils.JoinHostPort(instance.MainIP, port))
+ m.Add("__meta_vultr_instance_id", instance.ID)
+ m.Add("__meta_vultr_instance_label", instance.Label)
+ m.Add("__meta_vultr_instance_os", instance.Os)
+ m.Add("__meta_vultr_instance_os_id", strconv.Itoa(instance.OsID))
+ m.Add("__meta_vultr_instance_region", instance.Region)
+ m.Add("__meta_vultr_instance_plan", instance.Plan)
+ m.Add("__meta_vultr_instance_main_ip", instance.MainIP)
+ m.Add("__meta_vultr_instance_internal_ip", instance.InternalIP)
+ m.Add("__meta_vultr_instance_main_ipv6", instance.V6MainIP)
+ m.Add("__meta_vultr_instance_hostname", instance.Hostname)
+ m.Add("__meta_vultr_instance_server_status", instance.ServerStatus)
+ m.Add("__meta_vultr_instance_vcpu_count", strconv.Itoa(instance.VCPUCount))
+ m.Add("__meta_vultr_instance_ram_mb", strconv.Itoa(instance.RAM))
+ m.Add("__meta_vultr_instance_allowed_bandwidth_gb", strconv.Itoa(instance.AllowedBandwidth))
+ m.Add("__meta_vultr_instance_disk_gb", strconv.Itoa(instance.Disk))
+
+ // We surround the separated list with the separator as well. This way regular expressions
+ // in relabeling rules don't have to consider feature positions.
+ if len(instance.Features) > 0 {
+ features := separator + strings.Join(instance.Features, separator) + separator
+ m.Add("__meta_vultr_instance_features", features)
+ }
+
+ if len(instance.Tags) > 0 {
+ tags := separator + strings.Join(instance.Tags, separator) + separator
+ m.Add("__meta_vultr_instance_tags", tags)
+ }
+ ms = append(ms, m)
+ }
+ return ms
+}
diff --git a/lib/promscrape/discovery/vultr/vultr_test.go b/lib/promscrape/discovery/vultr/vultr_test.go
new file mode 100644
index 000000000..572782726
--- /dev/null
+++ b/lib/promscrape/discovery/vultr/vultr_test.go
@@ -0,0 +1,96 @@
+package vultr
+
+import (
+ "testing"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
+)
+
+func TestGetInstanceLabels(t *testing.T) {
+ input := []Instance{
+ {
+ ID: "fake-id-07f7-4b68-88ac-fake-id",
+ Os: "Ubuntu 22.04 x64",
+ RAM: 1024,
+ Disk: 25,
+ MainIP: "64.176.84.27",
+ VCPUCount: 1,
+ Region: "sgp",
+ Plan: "vc2-1c-1gb",
+ AllowedBandwidth: 1,
+ ServerStatus: "installingbooting",
+ V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ Label: "vultr-sd",
+ InternalIP: "",
+ Hostname: "vultr-sd",
+ Tags: []string{"mock tags"},
+ OsID: 1743,
+ Features: []string{"ipv6"},
+ },
+ {
+ ID: "fake-id-07f7-4b68-88ac-fake-id",
+ Os: "Ubuntu 22.04 x64",
+ RAM: 1024,
+ Disk: 25,
+ MainIP: "64.176.84.27",
+ VCPUCount: 1,
+ Region: "sgp",
+ Plan: "vc2-1c-1gb",
+ AllowedBandwidth: 1,
+ ServerStatus: "installingbooting",
+ V6MainIP: "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ Label: "vultr-sd",
+ InternalIP: "",
+ Hostname: "vultr-sd",
+ Tags: []string{"mock tags"},
+ OsID: 1743,
+ Features: []string{"ipv6"},
+ },
+ }
+
+ expect := []*promutils.Labels{
+ promutils.NewLabelsFromMap(map[string]string{
+ "__address__": "64.176.84.27:8080",
+ "__meta_vultr_instance_id": "fake-id-07f7-4b68-88ac-fake-id",
+ "__meta_vultr_instance_label": "vultr-sd",
+ "__meta_vultr_instance_os": "Ubuntu 22.04 x64",
+ "__meta_vultr_instance_os_id": "1743",
+ "__meta_vultr_instance_region": "sgp",
+ "__meta_vultr_instance_plan": "vc2-1c-1gb",
+ "__meta_vultr_instance_main_ip": "64.176.84.27",
+ "__meta_vultr_instance_internal_ip": "",
+ "__meta_vultr_instance_main_ipv6": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ "__meta_vultr_instance_hostname": "vultr-sd",
+ "__meta_vultr_instance_server_status": "installingbooting",
+ "__meta_vultr_instance_vcpu_count": "1",
+ "__meta_vultr_instance_ram_mb": "1024",
+ "__meta_vultr_instance_allowed_bandwidth_gb": "1",
+ "__meta_vultr_instance_disk_gb": "25",
+ "__meta_vultr_instance_features": ",ipv6,",
+ "__meta_vultr_instance_tags": ",mock tags,",
+ }),
+ promutils.NewLabelsFromMap(map[string]string{
+ "__address__": "64.176.84.27:8080",
+ "__meta_vultr_instance_id": "fake-id-07f7-4b68-88ac-fake-id",
+ "__meta_vultr_instance_label": "vultr-sd",
+ "__meta_vultr_instance_os": "Ubuntu 22.04 x64",
+ "__meta_vultr_instance_os_id": "1743",
+ "__meta_vultr_instance_region": "sgp",
+ "__meta_vultr_instance_plan": "vc2-1c-1gb",
+ "__meta_vultr_instance_main_ip": "64.176.84.27",
+ "__meta_vultr_instance_internal_ip": "",
+ "__meta_vultr_instance_main_ipv6": "2002:18f0:4100:263a:5300:07ff:fdd7:691c",
+ "__meta_vultr_instance_hostname": "vultr-sd",
+ "__meta_vultr_instance_server_status": "installingbooting",
+ "__meta_vultr_instance_vcpu_count": "1",
+ "__meta_vultr_instance_ram_mb": "1024",
+ "__meta_vultr_instance_allowed_bandwidth_gb": "1",
+ "__meta_vultr_instance_disk_gb": "25",
+ "__meta_vultr_instance_features": ",ipv6,",
+ "__meta_vultr_instance_tags": ",mock tags,",
+ }),
+ }
+ labels := getInstanceLabels(input, 8080)
+ discoveryutils.TestEqualLabelss(t, labels, expect)
+}
diff --git a/lib/promscrape/scraper.go b/lib/promscrape/scraper.go
index 797503298..d60511b8c 100644
--- a/lib/promscrape/scraper.go
+++ b/lib/promscrape/scraper.go
@@ -30,6 +30,7 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/kuma"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/nomad"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/openstack"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/vultr"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/yandexcloud"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
"github.com/VictoriaMetrics/metrics"
@@ -140,6 +141,7 @@ func runScraper(configFile string, pushData func(at *auth.Token, wr *prompbmarsh
scs.add("kuma_sd_configs", *kuma.SDCheckInterval, func(cfg *Config, swsPrev []*ScrapeWork) []*ScrapeWork { return cfg.getKumaSDScrapeWork(swsPrev) })
scs.add("nomad_sd_configs", *nomad.SDCheckInterval, func(cfg *Config, swsPrev []*ScrapeWork) []*ScrapeWork { return cfg.getNomadSDScrapeWork(swsPrev) })
scs.add("openstack_sd_configs", *openstack.SDCheckInterval, func(cfg *Config, swsPrev []*ScrapeWork) []*ScrapeWork { return cfg.getOpenStackSDScrapeWork(swsPrev) })
+ scs.add("vultr_sd_configs", *vultr.SDCheckInterval, func(cfg *Config, swsPrev []*ScrapeWork) []*ScrapeWork { return cfg.getVultrSDScrapeWork(swsPrev) })
scs.add("yandexcloud_sd_configs", *yandexcloud.SDCheckInterval, func(cfg *Config, swsPrev []*ScrapeWork) []*ScrapeWork { return cfg.getYandexCloudSDScrapeWork(swsPrev) })
scs.add("static_configs", 0, func(cfg *Config, _ []*ScrapeWork) []*ScrapeWork { return cfg.getStaticScrapeWork() })
diff --git a/lib/promscrape/scrapework.go b/lib/promscrape/scrapework.go
index 837db6dc5..ad478dbf7 100644
--- a/lib/promscrape/scrapework.go
+++ b/lib/promscrape/scrapework.go
@@ -670,6 +670,7 @@ type writeRequestCtx struct {
writeRequest prompbmarshal.WriteRequest
labels []prompbmarshal.Label
samples []prompbmarshal.Sample
+ exemplars []prompbmarshal.Exemplar
}
func (wc *writeRequestCtx) reset() {
@@ -684,6 +685,7 @@ func (wc *writeRequestCtx) resetNoRows() {
wc.labels = wc.labels[:0]
wc.samples = wc.samples[:0]
+ wc.exemplars = wc.exemplars[:0]
}
var writeRequestCtxPool leveledWriteRequestCtxPool
@@ -902,10 +904,27 @@ func (sw *scrapeWork) addRowToTimeseries(wc *writeRequestCtx, r *parser.Row, tim
Value: r.Value,
Timestamp: sampleTimestamp,
})
+ // Add Exemplars to Timeseries
+ exemplarsLen := len(wc.exemplars)
+ exemplarTagsLen := len(r.Exemplar.Tags)
+ if exemplarTagsLen > 0 {
+ exemplarLabels := make([]prompbmarshal.Label, exemplarTagsLen)
+ for i, label := range r.Exemplar.Tags {
+ exemplarLabels[i].Name = label.Key
+ exemplarLabels[i].Value = label.Value
+ }
+ wc.exemplars = append(wc.exemplars, prompbmarshal.Exemplar{
+ Labels: exemplarLabels,
+ Value: r.Exemplar.Value,
+ Timestamp: r.Exemplar.Timestamp,
+ })
+
+ }
wr := &wc.writeRequest
wr.Timeseries = append(wr.Timeseries, prompbmarshal.TimeSeries{
- Labels: wc.labels[labelsLen:],
- Samples: wc.samples[len(wc.samples)-1:],
+ Labels: wc.labels[labelsLen:],
+ Samples: wc.samples[len(wc.samples)-1:],
+ Exemplars: wc.exemplars[exemplarsLen:],
})
}
diff --git a/lib/promscrape/scrapework_test.go b/lib/promscrape/scrapework_test.go
index 787203d29..a4a972c62 100644
--- a/lib/promscrape/scrapework_test.go
+++ b/lib/promscrape/scrapework_test.go
@@ -708,6 +708,11 @@ func TestAddRowToTimeseriesNoRelabeling(t *testing.T) {
HonorLabels: true,
},
`metric{a="e",foo="bar"} 0 123`)
+ f(`metric{foo="bar"} 0 123 # {trace_id="12345"} 52 456`,
+ &ScrapeWork{
+ HonorLabels: true,
+ },
+ `metric{foo="bar"} 0 123 # {trace_id="12345"} 52 456`)
}
func TestSendStaleSeries(t *testing.T) {
@@ -765,6 +770,8 @@ func parseData(data string) []prompbmarshal.TimeSeries {
}
rows.UnmarshalWithErrLogger(data, errLogger)
var tss []prompbmarshal.TimeSeries
+ var exemplars []prompbmarshal.Exemplar
+
for _, r := range rows.Rows {
labels := []prompbmarshal.Label{
{
@@ -778,6 +785,21 @@ func parseData(data string) []prompbmarshal.TimeSeries {
Value: tag.Value,
})
}
+ exemplarLabels := []prompbmarshal.Label{}
+ if len(r.Exemplar.Tags) > 0 {
+ for _, tag := range r.Exemplar.Tags {
+ exemplarLabels = append(exemplarLabels, prompbmarshal.Label{
+ Name: tag.Key,
+ Value: tag.Value,
+ })
+ }
+ exemplars = append(exemplars, prompbmarshal.Exemplar{
+ Labels: exemplarLabels,
+ Value: r.Exemplar.Value,
+ Timestamp: r.Exemplar.Timestamp,
+ })
+ }
+
var ts prompbmarshal.TimeSeries
ts.Labels = labels
ts.Samples = []prompbmarshal.Sample{
@@ -786,6 +808,7 @@ func parseData(data string) []prompbmarshal.TimeSeries {
Timestamp: r.Timestamp,
},
}
+ ts.Exemplars = exemplars
tss = append(tss, ts)
}
return tss
@@ -850,6 +873,19 @@ func timeseriesToString(ts *prompbmarshal.TimeSeries) string {
}
s := ts.Samples[0]
fmt.Fprintf(&sb, "%g %d", s.Value, s.Timestamp)
+ // Add Exemplars to the end of string
+ for j, exemplar := range ts.Exemplars {
+ for i, label := range exemplar.Labels {
+ fmt.Fprintf(&sb, "%s=%q", label.Name, label.Value)
+ if i+1 < len(ts.Labels) {
+ fmt.Fprintf(&sb, ",")
+ }
+ }
+ fmt.Fprintf(&sb, "%g %d", exemplar.Value, exemplar.Timestamp)
+ if j+1 < len(ts.Exemplars) {
+ fmt.Fprintf(&sb, ",")
+ }
+ }
return sb.String()
}
diff --git a/lib/protoparser/prometheus/parser.go b/lib/protoparser/prometheus/parser.go
index 923737f12..58ef46f1f 100644
--- a/lib/protoparser/prometheus/parser.go
+++ b/lib/protoparser/prometheus/parser.go
@@ -57,12 +57,33 @@ func (rs *Rows) UnmarshalWithErrLogger(s string, errLogger func(s string)) {
rs.Rows, rs.tagsPool = unmarshalRows(rs.Rows[:0], s, rs.tagsPool[:0], noEscapes, errLogger)
}
+const tagsPrefix = '{'
+const exemplarPreifx = '{'
+
+// Exemplar Item
+type Exemplar struct {
+ // Tags: a list of labels that uniquely identifies exemplar
+ Tags []Tag
+ // Value: the value of the exemplar
+ Value float64
+ // Timestamp: the time when exemplar was recorded
+ Timestamp int64
+}
+
+// Reset - resets the Exemplar object to defaults
+func (e *Exemplar) Reset() {
+ e.Tags = nil
+ e.Value = 0
+ e.Timestamp = 0
+}
+
// Row is a single Prometheus row.
type Row struct {
Metric string
Tags []Tag
Value float64
Timestamp int64
+ Exemplar Exemplar
}
func (r *Row) reset() {
@@ -70,6 +91,7 @@ func (r *Row) reset() {
r.Tags = nil
r.Value = 0
r.Timestamp = 0
+ r.Exemplar = Exemplar{}
}
func skipTrailingComment(s string) string {
@@ -110,69 +132,140 @@ func nextWhitespace(s string) int {
return n1
}
-func (r *Row) unmarshal(s string, tagsPool []Tag, noEscapes bool) ([]Tag, error) {
- r.reset()
+func parseStringToTags(s string, tagsPool []Tag, noEscapes bool) (string, []Tag, error) {
+ n := strings.IndexByte(s, tagsPrefix)
+ c := strings.IndexByte(s, '#')
+ if c != -1 && c < n {
+ return s, tagsPool, nil
+ }
s = skipLeadingWhitespace(s)
- n := strings.IndexByte(s, '{')
if n >= 0 {
// Tags found. Parse them.
- r.Metric = skipTrailingWhitespace(s[:n])
s = s[n+1:]
- tagsStart := len(tagsPool)
var err error
s, tagsPool, err = unmarshalTags(tagsPool, s, noEscapes)
if err != nil {
- return tagsPool, fmt.Errorf("cannot unmarshal tags: %w", err)
+ return s, tagsPool, fmt.Errorf("cannot unmarshal tags: %w", err)
}
if len(s) > 0 && s[0] == ' ' {
// Fast path - skip whitespace.
s = s[1:]
}
- tags := tagsPool[tagsStart:]
- r.Tags = tags[:len(tags):len(tags)]
- } else {
- // Tags weren't found. Search for value after whitespace
- n = nextWhitespace(s)
- if n < 0 {
- return tagsPool, fmt.Errorf("missing value")
- }
- r.Metric = s[:n]
- s = s[n+1:]
}
- if len(r.Metric) == 0 {
- return tagsPool, fmt.Errorf("metric cannot be empty")
+ return s, tagsPool, nil
+}
+
+var tvtPool = sync.Pool{New: func() interface{} {
+ return &tagsValueTimestamp{}
+}}
+
+func getTVT() *tagsValueTimestamp {
+ return tvtPool.Get().(*tagsValueTimestamp)
+}
+func putTVT(tvt *tagsValueTimestamp) {
+ tvt.reset()
+ tvtPool.Put(tvt)
+}
+
+type tagsValueTimestamp struct {
+ Prefix string
+ Value float64
+ Timestamp int64
+ Comments string
+}
+
+func (tvt *tagsValueTimestamp) reset() {
+ tvt.Prefix = ""
+ tvt.Value = 0
+ tvt.Timestamp = 0
+ tvt.Comments = ""
+}
+func parseTagsValueTimestamp(s string, tagsPool []Tag, noEscapes bool) ([]Tag, *tagsValueTimestamp, error) {
+ tvt := getTVT()
+ n := 0
+ // Prefix is everything up to a tag start or a space
+ t := strings.IndexByte(s, tagsPrefix)
+ // If there is no tag start process rest of string
+ mustParseTags := false
+ if t != -1 {
+ // Check to see if there is a space before tag
+ n = nextWhitespace(s)
+ // If there is a space
+ if n > 0 {
+ if n < t {
+ tvt.Prefix = s[:n]
+ s = skipLeadingWhitespace(s[n:])
+ // Cover the use case where there is whitespace between the prefix and the tag
+ if len(s) > 0 && s[0] == '{' {
+ mustParseTags = true
+ }
+ // Most likely this has an exemplar
+ } else {
+ tvt.Prefix = s[:t]
+ s = s[t:]
+ mustParseTags = true
+ }
+ }
+ if mustParseTags {
+ var err error
+ s, tagsPool, err = parseStringToTags(s, tagsPool, noEscapes)
+ if err != nil {
+ return tagsPool, tvt, err
+ }
+ }
+ } else {
+ // Tag doesn't exist
+ n = nextWhitespace(s)
+ if n != -1 {
+ tvt.Prefix = s[:n]
+ s = s[n:]
+ } else {
+ tvt.Prefix = s
+ return tagsPool, tvt, fmt.Errorf("missing value")
+ }
}
s = skipLeadingWhitespace(s)
- s = skipTrailingComment(s)
- if len(s) == 0 {
- return tagsPool, fmt.Errorf("value cannot be empty")
+ // save and remove the comments
+ n = strings.IndexByte(s, '#')
+ if n >= 0 {
+ tvt.Comments = s[n:]
+ if len(tvt.Comments) > 1 {
+ tvt.Comments = s[n+1:]
+ } else {
+ tvt.Comments = ""
+ }
+ s = skipTrailingComment(s)
+ s = skipLeadingWhitespace(s)
+ s = skipTrailingWhitespace(s)
}
n = nextWhitespace(s)
if n < 0 {
// There is no timestamp.
v, err := fastfloat.Parse(s)
if err != nil {
- return tagsPool, fmt.Errorf("cannot parse value %q: %w", s, err)
+ return tagsPool, tvt, fmt.Errorf("cannot parse value %q: %w", s, err)
}
- r.Value = v
- return tagsPool, nil
+ tvt.Value = v
+ return tagsPool, tvt, nil
}
- // There is a timestamp.
+ // There is a timestamp
+ s = skipLeadingWhitespace(s)
v, err := fastfloat.Parse(s[:n])
if err != nil {
- return tagsPool, fmt.Errorf("cannot parse value %q: %w", s[:n], err)
+ return tagsPool, tvt, fmt.Errorf("cannot parse value %q: %w", s[:n], err)
}
- r.Value = v
- s = skipLeadingWhitespace(s[n+1:])
+ tvt.Value = v
+ s = s[n:]
+ // There are some whitespaces after timestamp
+ s = skipLeadingWhitespace(s)
if len(s) == 0 {
// There is no timestamp - just a whitespace after the value.
- return tagsPool, nil
+ return tagsPool, tvt, nil
}
- // There are some whitespaces after timestamp
s = skipTrailingWhitespace(s)
ts, err := fastfloat.Parse(s)
if err != nil {
- return tagsPool, fmt.Errorf("cannot parse timestamp %q: %w", s, err)
+ return tagsPool, tvt, fmt.Errorf("cannot parse timestamp %q: %w", s, err)
}
if ts >= -1<<31 && ts < 1<<31 {
// This looks like OpenMetrics timestamp in Unix seconds.
@@ -181,7 +274,68 @@ func (r *Row) unmarshal(s string, tagsPool []Tag, noEscapes bool) ([]Tag, error)
// See https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md#timestamps
ts *= 1000
}
- r.Timestamp = int64(ts)
+ tvt.Timestamp = int64(ts)
+ return tagsPool, tvt, nil
+}
+
+// Returns possible comments that could be exemplars
+func (r *Row) unmarshalMetric(s string, tagsPool []Tag, noEscapes bool) (string, []Tag, error) {
+ tagsStart := len(tagsPool)
+ var err error
+ var tvt *tagsValueTimestamp
+ tagsPool, tvt, err = parseTagsValueTimestamp(s, tagsPool, noEscapes)
+ defer putTVT(tvt)
+ if err != nil {
+ return "", tagsPool, err
+ }
+ r.Metric = tvt.Prefix
+ tags := tagsPool[tagsStart:]
+ if len(tags) > 0 {
+ r.Tags = tags
+ }
+ r.Value = tvt.Value
+ r.Timestamp = tvt.Timestamp
+ return tvt.Comments, tagsPool, nil
+
+}
+func (e *Exemplar) unmarshal(s string, tagsPool []Tag, noEscapes bool) ([]Tag, error) {
+ // We can use the Comment parsed out to further parse the Exemplar
+ s = skipLeadingWhitespace(s)
+ // If we are a comment immediately followed by whitespace or a labelset
+ // then we are an exemplar
+ if len(s) != 0 && s[0] == exemplarPreifx {
+ var err error
+ var tvt *tagsValueTimestamp
+ tagsStart := len(tagsPool)
+ tagsPool, tvt, err = parseTagsValueTimestamp(s, tagsPool, noEscapes)
+ defer putTVT(tvt)
+ if err != nil {
+ return tagsPool, err
+ }
+ tags := tagsPool[tagsStart:]
+ if len(tags) > 0 {
+ e.Tags = tags
+ }
+ e.Value = tvt.Value
+ e.Timestamp = tvt.Timestamp
+ return tagsPool, nil
+ }
+ return tagsPool, nil
+
+}
+func (r *Row) unmarshal(s string, tagsPool []Tag, noEscapes bool) ([]Tag, error) {
+ r.reset()
+ // Parse for labels, the value and the timestamp
+ // Anything before labels is saved in Prefix we can use this
+ // for the metric name
+ comments, tagsPool, err := r.unmarshalMetric(s, tagsPool, noEscapes)
+ if err != nil {
+ return nil, err
+ }
+ tagsPool, err = r.Exemplar.unmarshal(comments, tagsPool, noEscapes)
+ if err != nil {
+ return nil, err
+ }
return tagsPool, nil
}
diff --git a/lib/protoparser/prometheus/parser_test.go b/lib/protoparser/prometheus/parser_test.go
index 39116c937..ff95f25b1 100644
--- a/lib/protoparser/prometheus/parser_test.go
+++ b/lib/protoparser/prometheus/parser_test.go
@@ -362,12 +362,87 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
Value: 56,
}},
})
-
- // Exemplars - see https://github.com/OpenObservability/OpenMetrics/blob/master/OpenMetrics.md#exemplars-1
- f(`foo_bucket{le="10",a="#b"} 17 # {trace_id="oHg5SJ#YRHA0"} 9.8 1520879607.789
- abc 123 456 # foobar
- foo 344#bar`, &Rows{
+ // Support for Exemplars Open Metric Specification
+ // see: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#exemplars-1
+ f(`foo_bucket{le="25"} 17 # {trace_id="oHg5SJYRHA0", log_id="test_id"} 9.8 1520879607.789`, &Rows{
Rows: []Row{
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "le",
+ Value: "25",
+ },
+ },
+ Value: 17,
+ Exemplar: Exemplar{
+ Value: 9.8,
+ Tags: []Tag{
+ {
+ Key: "trace_id",
+ Value: "oHg5SJYRHA0",
+ },
+ {
+ Key: "log_id",
+ Value: "test_id",
+ },
+ },
+ Timestamp: 1520879607789,
+ },
+ },
+ }})
+ f(`foo_bucket{le="0.01"} 0
+foo_bucket{le="0.1"} 8 # {} 0.054
+foo_bucket{le="1"} 11 # {trace_id="KOO5S4vxi0o"} 0.67
+foo_bucket{le="10"} 17 # {trace_id="oHg5SJYRHA0"} 9.8 1520879607.789
+foo_bucket{le="25"} 17 # {trace_id="oHg5SJYRHA0", log_id="test_id"} 9.8 1520879607.789
+foo_bucket{nospace="exemplar"} 17 #{trace_id="oHg5SJYRHA0"} 9.8 1520879607.789
+foo_bucket{le="+Inf"} 17
+foo_count 17
+foo_sum 324789.3
+foo_created 1520430000.123`, &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "le",
+ Value: "0.01",
+ },
+ },
+ },
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "le",
+ Value: "0.1",
+ },
+ },
+ Value: 8,
+ Exemplar: Exemplar{
+ Value: 0.054,
+ },
+ },
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "le",
+ Value: "1",
+ },
+ },
+ Value: 11,
+ Exemplar: Exemplar{
+ Value: 0.67,
+ Tags: []Tag{
+ {
+ Key: "trace_id",
+ Value: "KOO5S4vxi0o",
+ },
+ },
+ },
+ },
{
Metric: "foo_bucket",
Tags: []Tag{
@@ -375,21 +450,84 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
Key: "le",
Value: "10",
},
+ },
+ Value: 17,
+ Exemplar: Exemplar{
+ Value: 9.8,
+ Tags: []Tag{
+ {
+ Key: "trace_id",
+ Value: "oHg5SJYRHA0",
+ },
+ },
+ Timestamp: 1520879607789,
+ },
+ },
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
{
- Key: "a",
- Value: "#b",
+ Key: "le",
+ Value: "25",
+ },
+ },
+ Value: 17,
+ Exemplar: Exemplar{
+ Value: 9.8,
+ Tags: []Tag{
+ {
+ Key: "trace_id",
+ Value: "oHg5SJYRHA0",
+ },
+ {
+ Key: "log_id",
+ Value: "test_id",
+ },
+ },
+ Timestamp: 1520879607789,
+ },
+ },
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "nospace",
+ Value: "exemplar",
+ },
+ },
+ Value: 17,
+ Exemplar: Exemplar{
+ Value: 9.8,
+ Tags: []Tag{
+ {
+ Key: "trace_id",
+ Value: "oHg5SJYRHA0",
+ },
+ },
+ Timestamp: 1520879607789,
+ },
+ },
+ {
+ Metric: "foo_bucket",
+ Tags: []Tag{
+ {
+ Key: "le",
+ Value: "+Inf",
},
},
Value: 17,
},
{
- Metric: "abc",
- Value: 123,
- Timestamp: 456000,
+ Metric: "foo_count",
+ Value: 17,
},
{
- Metric: "foo",
- Value: 344,
+ Metric: "foo_sum",
+ Value: 324789.3,
+ },
+ {
+ Metric: "foo_created",
+ Value: 1520430000.123,
},
},
})
diff --git a/lib/protoparser/prometheus/parser_timing_test.go b/lib/protoparser/prometheus/parser_timing_test.go
index 8d6a2827b..acabb7460 100644
--- a/lib/protoparser/prometheus/parser_timing_test.go
+++ b/lib/protoparser/prometheus/parser_timing_test.go
@@ -146,10 +146,10 @@ container_ulimits_soft{container="kube-scheduler",id="/kubelet/kubepods/burstabl
}
func BenchmarkRowsUnmarshal(b *testing.B) {
- s := `cpu_usage{mode="user"} 1.23
-cpu_usage{mode="system"} 23.344
-cpu_usage{mode="iowait"} 3.3443
-cpu_usage{mode="irq"} 0.34432
+ s := `foo_bucket{le="0.01"} 0
+ foo_bucket{le="1"} 11 # {trace_id="KOO5S4vxi0o"} 0.67
+ foo_bucket{le="10"} 17 # {trace_id="oHg5SJYRHA0"} 9.8 1520879607.789
+ foo_bucket{nospace="exemplar"} 17 #{trace_id="oHg5SJYRHA0"} 9.8 1520879607.789
`
b.SetBytes(int64(len(s)))
b.ReportAllocs()
diff --git a/lib/protoparser/statsd/parser.go b/lib/protoparser/statsd/parser.go
new file mode 100644
index 000000000..3ae9800d6
--- /dev/null
+++ b/lib/protoparser/statsd/parser.go
@@ -0,0 +1,226 @@
+package statsd
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
+ "github.com/VictoriaMetrics/metrics"
+ "github.com/valyala/fastjson/fastfloat"
+)
+
+// Statsd metric format with tags: MetricName:value|type|@sample_rate|#tag1:value,tag1...
+const statsdSeparator = '|'
+const statsdPairsSeparator = ':'
+const statsdTagsStartSeparator = '#'
+const statsdTagsSeparator = ','
+
+// Rows contains parsed statsd rows.
+type Rows struct {
+ Rows []Row
+
+ tagsPool []Tag
+}
+
+// Reset resets rs.
+func (rs *Rows) Reset() {
+ // Reset items, so they can be GC'ed
+
+ for i := range rs.Rows {
+ rs.Rows[i].reset()
+ }
+ rs.Rows = rs.Rows[:0]
+
+ for i := range rs.tagsPool {
+ rs.tagsPool[i].reset()
+ }
+ rs.tagsPool = rs.tagsPool[:0]
+}
+
+// Unmarshal unmarshals statsd plaintext protocol rows from s.
+//
+// s shouldn't be modified when rs is in use.
+func (rs *Rows) Unmarshal(s string) {
+ rs.Rows, rs.tagsPool = unmarshalRows(rs.Rows[:0], s, rs.tagsPool[:0])
+}
+
+// Row is a single statsd row.
+type Row struct {
+ Metric string
+ Tags []Tag
+ Value float64
+ Timestamp int64
+}
+
+func (r *Row) reset() {
+ r.Metric = ""
+ r.Tags = nil
+ r.Value = 0
+ r.Timestamp = 0
+}
+
+func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) {
+ r.reset()
+ originalString := s
+ s = stripTrailingWhitespace(s)
+ separatorPosition := strings.IndexByte(s, statsdSeparator)
+ if separatorPosition < 0 {
+ s = stripTrailingWhitespace(s)
+ } else {
+ s = stripTrailingWhitespace(s[:separatorPosition])
+ }
+
+ valuesSeparatorPosition := strings.LastIndexByte(s, statsdPairsSeparator)
+
+ if valuesSeparatorPosition == 0 {
+ return tagsPool, fmt.Errorf("cannot find metric name for %q", s)
+ }
+
+ if valuesSeparatorPosition < 0 {
+ return tagsPool, fmt.Errorf("cannot find separator for %q", s)
+ }
+
+ r.Metric = s[:valuesSeparatorPosition]
+ valueStr := s[valuesSeparatorPosition+1:]
+
+ v, err := fastfloat.Parse(valueStr)
+ if err != nil {
+ return tagsPool, fmt.Errorf("cannot unmarshal value from %q: %w; original line: %q", valueStr, err, originalString)
+ }
+ r.Value = v
+
+ // parsing tags
+ tagsSeparatorPosition := strings.LastIndexByte(originalString, statsdTagsStartSeparator)
+
+ if tagsSeparatorPosition < 0 {
+ // no tags
+ return tagsPool, nil
+ }
+
+ tagsStart := len(tagsPool)
+ tagsPool = unmarshalTags(tagsPool, originalString[tagsSeparatorPosition+1:])
+ tags := tagsPool[tagsStart:]
+ r.Tags = tags[:len(tags):len(tags)]
+
+ return tagsPool, nil
+}
+
+func unmarshalRows(dst []Row, s string, tagsPool []Tag) ([]Row, []Tag) {
+ for len(s) > 0 {
+ n := strings.IndexByte(s, '\n')
+ if n < 0 {
+ // The last line.
+ return unmarshalRow(dst, s, tagsPool)
+ }
+ dst, tagsPool = unmarshalRow(dst, s[:n], tagsPool)
+ s = s[n+1:]
+ }
+ return dst, tagsPool
+}
+
+func unmarshalRow(dst []Row, s string, tagsPool []Tag) ([]Row, []Tag) {
+ if len(s) > 0 && s[len(s)-1] == '\r' {
+ s = s[:len(s)-1]
+ }
+ s = stripLeadingWhitespace(s)
+ if len(s) == 0 {
+ // Skip empty line
+ return dst, tagsPool
+ }
+ if cap(dst) > len(dst) {
+ dst = dst[:len(dst)+1]
+ } else {
+ dst = append(dst, Row{})
+ }
+ r := &dst[len(dst)-1]
+ var err error
+ tagsPool, err = r.unmarshal(s, tagsPool)
+ if err != nil {
+ dst = dst[:len(dst)-1]
+ logger.Errorf("cannot unmarshal Statsd line %q: %s", s, err)
+ invalidLines.Inc()
+ }
+ return dst, tagsPool
+}
+
+var invalidLines = metrics.NewCounter(`vm_rows_invalid_total{type="statsd"}`)
+
+func unmarshalTags(dst []Tag, s string) []Tag {
+ for {
+ if cap(dst) > len(dst) {
+ dst = dst[:len(dst)+1]
+ } else {
+ dst = append(dst, Tag{})
+ }
+ tag := &dst[len(dst)-1]
+
+ n := strings.IndexByte(s, statsdTagsSeparator)
+
+ if n < 0 {
+ // The last tag found
+ tag.unmarshal(s)
+ if len(tag.Key) == 0 || len(tag.Value) == 0 {
+ // Skip empty tag
+ dst = dst[:len(dst)-1]
+ }
+ return dst
+ }
+ tag.unmarshal(s[:n])
+ s = s[n+1:]
+ if len(tag.Key) == 0 || len(tag.Value) == 0 {
+ // Skip empty tag
+ dst = dst[:len(dst)-1]
+ }
+ }
+}
+
+// Tag is a statsd tag.
+type Tag struct {
+ Key string
+ Value string
+}
+
+func (t *Tag) reset() {
+ t.Key = ""
+ t.Value = ""
+}
+
+func (t *Tag) unmarshal(s string) {
+ t.reset()
+ n := strings.IndexByte(s, statsdPairsSeparator)
+ if n < 0 {
+ // Empty tag value.
+ // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1100
+ t.Key = s
+ t.Value = s[len(s):]
+ } else {
+ t.Key = s[:n]
+ t.Value = s[n+1:]
+ }
+}
+
+func stripTrailingWhitespace(s string) string {
+ n := len(s)
+ for {
+ n--
+ if n < 0 {
+ return ""
+ }
+ ch := s[n]
+
+ if ch != ' ' && ch != '\t' {
+ return s[:n+1]
+ }
+ }
+}
+
+func stripLeadingWhitespace(s string) string {
+ for len(s) > 0 {
+ ch := s[0]
+ if ch != ' ' && ch != '\t' {
+ return s
+ }
+ s = s[1:]
+ }
+ return ""
+}
diff --git a/lib/protoparser/statsd/parser_test.go b/lib/protoparser/statsd/parser_test.go
new file mode 100644
index 000000000..aeb498bb7
--- /dev/null
+++ b/lib/protoparser/statsd/parser_test.go
@@ -0,0 +1,367 @@
+package statsd
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestUnmarshalTagsSuccess(t *testing.T) {
+ f := func(dst []Tag, s string, tagsPoolExpected []Tag) {
+ t.Helper()
+
+ tagsPool := unmarshalTags(dst, s)
+ if !reflect.DeepEqual(tagsPool, tagsPoolExpected) {
+ t.Fatalf("unexpected tags;\ngot\n%+v;\nwant\n%+v", tagsPool, tagsPoolExpected)
+ }
+
+ // Try unmarshaling again
+ tagsPool = unmarshalTags(dst, s)
+ if !reflect.DeepEqual(tagsPool, tagsPoolExpected) {
+ t.Fatalf("unexpected tags on second unmarshal;\ngot\n%+v;\nwant\n%+v", tagsPool, tagsPoolExpected)
+ }
+ }
+
+ f([]Tag{}, "foo:bar", []Tag{
+ {
+ Key: "foo",
+ Value: "bar",
+ },
+ })
+
+ f([]Tag{}, "foo:bar,qwe:123", []Tag{
+ {
+ Key: "foo",
+ Value: "bar",
+ },
+ {
+ Key: "qwe",
+ Value: "123",
+ },
+ })
+
+ f([]Tag{}, "foo.qwe:bar", []Tag{
+ {
+ Key: "foo.qwe",
+ Value: "bar",
+ },
+ })
+
+ f([]Tag{}, "foo:10", []Tag{
+ {
+ Key: "foo",
+ Value: "10",
+ },
+ })
+
+ f([]Tag{}, "foo: _qwe", []Tag{
+ {
+ Key: "foo",
+ Value: " _qwe",
+ },
+ })
+
+ f([]Tag{}, "foo:qwe ", []Tag{
+ {
+ Key: "foo",
+ Value: "qwe ",
+ },
+ })
+
+ f([]Tag{}, "foo asd:qwe ", []Tag{
+ {
+ Key: "foo asd",
+ Value: "qwe ",
+ },
+ })
+
+ f([]Tag{}, "foo:var:123", []Tag{
+ {
+ Key: "foo",
+ Value: "var:123",
+ },
+ })
+
+ // invalid tags
+ f([]Tag{}, ":bar", []Tag{})
+ f([]Tag{}, "foo:", []Tag{})
+ f([]Tag{}, " ", []Tag{})
+}
+
+func TestRowsUnmarshalSuccess(t *testing.T) {
+ f := func(s string, rowsExpected *Rows) {
+ t.Helper()
+ var rows Rows
+ rows.Unmarshal(s)
+ if !reflect.DeepEqual(rows.Rows, rowsExpected.Rows) {
+ t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows.Rows, rowsExpected.Rows)
+ }
+
+ // Try unmarshaling again
+ rows.Unmarshal(s)
+ if !reflect.DeepEqual(rows.Rows, rowsExpected.Rows) {
+ t.Fatalf("unexpected rows on second unmarshal;\ngot\n%+v;\nwant\n%+v", rows.Rows, rowsExpected.Rows)
+ }
+
+ rows.Reset()
+ if len(rows.Rows) != 0 {
+ t.Fatalf("non-empty rows after reset: %+v", rows.Rows)
+ }
+ }
+
+ // Empty line
+ f("", &Rows{})
+ f("\r", &Rows{})
+ f("\n\n", &Rows{})
+ f("\n\r\n", &Rows{})
+
+ // Single line
+ f(" 123:455", &Rows{
+ Rows: []Row{{
+ Metric: "123",
+ Value: 455,
+ }},
+ })
+ f("123:455 |c", &Rows{
+ Rows: []Row{{
+ Metric: "123",
+ Value: 455,
+ }},
+ })
+ f("foobar:-123.456|c", &Rows{
+ Rows: []Row{{
+ Metric: "foobar",
+ Value: -123.456,
+ }},
+ })
+ f("foo.bar:123.456|c\n", &Rows{
+ Rows: []Row{{
+ Metric: "foo.bar",
+ Value: 123.456,
+ }},
+ })
+
+ // with sample rate
+ f("foo.bar:1|c|@0.1", &Rows{
+ Rows: []Row{{
+ Metric: "foo.bar",
+ Value: 1,
+ }},
+ })
+
+ // without specifying metric unit
+ f("foo.bar:123", &Rows{
+ Rows: []Row{{
+ Metric: "foo.bar",
+ Value: 123,
+ }},
+ })
+ // without specifying metric unit but with tags
+ f("foo.bar:123|#foo:bar", &Rows{
+ Rows: []Row{{
+ Metric: "foo.bar",
+ Value: 123,
+ Tags: []Tag{
+ {
+ Key: "foo",
+ Value: "bar",
+ },
+ },
+ }},
+ })
+
+ f("foo.bar:123.456|c|#foo:bar,qwe:asd", &Rows{
+ Rows: []Row{{
+ Metric: "foo.bar",
+ Value: 123.456,
+ Tags: []Tag{
+ {
+ Key: "foo",
+ Value: "bar",
+ },
+ {
+ Key: "qwe",
+ Value: "asd",
+ },
+ },
+ }},
+ })
+
+ // Whitespace in metric name, tag name and tag value
+ f("s a:1|c|#ta g1:aaa1,tag2:bb b2", &Rows{
+ Rows: []Row{{
+ Metric: "s a",
+ Value: 1,
+ Tags: []Tag{
+ {
+ Key: "ta g1",
+ Value: "aaa1",
+ },
+ {
+ Key: "tag2",
+ Value: "bb b2",
+ },
+ },
+ }},
+ })
+
+ // Tags
+ f("foo:1|c", &Rows{
+ Rows: []Row{{
+ Metric: "foo",
+ Value: 1,
+ }},
+ })
+ // Empty tag name
+ f("foo:1|#:123", &Rows{
+ Rows: []Row{{
+ Metric: "foo",
+ Tags: []Tag{},
+ Value: 1,
+ }},
+ })
+ // Empty tag value
+ f("foo:1|#tag1:", &Rows{
+ Rows: []Row{{
+ Metric: "foo",
+ Tags: []Tag{},
+ Value: 1,
+ }},
+ })
+ f("foo:1|#bar:baz,aa:,x:y,:z", &Rows{
+ Rows: []Row{{
+ Metric: "foo",
+ Tags: []Tag{
+ {
+ Key: "bar",
+ Value: "baz",
+ },
+ {
+ Key: "x",
+ Value: "y",
+ },
+ },
+ Value: 1,
+ }},
+ })
+
+ // Multi lines
+ f("foo:0.3|c\naaa:3|g\nbar.baz:0.34|c\n", &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo",
+ Value: 0.3,
+ },
+ {
+ Metric: "aaa",
+ Value: 3,
+ },
+ {
+ Metric: "bar.baz",
+ Value: 0.34,
+ },
+ },
+ })
+
+ f("foo:0.3|c|#tag1:1,tag2:2\naaa:3|g|#tag3:3,tag4:4", &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo",
+ Value: 0.3,
+ Tags: []Tag{
+ {
+ Key: "tag1",
+ Value: "1",
+ },
+ {
+ Key: "tag2",
+ Value: "2",
+ },
+ },
+ },
+ {
+ Metric: "aaa",
+ Value: 3,
+ Tags: []Tag{
+ {
+ Key: "tag3",
+ Value: "3",
+ },
+ {
+ Key: "tag4",
+ Value: "4",
+ },
+ },
+ },
+ },
+ })
+
+ // Multi lines with invalid line
+ f("foo:0.3|c\naaa\nbar.baz:0.34\n", &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo",
+ Value: 0.3,
+ },
+ {
+ Metric: "bar.baz",
+ Value: 0.34,
+ },
+ },
+ })
+
+ // Whitespace after at the end
+ f("foo.baz:125|c\na:1.34\t ", &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo.baz",
+ Value: 125,
+ },
+ {
+ Metric: "a",
+ Value: 1.34,
+ },
+ },
+ })
+
+ // ignores sample rate
+ f("foo.baz:125|c|@0.5#tag1:12", &Rows{
+ Rows: []Row{
+ {
+ Metric: "foo.baz",
+ Value: 125,
+ Tags: []Tag{
+ {
+ Key: "tag1",
+ Value: "12",
+ },
+ },
+ },
+ },
+ })
+}
+
+func TestRowsUnmarshalFailure(t *testing.T) {
+ f := func(s string) {
+ t.Helper()
+ var rows Rows
+ rows.Unmarshal(s)
+ if len(rows.Rows) != 0 {
+ t.Fatalf("unexpected number of rows parsed; got %d; want 0", len(rows.Rows))
+ }
+
+ // Try again
+ rows.Unmarshal(s)
+ if len(rows.Rows) != 0 {
+ t.Fatalf("unexpected number of rows parsed; got %d; want 0", len(rows.Rows))
+ }
+ }
+
+ // random string
+ f("aaa")
+
+ // empty value
+ f("foo:")
+
+ // empty metric name
+ f(":12")
+}
diff --git a/lib/protoparser/statsd/parser_timing_test.go b/lib/protoparser/statsd/parser_timing_test.go
new file mode 100644
index 000000000..d9e3c6479
--- /dev/null
+++ b/lib/protoparser/statsd/parser_timing_test.go
@@ -0,0 +1,25 @@
+package statsd
+
+import (
+ "fmt"
+ "testing"
+)
+
+func BenchmarkRowsUnmarshal(b *testing.B) {
+ s := `cpu.usage_user:1.23|c
+cpu.usage_system:23.344|c
+cpu.usage_iowait:3.3443|c
+cpu.usage_irq:0.34432|c
+`
+ b.SetBytes(int64(len(s)))
+ b.ReportAllocs()
+ b.RunParallel(func(pb *testing.PB) {
+ var rows Rows
+ for pb.Next() {
+ rows.Unmarshal(s)
+ if len(rows.Rows) != 4 {
+ panic(fmt.Errorf("unexpected number of rows unmarshaled: got %d; want 4", len(rows.Rows)))
+ }
+ }
+ })
+}
diff --git a/lib/protoparser/statsd/stream/streamparser.go b/lib/protoparser/statsd/stream/streamparser.go
new file mode 100644
index 000000000..27d9e4027
--- /dev/null
+++ b/lib/protoparser/statsd/stream/streamparser.go
@@ -0,0 +1,218 @@
+package stream
+
+import (
+ "bufio"
+ "flag"
+ "fmt"
+ "io"
+ "sync"
+ "time"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/common"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/statsd"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/writeconcurrencylimiter"
+ "github.com/VictoriaMetrics/metrics"
+)
+
+var (
+ trimTimestamp = flag.Duration("statsdTrimTimestamp", time.Second, "Trim timestamps for Statsd data to this duration. "+
+ "Minimum practical duration is 1s. Higher duration (i.e. 1m) may be used for reducing disk space usage for timestamp data")
+)
+
+// Parse parses Statsd lines from r and calls callback for the parsed rows.
+//
+// The callback can be called concurrently multiple times for streamed data from r.
+//
+// callback shouldn't hold rows after returning.
+func Parse(r io.Reader, isGzipped bool, callback func(rows []statsd.Row) error) error {
+ wcr := writeconcurrencylimiter.GetReader(r)
+ defer writeconcurrencylimiter.PutReader(wcr)
+ r = wcr
+
+ if isGzipped {
+ zr, err := common.GetGzipReader(r)
+ if err != nil {
+ return fmt.Errorf("cannot read gzipped statsd data: %w", err)
+ }
+ defer common.PutGzipReader(zr)
+ r = zr
+ }
+
+ ctx := getStreamContext(r)
+ defer putStreamContext(ctx)
+
+ for ctx.Read() {
+ uw := getUnmarshalWork()
+ uw.ctx = ctx
+ uw.callback = callback
+ uw.reqBuf, ctx.reqBuf = ctx.reqBuf, uw.reqBuf
+ ctx.wg.Add(1)
+ common.ScheduleUnmarshalWork(uw)
+ wcr.DecConcurrency()
+ }
+ ctx.wg.Wait()
+ if err := ctx.Error(); err != nil {
+ return err
+ }
+ return ctx.callbackErr
+}
+
+func (ctx *streamContext) Read() bool {
+ readCalls.Inc()
+ if ctx.err != nil || ctx.hasCallbackError() {
+ return false
+ }
+ ctx.reqBuf, ctx.tailBuf, ctx.err = common.ReadLinesBlock(ctx.br, ctx.reqBuf, ctx.tailBuf)
+ if ctx.err != nil {
+ if ctx.err != io.EOF {
+ readErrors.Inc()
+ ctx.err = fmt.Errorf("cannot read statsd plaintext protocol data: %w", ctx.err)
+ }
+ return false
+ }
+ return true
+}
+
+type streamContext struct {
+ br *bufio.Reader
+ reqBuf []byte
+ tailBuf []byte
+ err error
+
+ wg sync.WaitGroup
+ callbackErrLock sync.Mutex
+ callbackErr error
+}
+
+func (ctx *streamContext) Error() error {
+ if ctx.err == io.EOF {
+ return nil
+ }
+ return ctx.err
+}
+
+func (ctx *streamContext) hasCallbackError() bool {
+ ctx.callbackErrLock.Lock()
+ ok := ctx.callbackErr != nil
+ ctx.callbackErrLock.Unlock()
+ return ok
+}
+
+func (ctx *streamContext) reset() {
+ ctx.br.Reset(nil)
+ ctx.reqBuf = ctx.reqBuf[:0]
+ ctx.tailBuf = ctx.tailBuf[:0]
+ ctx.err = nil
+ ctx.callbackErr = nil
+}
+
+var (
+ readCalls = metrics.NewCounter(`vm_protoparser_read_calls_total{type="statsd"}`)
+ readErrors = metrics.NewCounter(`vm_protoparser_read_errors_total{type="statsd"}`)
+ rowsRead = metrics.NewCounter(`vm_protoparser_rows_read_total{type="statsd"}`)
+)
+
+func getStreamContext(r io.Reader) *streamContext {
+ select {
+ case ctx := <-streamContextPoolCh:
+ ctx.br.Reset(r)
+ return ctx
+ default:
+ if v := streamContextPool.Get(); v != nil {
+ ctx := v.(*streamContext)
+ ctx.br.Reset(r)
+ return ctx
+ }
+ return &streamContext{
+ br: bufio.NewReaderSize(r, 64*1024),
+ }
+ }
+}
+
+func putStreamContext(ctx *streamContext) {
+ ctx.reset()
+ select {
+ case streamContextPoolCh <- ctx:
+ default:
+ streamContextPool.Put(ctx)
+ }
+}
+
+var streamContextPool sync.Pool
+var streamContextPoolCh = make(chan *streamContext, cgroup.AvailableCPUs())
+
+type unmarshalWork struct {
+ rows statsd.Rows
+ ctx *streamContext
+ callback func(rows []statsd.Row) error
+ reqBuf []byte
+}
+
+func (uw *unmarshalWork) reset() {
+ uw.rows.Reset()
+ uw.ctx = nil
+ uw.callback = nil
+ uw.reqBuf = uw.reqBuf[:0]
+}
+
+func (uw *unmarshalWork) runCallback(rows []statsd.Row) {
+ ctx := uw.ctx
+ if err := uw.callback(rows); err != nil {
+ ctx.callbackErrLock.Lock()
+ if ctx.callbackErr == nil {
+ ctx.callbackErr = fmt.Errorf("error when processing imported data: %w", err)
+ }
+ ctx.callbackErrLock.Unlock()
+ }
+ ctx.wg.Done()
+}
+
+// Unmarshal implements common.UnmarshalWork
+func (uw *unmarshalWork) Unmarshal() {
+ uw.rows.Unmarshal(bytesutil.ToUnsafeString(uw.reqBuf))
+ rows := uw.rows.Rows
+ rowsRead.Add(len(rows))
+
+ // Fill missing timestamps with the current timestamp rounded to seconds.
+ currentTimestamp := int64(fasttime.UnixTimestamp())
+ for i := range rows {
+ r := &rows[i]
+ if r.Timestamp == 0 || r.Timestamp == -1 {
+ r.Timestamp = currentTimestamp
+ }
+ }
+
+ // Convert timestamps from seconds to milliseconds.
+ for i := range rows {
+ rows[i].Timestamp *= 1e3
+ }
+
+ // Trim timestamps if required.
+ if tsTrim := trimTimestamp.Milliseconds(); tsTrim > 1000 {
+ for i := range rows {
+ row := &rows[i]
+ row.Timestamp -= row.Timestamp % tsTrim
+ }
+ }
+
+ uw.runCallback(rows)
+ putUnmarshalWork(uw)
+}
+
+func getUnmarshalWork() *unmarshalWork {
+ v := unmarshalWorkPool.Get()
+ if v == nil {
+ return &unmarshalWork{}
+ }
+ return v.(*unmarshalWork)
+}
+
+func putUnmarshalWork(uw *unmarshalWork) {
+ uw.reset()
+ unmarshalWorkPool.Put(uw)
+}
+
+var unmarshalWorkPool sync.Pool
diff --git a/lib/protoparser/statsd/stream/streamparser_test.go b/lib/protoparser/statsd/stream/streamparser_test.go
new file mode 100644
index 000000000..8800dfd45
--- /dev/null
+++ b/lib/protoparser/statsd/stream/streamparser_test.go
@@ -0,0 +1,60 @@
+package stream
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
+ "github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/statsd"
+)
+
+func Test_streamContext_Read(t *testing.T) {
+ f := func(s string, rowsExpected *statsd.Rows) {
+ t.Helper()
+ ctx := getStreamContext(strings.NewReader(s))
+ if !ctx.Read() {
+ t.Fatalf("expecting successful read")
+ }
+ uw := getUnmarshalWork()
+ callbackCalls := 0
+ uw.ctx = ctx
+ uw.callback = func(rows []statsd.Row) error {
+ callbackCalls++
+ if len(rows) != len(rowsExpected.Rows) {
+ t.Fatalf("different len of expected rows;\ngot\n%+v;\nwant\n%+v", rows, rowsExpected.Rows)
+ }
+ if !reflect.DeepEqual(rows, rowsExpected.Rows) {
+ t.Fatalf("unexpected rows;\ngot\n%+v;\nwant\n%+v", rows, rowsExpected.Rows)
+ }
+ return nil
+ }
+ uw.reqBuf = append(uw.reqBuf[:0], ctx.reqBuf...)
+ ctx.wg.Add(1)
+ uw.Unmarshal()
+ if callbackCalls != 1 {
+ t.Fatalf("unexpected number of callback calls; got %d; want 1", callbackCalls)
+ }
+ }
+
+ // Full line without tags
+ f("aaa:1123|c", &statsd.Rows{
+ Rows: []statsd.Row{{
+ Metric: "aaa",
+ Value: 1123,
+ Timestamp: int64(fasttime.UnixTimestamp()) * 1000,
+ }},
+ })
+ // Full line with tags
+ f("aaa:1123|c|#x:y", &statsd.Rows{
+ Rows: []statsd.Row{{
+ Metric: "aaa",
+ Tags: []statsd.Tag{{
+ Key: "x",
+ Value: "y",
+ }},
+ Value: 1123,
+ Timestamp: int64(fasttime.UnixTimestamp()) * 1000,
+ }},
+ })
+}
diff --git a/lib/streamaggr/dedup_timing_test.go b/lib/streamaggr/dedup_timing_test.go
index 2b906fe39..abb1d0451 100644
--- a/lib/streamaggr/dedup_timing_test.go
+++ b/lib/streamaggr/dedup_timing_test.go
@@ -7,7 +7,6 @@ import (
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
- "github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
)
func BenchmarkDedupAggr(b *testing.B) {
@@ -50,7 +49,6 @@ func benchmarkDedupAggr(b *testing.B, samplesPerPush int) {
}
func newBenchSamples(count int) []pushSample {
- var lc promutils.LabelsCompressor
labels := []prompbmarshal.Label{
{
Name: "app",
@@ -82,7 +80,7 @@ func newBenchSamples(count int) []pushSample {
Name: "app",
Value: fmt.Sprintf("instance-%d", i),
})
- keyBuf = compressLabels(keyBuf[:0], &lc, labels[:labelsLen], labels[labelsLen:])
+ keyBuf = compressLabels(keyBuf[:0], labels[:labelsLen], labels[labelsLen:])
sample.key = string(keyBuf)
sample.value = float64(i)
}
diff --git a/lib/streamaggr/deduplicator.go b/lib/streamaggr/deduplicator.go
index 9cc3fee22..a96d765c2 100644
--- a/lib/streamaggr/deduplicator.go
+++ b/lib/streamaggr/deduplicator.go
@@ -15,7 +15,6 @@ import (
// Deduplicator deduplicates samples per each time series.
type Deduplicator struct {
da *dedupAggr
- lc promutils.LabelsCompressor
dropLabels []string
@@ -38,8 +37,7 @@ type Deduplicator struct {
// MustStop must be called on the returned deduplicator in order to free up occupied resources.
func NewDeduplicator(pushFunc PushFunc, dedupInterval time.Duration, dropLabels []string) *Deduplicator {
d := &Deduplicator{
- da: newDedupAggr(),
-
+ da: newDedupAggr(),
dropLabels: dropLabels,
stopCh: make(chan struct{}),
@@ -54,13 +52,6 @@ func NewDeduplicator(pushFunc PushFunc, dedupInterval time.Duration, dropLabels
return float64(d.da.itemsCount())
})
- _ = ms.NewGauge(`vm_streamaggr_labels_compressor_size_bytes`, func() float64 {
- return float64(d.lc.SizeBytes())
- })
- _ = ms.NewGauge(`vm_streamaggr_labels_compressor_items_count`, func() float64 {
- return float64(d.lc.ItemsCount())
- })
-
d.dedupFlushDuration = ms.GetOrCreateHistogram(`vm_streamaggr_dedup_flush_duration_seconds`)
d.dedupFlushTimeouts = ms.GetOrCreateCounter(`vm_streamaggr_dedup_flush_timeouts_total`)
@@ -103,7 +94,7 @@ func (d *Deduplicator) Push(tss []prompbmarshal.TimeSeries) {
}
labels.Sort()
- buf = d.lc.Compress(buf[:0], labels.Labels)
+ buf = lc.Compress(buf[:0], labels.Labels)
key := bytesutil.InternBytes(buf)
for _, s := range ts.Samples {
pss = append(pss, pushSample{
@@ -155,7 +146,7 @@ func (d *Deduplicator) flush(pushFunc PushFunc, dedupInterval time.Duration) {
samples := ctx.samples
for _, ps := range pss {
labelsLen := len(labels)
- labels = decompressLabels(labels, &d.lc, ps.key)
+ labels = decompressLabels(labels, ps.key)
samplesLen := len(samples)
samples = append(samples, prompbmarshal.Sample{
diff --git a/lib/streamaggr/streamaggr.go b/lib/streamaggr/streamaggr.go
index 06d281f69..3e5b72ecd 100644
--- a/lib/streamaggr/streamaggr.go
+++ b/lib/streamaggr/streamaggr.go
@@ -45,6 +45,19 @@ var supportedOutputs = []string{
"quantiles(phi1, ..., phiN)",
}
+var (
+ // lc contains information about all compressed labels for streaming aggregation
+ lc promutils.LabelsCompressor
+
+ _ = metrics.NewGauge(`vm_streamaggr_labels_compressor_size_bytes`, func() float64 {
+ return float64(lc.SizeBytes())
+ })
+
+ _ = metrics.NewGauge(`vm_streamaggr_labels_compressor_items_count`, func() float64 {
+ return float64(lc.ItemsCount())
+ })
+)
+
// LoadFromFile loads Aggregators from the given path and uses the given pushFunc for pushing the aggregated data.
//
// opts can contain additional options. If opts is nil, then default options are used.
@@ -111,6 +124,13 @@ type Options struct {
//
// This option can be overridden individually per each aggregation via ignore_old_samples option.
IgnoreOldSamples bool
+
+ // IgnoreFirstIntervals sets amount of aggregation intervals to ignore on start.
+ //
+ // By default, no intervals will be ignored.
+ //
+ // This option can be overridden individually per each aggregation via ignore_first_intervals option.
+ IgnoreFirstIntervals int
}
// Config is a configuration for a single stream aggregation.
@@ -175,6 +195,9 @@ type Config struct {
// IgnoreOldSamples instructs to ignore samples with old timestamps outside the current aggregation interval.
IgnoreOldSamples *bool `yaml:"ignore_old_samples,omitempty"`
+ // IgnoreFirstIntervals sets number of aggregation intervals to be ignored on start.
+ IgnoreFirstIntervals *int `yaml:"ignore_first_intervals,omitempty"`
+
// By is an optional list of labels for grouping input series.
//
// See also Without.
@@ -259,21 +282,6 @@ func newAggregatorsFromData(data []byte, pushFunc PushFunc, opts *Options) (*Agg
return float64(n)
})
- _ = ms.NewGauge(`vm_streamaggr_labels_compressor_size_bytes`, func() float64 {
- n := uint64(0)
- for _, aggr := range as {
- n += aggr.lc.SizeBytes()
- }
- return float64(n)
- })
- _ = ms.NewGauge(`vm_streamaggr_labels_compressor_items_count`, func() float64 {
- n := uint64(0)
- for _, aggr := range as {
- n += aggr.lc.ItemsCount()
- }
- return float64(n)
- })
-
metrics.RegisterSet(ms)
return &Aggregators{
as: as,
@@ -351,9 +359,6 @@ type aggregator struct {
// aggrStates contains aggregate states for the given outputs
aggrStates []aggrState
- // lc is used for compressing series keys before passing them to dedupAggr and aggrState
- lc promutils.LabelsCompressor
-
// minTimestamp is used for ignoring old samples when ignoreOldSamples is set
minTimestamp atomic.Int64
@@ -479,6 +484,12 @@ func newAggregator(cfg *Config, pushFunc PushFunc, ms *metrics.Set, opts *Option
ignoreOldSamples = *v
}
+ // check cfg.IgnoreFirstIntervals
+ ignoreFirstIntervals := opts.IgnoreFirstIntervals
+ if v := cfg.IgnoreFirstIntervals; v != nil {
+ ignoreFirstIntervals = *v
+ }
+
// initialize outputs list
if len(cfg.Outputs) == 0 {
return nil, fmt.Errorf("`outputs` list must contain at least a single entry from the list %s; "+
@@ -600,14 +611,14 @@ func newAggregator(cfg *Config, pushFunc PushFunc, ms *metrics.Set, opts *Option
a.wg.Add(1)
go func() {
- a.runFlusher(pushFunc, alignFlushToInterval, skipIncompleteFlush, interval, dedupInterval)
+ a.runFlusher(pushFunc, alignFlushToInterval, skipIncompleteFlush, interval, dedupInterval, ignoreFirstIntervals)
a.wg.Done()
}()
return a, nil
}
-func (a *aggregator) runFlusher(pushFunc PushFunc, alignFlushToInterval, skipIncompleteFlush bool, interval, dedupInterval time.Duration) {
+func (a *aggregator) runFlusher(pushFunc PushFunc, alignFlushToInterval, skipIncompleteFlush bool, interval, dedupInterval time.Duration, ignoreFirstIntervals int) {
alignedSleep := func(d time.Duration) {
if !alignFlushToInterval {
return
@@ -642,7 +653,12 @@ func (a *aggregator) runFlusher(pushFunc PushFunc, alignFlushToInterval, skipInc
}
for tickerWait(t) {
- a.flush(pushFunc, interval, true)
+ pf := pushFunc
+ if ignoreFirstIntervals > 0 {
+ pf = nil
+ ignoreFirstIntervals--
+ }
+ a.flush(pf, interval, true)
if alignFlushToInterval {
select {
@@ -663,13 +679,17 @@ func (a *aggregator) runFlusher(pushFunc PushFunc, alignFlushToInterval, skipInc
ct := time.Now()
if ct.After(flushDeadline) {
+ pf := pushFunc
+ if ignoreFirstIntervals > 0 {
+ pf = nil
+ ignoreFirstIntervals--
+ }
// It is time to flush the aggregated state
if alignFlushToInterval && skipIncompleteFlush && !isSkippedFirstFlush {
- a.flush(nil, interval, true)
+ pf = nil
isSkippedFirstFlush = true
- } else {
- a.flush(pushFunc, interval, true)
}
+ a.flush(pf, interval, true)
for ct.After(flushDeadline) {
flushDeadline = flushDeadline.Add(interval)
}
@@ -684,7 +704,7 @@ func (a *aggregator) runFlusher(pushFunc PushFunc, alignFlushToInterval, skipInc
}
}
- if !skipIncompleteFlush {
+ if !skipIncompleteFlush && ignoreFirstIntervals == 0 {
a.dedupFlush(dedupInterval)
a.flush(pushFunc, interval, true)
}
@@ -797,7 +817,7 @@ func (a *aggregator) Push(tss []prompbmarshal.TimeSeries, matchIdxs []byte) {
outputLabels.Labels = append(outputLabels.Labels, labels.Labels...)
}
- buf = compressLabels(buf[:0], &a.lc, inputLabels.Labels, outputLabels.Labels)
+ buf = compressLabels(buf[:0], inputLabels.Labels, outputLabels.Labels)
key := bytesutil.InternBytes(buf)
for _, sample := range ts.Samples {
if math.IsNaN(sample.Value) {
@@ -825,7 +845,7 @@ func (a *aggregator) Push(tss []prompbmarshal.TimeSeries, matchIdxs []byte) {
}
}
-func compressLabels(dst []byte, lc *promutils.LabelsCompressor, inputLabels, outputLabels []prompbmarshal.Label) []byte {
+func compressLabels(dst []byte, inputLabels, outputLabels []prompbmarshal.Label) []byte {
bb := bbPool.Get()
bb.B = lc.Compress(bb.B, inputLabels)
dst = encoding.MarshalVarUint64(dst, uint64(len(bb.B)))
@@ -835,7 +855,7 @@ func compressLabels(dst []byte, lc *promutils.LabelsCompressor, inputLabels, out
return dst
}
-func decompressLabels(dst []prompbmarshal.Label, lc *promutils.LabelsCompressor, key string) []prompbmarshal.Label {
+func decompressLabels(dst []prompbmarshal.Label, key string) []prompbmarshal.Label {
return lc.Decompress(dst, bytesutil.ToUnsafeBytes(key))
}
@@ -1010,7 +1030,7 @@ func (ctx *flushCtx) flushSeries() {
func (ctx *flushCtx) appendSeries(key, suffix string, timestamp int64, value float64) {
labelsLen := len(ctx.labels)
samplesLen := len(ctx.samples)
- ctx.labels = decompressLabels(ctx.labels, &ctx.a.lc, key)
+ ctx.labels = decompressLabels(ctx.labels, key)
if !ctx.a.keepMetricNames {
ctx.labels = addMetricSuffix(ctx.labels, labelsLen, ctx.a.suffix, suffix)
}
@@ -1033,7 +1053,7 @@ func (ctx *flushCtx) appendSeries(key, suffix string, timestamp int64, value flo
func (ctx *flushCtx) appendSeriesWithExtraLabel(key, suffix string, timestamp int64, value float64, extraName, extraValue string) {
labelsLen := len(ctx.labels)
samplesLen := len(ctx.samples)
- ctx.labels = decompressLabels(ctx.labels, &ctx.a.lc, key)
+ ctx.labels = decompressLabels(ctx.labels, key)
if !ctx.a.keepMetricNames {
ctx.labels = addMetricSuffix(ctx.labels, labelsLen, ctx.a.suffix, suffix)
}
diff --git a/lib/streamaggr/streamaggr_test.go b/lib/streamaggr/streamaggr_test.go
index 5a079979b..ae234bb76 100644
--- a/lib/streamaggr/streamaggr_test.go
+++ b/lib/streamaggr/streamaggr_test.go
@@ -199,6 +199,14 @@ func TestAggregatorsEqual(t *testing.T) {
interval: 5m
flush_on_shutdown: false
`, false)
+ f(`
+- outputs: [total]
+ interval: 5m
+ ignore_first_intervals: 2
+`, `
+- outputs: [total]
+ interval: 5m
+ ignore_first_intervals: 4`, false)
}
func TestAggregatorsSuccess(t *testing.T) {
@@ -510,8 +518,8 @@ foo:1m_total 0
`, `
foo 123
bar{baz="qwe"} 4.34
-`, `bar:1m_total{baz="qwe"} 0
-foo:1m_total 0
+`, `bar:1m_total_prometheus{baz="qwe"} 0
+foo:1m_total_prometheus 0
`, "11")
// total output for repeated series
@@ -546,10 +554,10 @@ foo{baz="qwe"} -5
bar{baz="qwer"} 343
bar{baz="qwer"} 344
foo{baz="qwe"} 10
-`, `bar:1m_total{baz="qwe"} 5.02
-bar:1m_total{baz="qwer"} 1
-foo:1m_total 0
-foo:1m_total{baz="qwe"} 15
+`, `bar:1m_total_prometheus{baz="qwe"} 5.02
+bar:1m_total_prometheus{baz="qwer"} 1
+foo:1m_total_prometheus 0
+foo:1m_total_prometheus{baz="qwe"} 15
`, "11111111")
// total output for repeated series with group by __name__
@@ -584,8 +592,8 @@ foo{baz="qwe"} -5
bar{baz="qwer"} 343
bar{baz="qwer"} 344
foo{baz="qwe"} 10
-`, `bar:1m_total 6.02
-foo:1m_total 15
+`, `bar:1m_total_prometheus 6.02
+foo:1m_total_prometheus 15
`, "11111111")
// increase output for non-repeated series
@@ -606,8 +614,8 @@ foo:1m_increase 0
`, `
foo 123
bar{baz="qwe"} 4.34
-`, `bar:1m_increase{baz="qwe"} 0
-foo:1m_increase 0
+`, `bar:1m_increase_prometheus{baz="qwe"} 0
+foo:1m_increase_prometheus 0
`, "11")
// increase output for repeated series
@@ -642,10 +650,10 @@ foo{baz="qwe"} -5
bar{baz="qwer"} 343
bar{baz="qwer"} 344
foo{baz="qwe"} 10
-`, `bar:1m_increase{baz="qwe"} 5.02
-bar:1m_increase{baz="qwer"} 1
-foo:1m_increase 0
-foo:1m_increase{baz="qwe"} 15
+`, `bar:1m_increase_prometheus{baz="qwe"} 5.02
+bar:1m_increase_prometheus{baz="qwer"} 1
+foo:1m_increase_prometheus 0
+foo:1m_increase_prometheus{baz="qwe"} 15
`, "11111111")
// multiple aggregate configs
diff --git a/lib/streamaggr/total.go b/lib/streamaggr/total.go
index e0b28d437..a0576245e 100644
--- a/lib/streamaggr/total.go
+++ b/lib/streamaggr/total.go
@@ -53,6 +53,9 @@ func newTotalAggrState(stalenessInterval time.Duration, resetTotalOnFlush, keepF
if resetTotalOnFlush {
suffix = "increase"
}
+ if !keepFirstSample {
+ suffix += "_prometheus"
+ }
return &totalAggrState{
suffix: suffix,
resetTotalOnFlush: resetTotalOnFlush,