mirror of https://github.com/hashicorp/consul
44 lines
9.4 KiB
JavaScript
44 lines
9.4 KiB
JavaScript
(function(){var e={unitSuffix:"",labels:{},data:[]},t={options:{},init:function(e){if(this.options=e,!this.options.metrics_proxy_enabled)throw new Error("prometheus metrics provider currently requires the ui_config.metrics_proxy to be configured in the Consul agent.")},httpGet:function(e,t,r){if(t){var s=-1!==e.indexOf("?")?"&":"?"
|
|
e=e+s+Object.keys(t).map((function(e){return encodeURIComponent(e)+"="+encodeURIComponent(t[e])})).join("&")}return this.options.fetch(e,{headers:r||{}}).then((function(e){if(e.ok)return e.json()
|
|
var t=new Error("HTTP Error: "+e.statusText)
|
|
throw t.statusCode=e.status,t}))},serviceRecentSummarySeries:function(e,t,r,s,n){var a=(new Date).getTime()/1e3
|
|
return n.start=a-900,n.end=a,this.hasL7Metrics(s)?this.fetchRequestRateSeries(e,t,r,n):this.fetchDataRateSeries(e,t,r,n)},serviceRecentSummaryStats:function(e,t,r,s,n){var a=[]
|
|
return this.hasL7Metrics(s)?(a.push(this.fetchRPS(e,t,r,"service",n)),a.push(this.fetchER(e,t,r,"service",n)),a.push(this.fetchPercentile(50,e,t,r,"service",n)),a.push(this.fetchPercentile(99,e,t,r,"service",n))):(a.push(this.fetchConnRate(e,t,r,"service",n)),a.push(this.fetchServiceRx(e,t,r,"service",n)),a.push(this.fetchServiceTx(e,t,r,"service",n)),a.push(this.fetchServiceNoRoute(e,t,r,"service",n))),this.fetchStats(a)},upstreamRecentSummaryStats:function(e,t,r,s){return this.fetchRecentSummaryStats(e,t,r,"upstream",s)},downstreamRecentSummaryStats:function(e,t,r,s){return this.fetchRecentSummaryStats(e,t,r,"downstream",s)},fetchRecentSummaryStats:function(e,t,r,s,n){var a=[]
|
|
return a.push(this.fetchRPS(e,t,r,s,n)),a.push(this.fetchER(e,t,r,s,n)),a.push(this.fetchPercentile(50,e,t,r,s,n)),a.push(this.fetchPercentile(99,e,t,r,s,n)),a.push(this.fetchConnRate(e,t,r,s,n)),a.push(this.fetchServiceRx(e,t,r,s,n)),a.push(this.fetchServiceTx(e,t,r,s,n)),a.push(this.fetchServiceNoRoute(e,t,r,s,n)),this.fetchStatsGrouped(a)},hasL7Metrics:function(e){return"http"===e||"http2"===e||"grpc"===e},fetchStats:function(e){return Promise.all(e).then((function(t){for(var r={stats:[]},s=0;s<e.length;s++)t[s].value&&r.stats.push(t[s])
|
|
return r}))},fetchStatsGrouped:function(e){return Promise.all(e).then((function(t){for(var r={stats:{}},s=0;s<e.length;s++)if(t[s])for(var n in t[s])t[s].hasOwnProperty(n)&&(r.stats[n]||(r.stats[n]=[]),r.stats[n].push(t[s][n]))
|
|
return r}))},reformatSeries:function(t,r){return function(s){if(!s.data||!s.data.result||0==s.data.result.length||!s.data.result[0].values||0==s.data.result[0].values.length)return e
|
|
let n=s.data.result[0].values.map((function(e){return{time:Math.round(1e3*e[0])}}))
|
|
return s.data.result.map((function(e){e.values.map((function(t,r){n[r][e.metric.label]=parseFloat(t[1])}))})),{unitSuffix:t,labels:r,data:n}}},fetchRequestRateSeries:function(e,t,r,s){var n=`sum by (label) (label_replace(label_replace(irate(envoy_listener_http_downstream_rq_xx{consul_source_service="${e}",consul_source_datacenter="${t}",consul_source_namespace="${r}",envoy_http_conn_manager_prefix="public_listener"}[10m]), "label", "Successes", "envoy_response_code_class", "[^5]"), "label", "Errors", "envoy_response_code_class", "5"))`
|
|
return this.fetchSeries(n,s).then(this.reformatSeries(" rps",{Total:"Total inbound requests per second",Successes:"Successful responses (with an HTTP response code not in the 5xx range) per second.",Errors:"Error responses (with an HTTP response code in the 5xx range) per second."}))},fetchDataRateSeries:function(e,t,r,s){var n=`8 * sum by (label) (label_replace(irate(envoy_tcp_downstream_cx_tx_bytes_total{consul_source_service="${e}",consul_source_datacenter="${t}",consul_source_namespace="${r}",envoy_tcp_prefix="public_listener"}[10m]), "label", "Outbound", "__name__", ".*") or label_replace(irate(envoy_tcp_downstream_cx_rx_bytes_total{consul_source_service="${e}",consul_source_datacenter="${t}",consul_source_namespace="${r}",envoy_tcp_prefix="public_listener"}[10m]), "label", "Inbound", "__name__", ".*"))`
|
|
return this.fetchSeries(n,s).then(this.reformatSeries("bps",{Total:"Total bandwidth",Inbound:"Inbound data rate (data recieved) from the network in bits per second.",Outbound:"Outbound data rate (data transmitted) from the network in bits per second."}))},makeSubject:function(e,t,r,s){var n=`${r}/${e} (${t})`
|
|
return"upstream"==s?n+" → {{GROUP}}":"downstream"==s?"{{GROUP}} → "+n:n},makeHTTPSelector:function(e,t,r,s){if("downstream"==s)return`consul_destination_service="${e}",consul_destination_datacenter="${t}",consul_destination_namespace="${r}"`
|
|
var n=`consul_source_service="${e}",consul_source_datacenter="${t}",consul_source_namespace="${r}"`
|
|
return n+="upstream"==s?',envoy_http_conn_manager_prefix="upstream"':',envoy_http_conn_manager_prefix="public_listener"'},makeTCPSelector:function(e,t,r,s){if("downstream"==s)return`consul_destination_service="${e}",consul_destination_datacenter="${t}",consul_destination_namespace="${r}"`
|
|
var n=`consul_source_service="${e}",consul_source_datacenter="${t}",consul_source_namespace="${r}"`
|
|
return n+="upstream"==s?',envoy_tcp_prefix=~"upstream.*"':',envoy_tcp_prefix="public_listener"'},groupQuery:function(e,t){return"upstream"==e?t+=" by (consul_upstream_service,consul_upstream_datacenter,consul_upstream_namespace)":"downstream"==e&&(t+=" by (consul_source_service,consul_source_datacenter,consul_source_namespace)"),t},groupByInfix:function(e){return"upstream"==e?"upstream":"downstream"==e&&"source"},metricPrefixHTTP:function(e){return"downstream"==e?"envoy_cluster_upstream_rq":"envoy_http_downstream_rq"},metricPrefixTCP:function(e){return"downstream"==e?"envoy_cluster_upstream_cx":"envoy_tcp_downstream_cx"},fetchRPS:function(e,t,s,n){var a=this.makeHTTPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i=`sum(rate(${this.metricPrefixHTTP(n)}_completed{${a}}[15m]))`
|
|
return this.fetchStat(this.groupQuery(n,i),"RPS",`<b>${c}</b> request rate averaged over the last 15 minutes`,r,this.groupByInfix(n))},fetchER:function(e,t,s,n){var a=this.makeHTTPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i=""
|
|
"upstream"==n?i+=" by (consul_upstream_service,consul_upstream_datacenter,consul_upstream_namespace)":"downstream"==n&&(i+=" by (consul_source_service,consul_source_datacenter,consul_source_namespace)")
|
|
var u=this.metricPrefixHTTP(n),o=`sum(rate(${u}_xx{${a},envoy_response_code_class="5"}[15m]))${i}/sum(rate(${u}_xx{${a}}[15m]))${i}`
|
|
return this.fetchStat(o,"ER",`Percentage of <b>${c}</b> requests which were 5xx status over the last 15 minutes`,(function(e){return r(e)+"%"}),this.groupByInfix(n))},fetchPercentile:function(e,t,r,n,a){var c=this.makeHTTPSelector(t,r,n,a),i=this.makeSubject(t,r,n,a),u="le"
|
|
"upstream"==a?u+=",consul_upstream_service,consul_upstream_datacenter,consul_upstream_namespace":"downstream"==a&&(u+=",consul_source_service,consul_source_datacenter,consul_source_namespace")
|
|
var o=`histogram_quantile(${e/100}, sum by(${u}) (rate(${this.metricPrefixHTTP(a)}_time_bucket{${c}}[15m])))`
|
|
return this.fetchStat(o,"P"+e,`<b>${i}</b> ${e}th percentile request service time over the last 15 minutes`,s,this.groupByInfix(a))},fetchConnRate:function(e,t,s,n){var a=this.makeTCPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i=`sum(rate(${this.metricPrefixTCP(n)}_total{${a}}[15m]))`
|
|
return this.fetchStat(this.groupQuery(n,i),"CR",`<b>${c}</b> inbound TCP connections per second averaged over the last 15 minutes`,r,this.groupByInfix(n))},fetchServiceRx:function(e,t,s,n){var a=this.makeTCPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i=`8 * sum(rate(${this.metricPrefixTCP(n)}_rx_bytes_total{${a}}[15m]))`
|
|
return this.fetchStat(this.groupQuery(n,i),"RX",`<b>${c}</b> received bits per second averaged over the last 15 minutes`,r,this.groupByInfix(n))},fetchServiceTx:function(e,t,s,n){var a=this.makeTCPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i=`8 * sum(rate(${this.metricPrefixTCP(n)}_tx_bytes_total{${a}}[15m]))`
|
|
return this.fetchStat(this.groupQuery(n,i),"TX",`<b>${c}</b> transmitted bits per second averaged over the last 15 minutes`,r,this.groupByInfix(n))},fetchServiceNoRoute:function(e,t,s,n){var a=this.makeTCPSelector(e,t,s,n),c=this.makeSubject(e,t,s,n),i="_no_route"
|
|
"downstream"==n&&(i="_connect_fail")
|
|
var u=`sum(rate(${this.metricPrefixTCP(n)}${i}{${a}}[15m]))`
|
|
return this.fetchStat(this.groupQuery(n,u),"NR",`<b>${c}</b> unroutable (failed) connections per second averaged over the last 15 minutes`,r,this.groupByInfix(n))},fetchStat:function(e,t,r,s,n){n||(e+=" OR on() vector(0)")
|
|
var a={query:e,time:(new Date).getTime()/1e3}
|
|
return this.httpGet("/api/v1/query",a).then((function(e){if(!n){var a=parseFloat(e.data.result[0].value[1])
|
|
return{label:t,desc:r,value:isNaN(a)?"-":s(a)}}for(var c={},i=0;i<e.data.result.length;i++){var u=e.data.result[i],o=(a=parseFloat(u.value[1]),`${u.metric["consul_"+n+"_service"]}.${u.metric["consul_"+n+"_namespace"]}.${u.metric["consul_"+n+"_datacenter"]}`)
|
|
c[o]={label:t,desc:r.replace("{{GROUP}}",o),value:isNaN(a)?"-":s(a)}}return c}))},fetchSeries:function(e,t){var r={query:e,start:t.start,end:t.end,step:"10s",timeout:"8s"}
|
|
return this.httpGet("/api/v1/query_range",r)}}
|
|
function r(e){return e<1e3?Number.isInteger(e)?""+e:Number(e>=100?e.toPrecision(3):e<1?e.toFixed(2):e.toPrecision(2)):e>=1e3&&e<1e6?+(e/1e3).toPrecision(3)+"k":e>=1e6&&e<1e9?+(e/1e6).toPrecision(3)+"m":e>=1e9&&e<1e12?+(e/1e9).toPrecision(3)+"g":e>=1e12?+(e/1e12).toFixed(0)+"t":void 0}function s(e){if(e<1e3)return Math.round(e)+"ms"
|
|
var t=e/1e3
|
|
if(t<60)return t.toFixed(1)+"s"
|
|
var r=t/60
|
|
if(r<60)return r.toFixed(1)+"m"
|
|
var s=r/60
|
|
return s<24?s.toFixed(1)+"h":(s/24).toFixed(1)+"d"}window.consul.registerMetricsProvider("prometheus",t)})()
|