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  }