mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: fix prometheus filter bugs (#1792)
* fix: fix prometheus * fix: count latency with prefix api * fix: latency should not be counted when startTime is nil
This commit is contained in:
parent
4c1915b014
commit
e4c36d407f
@ -183,3 +183,14 @@ func wrapErrorResponse(err error) *Response {
|
||||
return &Response{Status: "error", Msg: err.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ApiController) Finish() {
|
||||
if strings.HasPrefix(c.Ctx.Input.URL(), "/api") {
|
||||
startTime := c.Ctx.Input.GetData("startTime")
|
||||
if startTime != nil {
|
||||
latency := time.Since(startTime.(time.Time)).Milliseconds()
|
||||
object.ApiLatency.WithLabelValues(c.Ctx.Input.Method(), c.Ctx.Input.URL()).Observe(float64(latency))
|
||||
}
|
||||
}
|
||||
c.Controller.Finish()
|
||||
}
|
||||
|
1
main.go
1
main.go
@ -60,6 +60,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
|
@ -24,8 +24,8 @@ import (
|
||||
)
|
||||
|
||||
type PrometheusInfo struct {
|
||||
APIThroughput []GaugeVecInfo `json:"apiThroughput"`
|
||||
APILatency []HistogramVecInfo `json:"apiLatency"`
|
||||
ApiThroughput []GaugeVecInfo `json:"apiThroughput"`
|
||||
ApiLatency []HistogramVecInfo `json:"apiLatency"`
|
||||
TotalThroughput float64 `json:"totalThroughput"`
|
||||
}
|
||||
|
||||
@ -43,12 +43,12 @@ type HistogramVecInfo struct {
|
||||
}
|
||||
|
||||
var (
|
||||
APIThroughput = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||
ApiThroughput = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "casdoor_api_throughput",
|
||||
Help: "The throughput of each api access",
|
||||
}, []string{"path", "method"})
|
||||
|
||||
APILatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
ApiLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "casdoor_api_latency",
|
||||
Help: "API processing latency in milliseconds",
|
||||
}, []string{"path", "method"})
|
||||
@ -73,7 +73,7 @@ func ClearThroughputPerSecond() {
|
||||
// Clear the throughput every second
|
||||
ticker := time.NewTicker(time.Second)
|
||||
for range ticker.C {
|
||||
APIThroughput.Reset()
|
||||
ApiThroughput.Reset()
|
||||
TotalThroughput.Set(0)
|
||||
}
|
||||
}
|
||||
@ -87,9 +87,9 @@ func GetPrometheusInfo() (*PrometheusInfo, error) {
|
||||
for _, metricFamily := range metricFamilies {
|
||||
switch metricFamily.GetName() {
|
||||
case "casdoor_api_throughput":
|
||||
res.APIThroughput = getGaugeVecInfo(metricFamily)
|
||||
res.ApiThroughput = getGaugeVecInfo(metricFamily)
|
||||
case "casdoor_api_latency":
|
||||
res.APILatency = getHistogramVecInfo(metricFamily)
|
||||
res.ApiLatency = getHistogramVecInfo(metricFamily)
|
||||
case "casdoor_total_throughput":
|
||||
res.TotalThroughput = metricFamily.GetMetric()[0].GetGauge().GetValue()
|
||||
}
|
||||
|
@ -2,46 +2,14 @@ package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type PrometheusMiddleWareWrapper struct {
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func PrometheusMiddleWare(h http.Handler) http.Handler {
|
||||
return &PrometheusMiddleWareWrapper{
|
||||
handler: h,
|
||||
}
|
||||
}
|
||||
|
||||
func (p PrometheusMiddleWareWrapper) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
method := req.Method
|
||||
endpoint := req.URL.Path
|
||||
if strings.HasPrefix(endpoint, "/api/metrics") {
|
||||
systemInfo, err := util.GetSystemInfo()
|
||||
if err == nil {
|
||||
recordSystemInfo(systemInfo)
|
||||
}
|
||||
p.handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(endpoint, "/api") {
|
||||
start := time.Now()
|
||||
p.handler.ServeHTTP(w, req)
|
||||
latency := time.Since(start).Milliseconds()
|
||||
object.TotalThroughput.Inc()
|
||||
object.APILatency.WithLabelValues(endpoint, method).Observe(float64(latency))
|
||||
object.APIThroughput.WithLabelValues(endpoint, method).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func recordSystemInfo(systemInfo *util.SystemInfo) {
|
||||
for i, value := range systemInfo.CpuUsage {
|
||||
object.CpuUsage.WithLabelValues(fmt.Sprintf("%d", i)).Set(value)
|
||||
@ -49,3 +17,21 @@ func recordSystemInfo(systemInfo *util.SystemInfo) {
|
||||
object.MemoryUsage.WithLabelValues("memoryUsed").Set(float64(systemInfo.MemoryUsed))
|
||||
object.MemoryUsage.WithLabelValues("memoryTotal").Set(float64(systemInfo.MemoryTotal))
|
||||
}
|
||||
|
||||
func PrometheusFilter(ctx *context.Context) {
|
||||
method := ctx.Input.Method()
|
||||
path := ctx.Input.URL()
|
||||
if strings.HasPrefix(path, "/api/metrics") {
|
||||
systemInfo, err := util.GetSystemInfo()
|
||||
if err == nil {
|
||||
recordSystemInfo(systemInfo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(path, "/api") {
|
||||
ctx.Input.SetData("startTime", time.Now())
|
||||
object.TotalThroughput.Inc()
|
||||
object.ApiThroughput.WithLabelValues(path, method).Inc()
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +87,9 @@ class SystemInfo extends React.Component {
|
||||
<br /> <br />
|
||||
<Progress type="circle" percent={Number((Number(this.state.systemInfo.memoryUsed) / Number(this.state.systemInfo.memoryTotal) * 100).toFixed(2))} />
|
||||
</div>;
|
||||
const latencyUi = this.state.prometheusInfo.apiLatency.length <= 0 ? <Spin size="large" /> :
|
||||
const latencyUi = this.state.prometheusInfo.apiLatency === null || this.state.prometheusInfo.apiLatency?.length <= 0 ? <Spin size="large" /> :
|
||||
<PrometheusInfoTable prometheusInfo={this.state.prometheusInfo} table={"latency"} />;
|
||||
const throughputUi = this.state.prometheusInfo.apiLatency.length <= 0 ? <Spin size="large" /> :
|
||||
const throughputUi = this.state.prometheusInfo.apiThroughput === null || this.state.prometheusInfo.apiThroughput?.length <= 0 ? <Spin size="large" /> :
|
||||
<PrometheusInfoTable prometheusInfo={this.state.prometheusInfo} table={"throughput"} />;
|
||||
const link = this.state.versionInfo?.version !== "" ? `https://github.com/casdoor/casdoor/releases/tag/${this.state.versionInfo?.version}` : "";
|
||||
let versionText = this.state.versionInfo?.version !== "" ? this.state.versionInfo?.version : i18next.t("system:Unknown version");
|
||||
|
Loading…
x
Reference in New Issue
Block a user