Calculate HTTP Availability Percentage

Hi everyone,

I’m trying to calculate availability percentage of a web site. I thought of dividing (number of 200 codes) by (number of total response).

So, here are my 2 influxql queries:

SELECT count("http_response_code") AS "up" FROM "http_response" WHERE ("name" =~ /^$name$/ AND "status_code" = '200') AND $timeFilter GROUP BY time(5m), "name" fill(null)
SELECT count("http_response_code") AS "total" FROM "http_response" WHERE ("name" =~ /^$name$/) AND $timeFilter GROUP BY time(5m), "name" fill(null)

Second one is the same with first one only without “200” filter. As far as I know I can’t divide these 2 using influxql. Can you show me an example of how to get this percentage using Flux or any other way if you have better ideas.

success = from(bucket: "SERVERS")
  |> range(start: -1d)
  |> filter(fn: (r) => r._measurement == "http_response" and
  		r._field == "http_response_code" and
        r.status_code == "200"
        )
  |> count()
  |> group(columns: ["name"])
  |> keep(columns: ["name", "_value"])
  
|> yield(name: "SUCCESS")

total = from(bucket: "SERVERS")
  |> range(start: -1d)
  |> filter(fn: (r) => r._measurement == "http_response" and
  		r._field == "http_response_code"
        )
  |> count()
  |> group(columns: ["name"])
  |> keep(columns: ["name", "_value"])

  |> yield(name: "TOTAL")

join(tables: {success: success, total: total}, on: ["name"])
  |> map(fn:(r) => ({
  					name: r.name,
                    _value: r._value_success / r._value_total}))
  |> group(columns: ["name"])
  |> yield(name: "RESULT")

So, I’ve created this flux code but I’ve a problem. It returns 3 tables and displays all values from “success”, “total” and “result”. Yet, I want to display only the “result” table. How can I drop first tables?

@Mert The yield() calls are what are forcing the other tables into the output. If yield() is called anywhere in your script, the output of that yield is included in the final output of the script. You don’t need the yields on each.

One other way to do this would be to extract the total requests as a scalar value. That way you don’t have to do a join and the query will likely be much more performant:

data = from(bucket: "SERVERS")
  |> range(start: -1d)
  |> filter(fn: (r) => r._measurement == "http_response" and r._field == "http_response_code")

total_requests = {
  total = data
    |> group()
    |> count()
    |> tableFind(fn: (key) => true)
    |> getColumn(column: "_value")
  return total[0]
}

success = data
  |> filter(fn: (r) => r.status_code == "200")
  |> count()
  |> map(fn: (r) => ({ name: r.name, _value: float(v: r._value) / float(v: total_requests) * 100.0  }))

success

That last success just calls the success variable and outputs the returned data.

Another variation of this approach returns the percentage of all your different status codes:

data = from(bucket: "SERVERS")
  |> range(start: -1d)
  |> filter(fn: (r) => r._measurement == "http_response" and r._field == "http_response_code")

total_requests = {
  total = data
    |> group()
    |> count()
    |> tableFind(fn: (key) => true)
    |> getColumn(column: "_value")
  return total[0]
}

data
  |> group(columns: ["status_code"])
  |> count()
  |> map(fn: (r) => ({ name: r.name, _value: float(v: r._value) / float(v: total_requests) * 100.0  }))
1 Like

Great! Thanks for the code and the explanations.

No problem. Happy to help!

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.