github.com/pelicanplatform/pelican@v1.0.5/web_ui/frontend/components/graphs/prometheus.tsx (about) 1 /*************************************************************** 2 * 3 * Copyright (C) 2023, Pelican Project, Morgridge Institute for Research 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); you 6 * may not use this file except in compliance with the License. You may 7 * obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ***************************************************************/ 18 19 20 import {ChartData} from "chart.js"; 21 22 import {isLoggedIn} from "@/helpers/login"; 23 import {DateTime} from "luxon"; 24 25 let getTimeDuration = (value: string, defaultValue: number = 1) => { 26 let _value = value.match(/\d+/) 27 if(_value){ 28 return parseInt(_value[0]) 29 } 30 31 console.error("Invalid time duration, using default value: " + defaultValue.toString()) 32 return defaultValue 33 } 34 35 let getDurationType = (value: string, defaultType: string = "h") => { 36 let _type = value.match(/\D+/) 37 if(_type){ 38 return _type[0] 39 } 40 41 console.error(`Invalid time duration type (${value}), using default value: ` + defaultType.toString()) 42 return defaultType 43 } 44 45 export type DurationType = "ms" | "s" | "m" | "h" | "d" | "w" | "y"; 46 47 export class TimeDuration { 48 value: number; 49 type: DurationType; 50 51 constructor(value: number, type: DurationType) { 52 this.value = value; 53 this.type = type; 54 } 55 56 toString(){ 57 return `${this.value}${this.type}` 58 } 59 60 static fromString(value: string){ 61 let _value= getTimeDuration(value) 62 let _type = getDurationType(value) as DurationType 63 64 return new TimeDuration(_value, _type) 65 } 66 67 copy(){ 68 return new TimeDuration(this.value, this.type) 69 } 70 } 71 72 export interface getDataFunction { 73 (): Promise<ChartData<"line", any, any>> 74 } 75 76 export interface DataPoint { 77 x: any; 78 y: any; 79 } 80 81 export async function query_raw(query: string, time?: Number): Promise<DataPoint[]> { 82 83 //Check if the user is logged in 84 if(!(await isLoggedIn())){ 85 window.location.replace("/view/login/") 86 } 87 88 const url = new URL(window.location.origin + "/api/v1.0/prometheus/query") 89 url.searchParams.append("query", query) 90 if(time) { 91 url.searchParams.append("time", time.toString()) 92 } 93 94 95 let response = await fetch(url.href) 96 97 if (response.status !== 200) { 98 throw new Error(`Prometheus query returned status ${response.status}`) 99 } 100 101 let json = await response.json() 102 103 if (json.status !== "success") { 104 throw new Error(`Prometheus query returned status ${json.status}`) 105 } 106 107 108 if(json.data.result.length == 0){ 109 return [] 110 } 111 112 // This will return the list of time and value tuples [1693918800,"0"],[1693919100,"0"]... 113 let prometheusTuples = json.data.result[0].values 114 115 // Chart.js expects milliseconds since epoch 116 let data: DataPoint[] = prometheusTuples.map((tuple: any) => { return {x: tuple[0] * 1000, y: tuple[1]}}) 117 118 return data 119 } 120 121 interface QueryBasicOptions { 122 metric: string; 123 duration: TimeDuration; 124 resolution: TimeDuration; 125 time?: DateTime; 126 } 127 128 export async function query_basic({metric, duration, resolution, time}: QueryBasicOptions): Promise<DataPoint[]> { 129 let query = `${metric}[${duration.toString()}:${resolution.toString()}]` 130 return query_raw(query, time?.toSeconds()) 131 } 132 133 interface QueryRateOptions { 134 metric: string; 135 rate: TimeDuration; 136 duration: TimeDuration; 137 resolution: TimeDuration; 138 time?: DateTime; 139 } 140 141 export async function query_rate({metric, rate, duration, resolution, time}: QueryRateOptions): Promise<DataPoint[]> { 142 let query = `rate(${metric}[${rate.toString()}])[${duration.toString()}:${resolution.toString()}]` 143 return query_raw(query, time?.toSeconds()) 144 }