OntVacStat/main.go

338 lines
14 KiB
Go

package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/cabify/gotoprom"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/robfig/cron/v3"
)
var addr = flag.String("listen-address", "127.0.0.1:8080", "The address to listen on for HTTP requests.")
type OntCovidData struct {
Help string `json:"help"`
Success bool `json:"success"`
Result struct {
Sort string `json:"sort"`
IncludeTotal bool `json:"include_total"`
ResourceID string `json:"resource_id"`
Fields []struct {
Type string `json:"type"`
ID string `json:"id"`
Info struct {
Notes string `json:"notes"`
TypeOverride string `json:"type_override"`
Label string `json:"label"`
} `json:"info,omitempty"`
} `json:"fields"`
RecordsFormat string `json:"records_format"`
Records []struct {
ID int `json:"_id"`
ReportDate string `json:"report_date"`
PreviousDayDosesAdministered json.Number `json:"previous_day_total_doses_administered"`
PreviousDayAtLeastOne json.Number `json:"previous_day_at_least_one"`
PreviousDayFullyVaccinated json.Number `json:"previous_day_fully_vaccinated"`
TotalDosesAdministered json.Number `json:"total_doses_administered"`
TotalDosesAtLeastOne json.Number `json:"total_individuals_at_least_one"`
TotalDosesInFullyVaccinatedIndividuals json.Number `json:"total_doses_in_fully_vaccinated_individuals"`
TotalIndividualsFullyVaccinated json.Number `json:"total_individuals_fully_vaccinated"`
} `json:"records"`
Limit int `json:"limit"`
Links struct {
Start string `json:"start"`
Next string `json:"next"`
} `json:"_links"`
Total int `json:"total"`
} `json:"result"`
}
type OntCovidDataByAge struct {
Help string `json:"help"`
Success bool `json:"success"`
Result struct {
IncludeTotal bool `json:"include_total"`
ResourceID string `json:"resource_id"`
Fields []struct {
Type string `json:"type"`
ID string `json:"id"`
Info struct {
Notes string `json:"notes"`
TypeOverride string `json:"type_override"`
Label string `json:"label"`
} `json:"info,omitempty"`
} `json:"fields"`
RecordsFormat string `json:"records_format"`
Records []struct {
ID int `json:"_id"`
Date string `json:"Date"`
Agegroup string `json:"Agegroup"`
AtLeastOneDoseCumulative json.Number `json:"At least one dose_cumulative"`
SecondDoseCumulative json.Number `json:"Second_dose_cumulative"`
TotalPopulation json.Number `json:"Total population"`
PercentAtLeastOneDose json.Number `json:"Percent_at_least_one_dose"`
PercentFullyVaccinated json.Number `json:"Percent_fully_vaccinated"`
} `json:"records"`
Limit int `json:"limit"`
Links struct {
Start string `json:"start"`
Next string `json:"next"`
} `json:"_links"`
Total int `json:"total"`
} `json:"result"`
}
type AgeRecord struct {
AtLeastOneDoseCumulative func() prometheus.Gauge `name:"at_least_one_dose_cumaltive" help:""`
SecondDoseCumulative func() prometheus.Gauge `name:"second_dose_cumulative" help:""`
TotalPopulation func() prometheus.Gauge `name:"total_population" help:""`
PercentAtLeastOneDose func() prometheus.Gauge `name:"percent_at_least_one_dose" help:""`
PercentFullyVaccinated func() prometheus.Gauge `name:"percent_fully_vaccinated" help:""`
}
type DataRecord struct {
PreviousDayDosesAdministered func() prometheus.Gauge `name:"previous_day_doses_administered" help:"Previous day doses administered"`
PreviousDayAtLeastOne func() prometheus.Gauge `name:"previous_day_at_least_one" help:"Previous day doses administered at least one shot"`
PreviousDayFullyVaccinated func() prometheus.Gauge `name:"previous_day_fully_vaccinated" help:"Previous day doses administered fully vaccinated"`
TotalDosesAdministered func() prometheus.Gauge `name:"total_doses_administered" help:"Total doses administered"`
TotalDosesAtLeastOne func() prometheus.Gauge `name:"total_individuals_at_least_one" help:"Total at least one dose in individuals"`
TotalDosesInFullyVaccinatedIndividuals func() prometheus.Gauge `name:"total_doses_in_fully_vaccinated_individuals" help:"Total does in fully vaccinated individuals"`
TotalIndividualsFullyVaccinated func() prometheus.Gauge `name:"total_individuals_fully_vaccinated" help:"Total individuals fully vaccinated"`
EligiblePopulation func() prometheus.Gauge `name:"eligible_population" help:"Total population eligible for the vaccination"`
Age12To17yrs AgeRecord `namespace:"age_12_17yrs"`
Age18To29yrs AgeRecord `namespace:"age_18_29yrs"`
Age30To39yrs AgeRecord `namespace:"age_30_39yrs"`
Age40To49yrs AgeRecord `namespace:"age_40_49yrs"`
Age50To59yrs AgeRecord `namespace:"age_50_59yrs"`
Age60To69yrs AgeRecord `namespace:"age_60_69yrs"`
Age70To79yrs AgeRecord `namespace:"age_70_79yrs"`
Age80Plus AgeRecord `namespace:"age_80_plus"`
AgeAdults18Plus AgeRecord `namespace:"age_adult_18_plus"`
AgeUndisclosedOrMissing AgeRecord `namespace:"age_undisclosed_or_missing"`
}
var dataRecord DataRecord
func init() {
gotoprom.MustInit(&dataRecord, "ontvacstat")
}
func fetchUrl(dataUrl string) []byte {
resp, getErr := http.Get(dataUrl)
if getErr != nil {
log.Println(getErr)
}
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
log.Println(readErr)
}
return body
}
func updateMetrics() {
dataUrl := "https://data.ontario.ca/api/3/action/datastore_search?sort=report_date+desc&limit=1&resource_id=8a89caa9-511c-4568-af89-7f2174b4378c"
dataAgeUrl := "https://data.ontario.ca/api/3/action/datastore_search?resource_id=775ca815-5028-4e9b-9dd4-6975ff1be021&sort=Date%20desc&limit=9"
eligiblePopulation := 0.0
dataUrlOut := fetchUrl(dataUrl)
data := OntCovidData{}
dataErr := json.Unmarshal(dataUrlOut, &data)
if dataErr != nil {
log.Println(dataUrl, dataErr)
return
}
dataAgeUrlOut := fetchUrl(dataAgeUrl)
dataAge := OntCovidDataByAge{}
dataAgeErr := json.Unmarshal(dataAgeUrlOut, &dataAge)
if dataAgeErr != nil {
log.Println(dataAgeUrl, dataAgeErr)
return
}
previousDayDosesAdministered, err := data.Result.Records[0].PreviousDayDosesAdministered.Float64()
if err != nil {
log.Println(err)
}
previousDayAtLeastOne, err := data.Result.Records[0].PreviousDayAtLeastOne.Float64()
if err != nil {
log.Println(err)
}
previousDayFullyVaccinated, err := data.Result.Records[0].PreviousDayFullyVaccinated.Float64()
if err != nil {
log.Println(err)
}
totalDosesAdministered, err := data.Result.Records[0].TotalDosesAdministered.Float64()
if err != nil {
log.Println(err)
}
totalDosesAtLeastOne, err := data.Result.Records[0].TotalDosesAtLeastOne.Float64()
if err != nil {
log.Println(err)
}
totalDosesInFullyVaccinatedIndividuals, err := data.Result.Records[0].TotalDosesInFullyVaccinatedIndividuals.Float64()
if err != nil {
log.Println(err)
}
totalIndividualsFullyVaccinated, err := data.Result.Records[0].TotalIndividualsFullyVaccinated.Float64()
if err != nil {
log.Println(err)
}
for _, record := range dataAge.Result.Records {
atLeastOneDoseCumulative, err := record.AtLeastOneDoseCumulative.Float64()
if err != nil {
log.Println(err)
}
secondDoseCumulative, err := record.SecondDoseCumulative.Float64()
if err != nil {
log.Println(err)
}
totalPopulation, err := record.TotalPopulation.Float64()
if err != nil {
log.Println(err)
}
percentAtLeastOneDose, err := record.PercentAtLeastOneDose.Float64()
if err != nil {
log.Println(err)
}
percentFullyVaccinated, err := record.PercentFullyVaccinated.Float64()
if err != nil {
log.Println(err)
}
switch record.Agegroup {
case "12-17yrs":
{
dataRecord.Age12To17yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age12To17yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age12To17yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age12To17yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age12To17yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "18-29yrs":
{
dataRecord.Age18To29yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age18To29yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age18To29yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age18To29yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age18To29yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "30-39yrs":
{
dataRecord.Age30To39yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age30To39yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age30To39yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age30To39yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age30To39yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "40-49yrs":
{
dataRecord.Age40To49yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age40To49yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age40To49yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age40To49yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age40To49yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "50-59yrs":
{
dataRecord.Age50To59yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age50To59yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age50To59yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age50To59yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age50To59yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "60-69yrs":
{
dataRecord.Age60To69yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age60To69yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age60To69yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age60To69yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age60To69yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "70-79yrs":
{
dataRecord.Age70To79yrs.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age70To79yrs.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age70To79yrs.TotalPopulation().Set(totalPopulation)
dataRecord.Age70To79yrs.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age70To79yrs.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "80+":
{
dataRecord.Age80Plus.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.Age80Plus.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.Age80Plus.TotalPopulation().Set(totalPopulation)
dataRecord.Age80Plus.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.Age80Plus.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
case "Adults_18plus":
{
dataRecord.AgeAdults18Plus.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.AgeAdults18Plus.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.AgeAdults18Plus.TotalPopulation().Set(totalPopulation)
dataRecord.AgeAdults18Plus.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.AgeAdults18Plus.PercentFullyVaccinated().Set(percentFullyVaccinated)
}
case "Undisclosed_or_missing":
{
dataRecord.AgeUndisclosedOrMissing.AtLeastOneDoseCumulative().Set(atLeastOneDoseCumulative)
dataRecord.AgeUndisclosedOrMissing.SecondDoseCumulative().Set(secondDoseCumulative)
dataRecord.AgeUndisclosedOrMissing.TotalPopulation().Set(totalPopulation)
dataRecord.AgeUndisclosedOrMissing.PercentAtLeastOneDose().Set(percentAtLeastOneDose)
dataRecord.AgeUndisclosedOrMissing.PercentFullyVaccinated().Set(percentFullyVaccinated)
eligiblePopulation += totalPopulation
}
default:
{
log.Println("Unknown Age Group: ", record.Agegroup)
}
}
}
dataRecord.PreviousDayDosesAdministered().Set(previousDayDosesAdministered)
dataRecord.PreviousDayAtLeastOne().Set(previousDayAtLeastOne)
dataRecord.PreviousDayFullyVaccinated().Set(previousDayFullyVaccinated)
dataRecord.TotalDosesAdministered().Set(totalDosesAdministered)
dataRecord.TotalDosesAtLeastOne().Set(totalDosesAtLeastOne)
dataRecord.TotalDosesInFullyVaccinatedIndividuals().Set(totalDosesInFullyVaccinatedIndividuals)
dataRecord.TotalIndividualsFullyVaccinated().Set(totalIndividualsFullyVaccinated)
dataRecord.EligiblePopulation().Set(float64(eligiblePopulation))
}
func main() {
c := cron.New()
c.AddFunc("@hourly", func() { updateMetrics() })
c.Start()
updateMetrics()
flag.Parse()
http.Handle("/metrics", promhttp.Handler())
fmt.Println("Listening on port 8080")
log.Fatal(http.ListenAndServe(*addr, nil))
}