BareGit
# Status Tracker

A simple self-hosted service status tracker.

## Requirements

- C++
- User Cmake to build.
- All external dependencies should be pulled using `FetchContent`,
  except for basic ones like OpenSSL, SQLite, etc. `FetchContent`
  should not pin to specific version of these dependencies. But some
  dependencies may need a branch specified.
- No authentication. The web UI is read-only and data-driven.
- YAML configuration
- It monitors a bunch of endpoints which are defined in the
  config file
- Endpoints may be monitored by one of the following protocols:
  * HTTP (check it returns 2xx status)
  * TCP or UDP port open
  * ICMP
- Possible config snippet for endpoint:

  ```yaml
  some-endpoint-id: # A uniq ID
    name: Blog
    description: It’s my blog.
    # User-facing URL
    url: https://blog.mws.rocks/
    endpoint:
      # Different protocols may have different set of fields.
      protocol: HTTP
      # This could be different from the user-facing URL. If this is omitted, use the user-facing URL
      url: https://blog.mws.rocks/
      timeout_second: 5
    interval:
      value: 1
      unit: minute
  ```

  Another:

  ```yaml
  some-endpoint-id: # A uniq ID
    name: VM host
    description: My VM host
    endpoint:
      protocol: ICMP
      host: 10.10.10.20
      timeout_second: 5
    interval:
      value: 1
      unit: minute
  ```

- In the config file the endpoints are grouped with another level of
  grouping. This grouping is also shown in the web UI.
- Stores status history in SQLite db.
- Endpoint status: There should be four possible status: good, bad,
  other, and n/a. Right now we can reserve “other” for the case where
  UDP probe does not get a response. “N/a” is the case where there is
  no data in the database (which is different from the service being
  unavailable) or data is staled (the last data point is more than
  twice the interval old). These status should be indicated on
  the webpage with a “LED light”. Good is green, bad is red, other is
  yellow, n/a is dimmed light.
- In the database, each status update has:
  * Service ID (the uniq ID defined in the config)
  * Timestamp with precision to a second (UTC unix timestamp)
  * Duration in microseconds (the time it takes to finish the status
    check)
  * Status (integer)

## Probe scheduling

- Probe workflow:
  1. A priority queue of tasks, ordered by next due time.
  2. Each endpoint has an atomic bool `in_flight`.
  3. The scheduler dequeue a task, If no worker is available, ditch
     the task. If there is a worker available, if the endpoint is
     already inflight, ditch the task; otherwise mark the endpoint as
     inflight, and dispatch it to a worker.
  4. The scheduler enqueue the next task of that endpoint. Note that
     if the schedued time of the next task is in the past, we should
     find the next one that’s in the future.
  5. The scheduler peeks the queue and wait for the next task to
     trigger.
  6. Meanwhile the worker does the probing, and save the result to db
  7. worker marks the endpoint as not inflight.

- Each worker is a thread in a thread pool with a fixed capacity. The
  capacity is defined in the config file.

## UI

- Server-rendered HTML
- No live updates. The user should referesh if they want new data
- Use Inja for templates
- Templates and static files are compiled into the binary at build
  time. In the repository they are individual files in the file
  system.