rawData = {
class NamespaceResource {
constructor(namespace, node, resource, value=0) {
this.namespace = namespace
this.node = node
this.resource = this.convertResource(resource)
this.value = this.convertValue(value)
}
convertResource (resource) {
if (resource?.includes("amd_com_xilinx")) return "fpga"
if (resource == "cpu") return "cpu"
if (resource?.includes("nvidia_com")) return "gpu"
if (resource == "memory") return "memory"
if (resource == "ephemeral_storage") return "storage"
return "other"
}
add(value) {
this.value += this.convertValue(value)
}
convertValue(value) {
return (this.resource == 'memory' || this.resource == 'storage') ? parseFloat(value) / 1000000000 : parseFloat(value)
}
}
async function queryPrometheus(query) {
var encodedUrl = "https://thanos.nrp-nautilus.io/api/v1/query?query=" + encodeURIComponent(query)
return new Promise((resolve, reject) => {
fetch(encodedUrl).then((response) => {
if (response.ok) {
response.json().then((json) => {
resolve(json.data.result)
})
} else {
var errorMessage = `Invalid response: Status ${response.status} ${response.statusText}`
dataStatus.status = "failure"
dataStatus.error = errorMessage
reject(errorMessage)
}
}).catch((error) => {
var errorMessage = `Networking error: ${error}`
dataStatus.status = "failure"
dataStatus.error = errorMessage
reject(errorMessage)
})
})
}
dataStatus.status = null
dataStatus.error = ''
var output = [{None: null}]
if (form.startDate == "") {
dataStatus.error = "Missing Input: Start Date"
return output
}
if (form.endDate == "") {
dataStatus.error = "Missing Input: End Date"
return output
}
var today = new Date()
var maxDate = new Date('09/15/23')
var startDate = new Date(form.startDate)
var endDate = new Date(form.endDate)
if (startDate > today || endDate > today || startDate >= endDate || startDate < maxDate) {
dataStatus.status = "failure"
dataStatus.error = "Invalid Date(s)"
return output
}
dataStatus.status = 'pending'
const moment = await require('moment')
var days = moment(endDate).diff(startDate, "days")
var dateRanges = []
for(var weeks = days == 7 ? 0 : Math.floor(days/7); weeks >= 0; weeks-- ) {
var searchDays = days - 7*weeks >= 7 || days - 7*weeks == 0 ? 7 : days - 7*weeks
var searchEnd = new Date()
searchEnd.setTime(endDate.getTime() - 1000*60*60*24*7*weeks)
searchEnd = weeks == Math.floor(days/7) ? moment(searchEnd).unix() : moment(searchEnd).unix() + 1
dateRanges.push([searchDays, searchEnd])
}
var allocatedQueries = []
for (const [searchDays, searchEnd] of dateRanges) {
allocatedQueries.push(queryPrometheus(`sum_over_time(namespace_allocated_resources[${searchDays}d:1h]@${searchEnd})`))
}
var data = []
var isMissingData = false
await Promise.allSettled(allocatedQueries).then((queries) => {
for (const query of queries) {
if (query.value.length == 0) {
isMissingData = true
} else {
for (const value of query.value) {
var namespace = value['metric']['namespace']
var node = value['metric']['node']
var resource = value['metric']['resource']
var allocatedValue = value['value'][1]
if(namespace && node && resource) {
var dataRow = data.find((row) => row.namespace == namespace && row.node == node && row.resource == row.convertResource(resource))
if (dataRow) {
dataRow.add(allocatedValue)
}
else {
var namespaceResource = new NamespaceResource(namespace, node, resource, allocatedValue)
data.push(namespaceResource)
}
}
}
}
}
})
if (isMissingData) {
dataStatus.status = "failure"
dataStatus.error = `Missing data, partial query failure`
} else {
dataStatus.status = "success"
}
return data
}