// Copyright 2023 The Casdoor Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package object import ( "fmt" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_model/go" ) type PrometheusInfo struct { ApiThroughput []GaugeVecInfo `json:"apiThroughput"` ApiLatency []HistogramVecInfo `json:"apiLatency"` TotalThroughput float64 `json:"totalThroughput"` } type GaugeVecInfo struct { Method string `json:"method"` Name string `json:"name"` Throughput float64 `json:"throughput"` } type HistogramVecInfo struct { Method string `json:"method"` Name string `json:"name"` Count uint64 `json:"count"` Latency string `json:"latency"` } var ( ApiThroughput = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "casdoor_api_throughput", Help: "The throughput of each api access", }, []string{"path", "method"}) ApiLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ Name: "casdoor_api_latency", Help: "API processing latency in milliseconds", }, []string{"path", "method"}) CpuUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "casdoor_cpu_usage", Help: "Casdoor cpu usage", }, []string{"cpuNum"}) MemoryUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "casdoor_memory_usage", Help: "Casdoor memory usage in Byte", }, []string{"type"}) TotalThroughput = promauto.NewGauge(prometheus.GaugeOpts{ Name: "casdoor_total_throughput", Help: "The total throughput of casdoor", }) ) func ClearThroughputPerSecond() { // Clear the throughput every second ticker := time.NewTicker(time.Second) for range ticker.C { ApiThroughput.Reset() TotalThroughput.Set(0) } } func GetPrometheusInfo() (*PrometheusInfo, error) { res := &PrometheusInfo{} metricFamilies, err := prometheus.DefaultGatherer.Gather() if err != nil { return nil, err } for _, metricFamily := range metricFamilies { switch metricFamily.GetName() { case "casdoor_api_throughput": res.ApiThroughput = getGaugeVecInfo(metricFamily) case "casdoor_api_latency": res.ApiLatency = getHistogramVecInfo(metricFamily) case "casdoor_total_throughput": res.TotalThroughput = metricFamily.GetMetric()[0].GetGauge().GetValue() } } return res, nil } func getHistogramVecInfo(metricFamily *io_prometheus_client.MetricFamily) []HistogramVecInfo { var histogramVecInfos []HistogramVecInfo for _, metric := range metricFamily.GetMetric() { sampleCount := metric.GetHistogram().GetSampleCount() sampleSum := metric.GetHistogram().GetSampleSum() latency := sampleSum / float64(sampleCount) histogramVecInfo := HistogramVecInfo{ Method: metric.Label[0].GetValue(), Name: metric.Label[1].GetValue(), Count: sampleCount, Latency: fmt.Sprintf("%.3f", latency), } histogramVecInfos = append(histogramVecInfos, histogramVecInfo) } return histogramVecInfos } func getGaugeVecInfo(metricFamily *io_prometheus_client.MetricFamily) []GaugeVecInfo { var counterVecInfos []GaugeVecInfo for _, metric := range metricFamily.GetMetric() { counterVecInfo := GaugeVecInfo{ Method: metric.Label[0].GetValue(), Name: metric.Label[1].GetValue(), Throughput: metric.Gauge.GetValue(), } counterVecInfos = append(counterVecInfos, counterVecInfo) } return counterVecInfos }