Filtering posts - complicated case of a status page

hi there! i’m reaching out for help because one of my most requested features on the theme/project cState—an open source status page of mine

i’ll try to give as much context as possible with examples (and links) which I hope will suffice

what the project is

there are issues in content/issues like gateway-latency.md or whatnot. Each issue has a markup that looks like this:

---
title: Issues Sending DMs
date: 2018-01-17 16:24:00
resolved: true
resolvedWhen: 2018-01-17 16:58:00
# Possible severity levels: down, disrupted, notice
severity: disrupted
affected:
  - API
section: issue
---

*Investigating* - We're aware of an issue affecting sending DMs and viewing online friends. We're online and working on a resolution.

every issue must have a section of “issue” and all the other outlined fields. what’s particularly going to be relevant is the “severity” & “affected” ones

how the current system works

this is for the homepage (see: https://cstate.mnts.lt) where we see what issues aren’t resolved and therefore changing the status from OK to disrupted or whatever

we first get the posts and filter out which, again, aren’t resolved

we also want to get each post’s severity (and this is kind of where the problem comes in)

{{ $incidents := where .Site.RegularPages "Params.section" "issue" }}
{{ $active := where $incidents "Params.resolved" "=" false }}

{{ $isNotice := where $active "Params.severity" "=" "notice" }}
{{ $isDisrupted := where $active "Params.severity" "=" "disrupted" }}
{{ $isDown := where $active "Params.severity" "=" "down" }}

let’s say there are 2 issues. one is just maintenance, but the other is big major downtime. you’d want to show that there is major downtime instead of just maintenance (even though there’s both) because downtime is more relevant than maintenance, the severity is higher:

        {{ $activeComponentIssues := where $active "Params.affected" "intersect" (slice .name) }}

        {{ $thisIsNotice := where $activeComponentIssues "Params.severity" "=" "notice" }}
        {{ $thisIsDisrupted := where $activeComponentIssues "Params.severity" "=" "disrupted" }}
        {{ $thisIsDown := where $activeComponentIssues "Params.severity" "=" "down" }}

        <span class="component-status">
          {{ if $thisIsDown }}
            <b>{{ T "thisIsDown" }}</b>
          {{ else }}
          {{ if $thisIsDisrupted }}
            <b>{{ T "thisIsDisrupted" }}</b>
          {{ else }}
          {{ if $thisIsNotice }}
            <b>{{ T "thisIsNotice" }}</b>
          {{ else }}
            {{ T "thisIsOk" }}
          {{ end }}{{ end }}{{ end }}
        </span>

that beautiful code shows either “Operational”, “Disrupted”, “Down” or “Maintenance” next to the name of a system/compoenent, like the Gateway, API< etc.

adding multiple severities

issue link: https://github.com/cstate/cstate/issues/47

let’s say the issues now look like this:

severity: disrupted # might be worth keeping?
affected:
  - API: disrupted
  - Web: down

then we want to show on the homepage for all systems, either:

  • one of them is completely down => we’re having major issues
  • one of them is disrupted, but neither is down => we have disruptions
  • there’s maintenance, but no disruptions nor downtime => read announcement
  • and finally if there’s no active issues then => we’re all doing ok everything is fine

so in each issue you have to check if ANY system is “down”, “disrupted” or on “notice”.

that means, like in my example, the summry would display: “We’re having major issues.”

But all of the affected systems should be shown correctly, as in:

  • Gateway: operational (not shown here at all)
  • API: disrupted
  • Web: down

the way that this currently works would make it:

severity: down
affected:
  - API
  - Web
  • gateway: operational
  • API: down
  • Web: down

closing notes

long post but I hope to find some insight or answers

for those who read everything - thank you! a solution would be awesome, of course, but any support/thoughts/opinions/hopes/dreams is/are welcome

I think that you need to use and/or logic to achieve what you need.
Something like:

{{ if or ( and ($notice) ($disrupted) ) ($down) }}

Here is a useful blog post for Conditionals in Go templates (it’s from 2017 but it’s quite good actually):

The problem is filtering the status. When there’s more than just one severity in ONE issue, what do?

Cause what I need to do is find the general highest status and then find the individual status for each system?

Does this system allow you to pull data? If it were my project, I would first think how can I get the data via some API, then I would probably massage the data with a script, making it easy for hugo to process via index or whatever. For instance, using stedolan jq to filter the json from the API to what I need. Then, pull that in via a shortcode in markdown, or even via a single template.

The data is in content. It’s all in Hugo.

I’m trying to go for simplicity but I’m not sure how to accomplish that with multiple severities.

Perhaps setting each severity for every system/component? Would that… help? lol

If the pages are going to be looking at a relatively simple data set then, you could just create a csv or whatever to pull from.

Given that format, this is what I think I would do:

  • Assign a numeric value to the severity: 0 is fine, 3 is down for example.
  • range through the issues, take the max severity
  • display all issues and corresponding severity per system
  • display the max

So something like

{{ range $pages }}
{{ $liststat := slice }} <!-- take all severity values -->

{{ range .Params.affected }}
  {{ range $system, $status := . }}
    {{$system}}: {{$status}}<br>

    {{ $currentstat := 0 }}
    {{ if eq $status "maintenance" }}{{ $currentstat = 1 }}
    {{ else if eq $status "disrupted" }}{{ $currentstat = 2 }}
    {{/* etc */}}
    {{ end }}
    {{ $liststat = $liststat | append $currentstat }}
  {{ end }}
{{ end }}

Overall Status: {{ first 1 (sort $liststat "value" "desc") }}
<!-- this is the max; add conditional to decide what to display based on value -->

{{ end }}

Interesting, thank you a lot for the example. Is it possible to do this not numerically? I’m (rather unsuccessfully) trying to be as backwards compatible as possible

As the cool kids are wont to say, “search and replace”. :sunglasses:

to put it bluntly, I have no idea what you mean to say

Never mind. :slight_smile:

You don’t have to use a numerical system, it’s just easier for sorting / getting the max severity value.

You could push the $status values as is into $liststat, then instead of the sort statement, do a big if-else-if chunk going down severity levels:

{{ if in $liststat "down" }}
{{ else if in $liststat "disrupted" }}
...etc...

So, I think I’m going to go with this solution. Edited it a tad, looks like this:

{{ $incidents := where .Site.RegularPages "Params.section" "issue" }}
{{ $active := where $incidents "Params.resolved" "=" false }}

{{ range $active }}
  {{ $liststat := slice }} <!-- take all severity values -->

  {{ range .Params.affected }}
    {{ .name }}: {{ .severity }}<br>

    {{ $currentstat := 0 }}
    {{ if eq .severity "maintenance" }}{{ $currentstat = 1 }}
    {{ else if eq .severity "disrupted" }}{{ $currentstat = 2 }}
    {{ else if eq .severity "down" }}{{ $currentstat = 3 }}
    {{ end }}
    {{ $liststat = $liststat | append $currentstat }}
  {{ end }}

  <br>
  Overall Status: {{ first 1 (sort $liststat "value" "desc") }}<br><br>
  <!-- this is the max; add conditional to decide what to display based on value -->

{{ end }}

And, of course, issues look like this:

---
title: US East Connection Issues
date: 2018-05-25 04:13:00
resolved: false
resolvedWhen: 2018-05-25 04:13:59
# Possible severity levels: down, disrupted, notice
affected:
  - name: API
    severity: down
  - name: Media Proxy
    severity: down
  - name: Gateway
    severity: disrupted
section: issue
---

*Resolved* -
We believe all users experiencing issues...

This is awesome, but I need to show the overall status of not only each issue, but a general system (like API, Media Proxy, etc) and then the overall status of EVERYTHING.

The output looks something like this right now:

API: disrupted
Backup Gateway: maintenance

Overall Status: [2]

API: down
Media Proxy: down
Gateway: disrupted

Overall Status: [3]

How would I accomplish something like this instead for filtering by systems, not incidents?

Media Proxy: Overall Status [3]
Backup Gateway: Overall Status [2]

‘Cause I don’t know how to apply the code in a shorter format like this (the code shown finds issues with a specific severity defined in the frontmatter, but I need to get the overall status here now):

{{ $incidents := where .Site.RegularPages "Params.section" "issue" }}
{{ $active := where $incidents "Params.resolved" "=" false }}

{{ $isNotice := where $active "Params.severity" "=" "notice" }}
{{ $isDisrupted := where $active "Params.severity" "=" "disrupted" }}
{{ $isDown := where $active "Params.severity" "=" "down" }}

Have I explained it well enough?

Would love some examples to deal with this, my main blocker.