Skip to content

feat: added capability to extract metrics from the logs - #101

Open
CptSchnitz wants to merge 3 commits into
masterfrom
logs-to-metrics
Open

CptSchnitz wants to merge 3 commits into
masterfrom
logs-to-metrics

Conversation

@CptSchnitz

Copy link
Copy Markdown

Main feature: derive Prometheus metrics from nginx access logs via Fluent Bit, instead of just shipping raw logs.

  • OGC request parsing (Lua) — new custom.lua script hooked into Fluent Bit that parses both KVP (?service=WMS&request=...) and RESTful (/wmts/.../{z}/{x}/{y}.{fmt}) URLs to extract ogc_service, ogc_operation, ogc_layer, ogc_zoom (bucketed into ogc_zoom_group to control cardinality), and ogc_format, plus a normalized result (ok/error) and request_time_seconds.
  • Metrics generation (log_to_metrics filters) — new Fluent Bit filters that turn the parsed log fields into:
    • mapproxy_wms_requests_total / mapproxy_wmts_requests_total counters (by operation, layer, format, result — WMTS also labeled by client name)
    • nginx_http_errors_total counter for all 4xx/5xx responses
    • mapproxy_{wms,wmts}_request_duration_seconds latency histograms (labeled by result)
  • Simplified log format — dropped the large, verbose log_format.conf (nginx log_format directive with ~50 fields) since raw stdout logs are no longer needed now that metrics are extracted (chore: remove stdout).
  • Dependency bump — nginx subchart upgraded 2.3.1 → 2.4.0 to pick up the fluentbit/log_to_metrics/Lua filter support this feature relies on.

Net effect: mapproxy nginx now exports structured request/latency metrics (by OGC service, operation, layer, zoom bucket, format, and error status) directly from access logs, rather than relying on log aggregation alone.

@shimoncohen shimoncohen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few notes from review — nothing blocking. Cardinality note on the WMS layer label, two label/parsing edge cases, and one nit for awareness.

Comment thread helm/values.yaml
regex: ogc_service ^WMS$
label_field:
- ogc_operation
- ogc_layer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note (not blocking): WMS LAYERS is comma-separated, and custom.lua sets ogc_layer verbatim, so multi-layer combos would each be a distinct series on mapproxy_wms_requests_total — same cardinality concern zoom_group bucketing guards against, but for layer. In our case only one layer is used per request, so this is fine; noting it since it's not enforced anywhere.

Comment thread helm/values.yaml
metric_name: requests_total
metric_description: Total WMTS requests
regex: ogc_service ^WMTS$
add_label: client_name $Attributes['mapcolonies.http.auth.token.client_name']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client_name is added unconditionally, but mapcolonies.http.auth.token.client_name was only populated under and .opalaEnabled .nginx.authorization.enabled (old log_format.conf). With authorization disabled the accessor won't resolve → empty/literal client_name label on every WMTS series. Gate the add_label on the same condition, or accept the noise deliberately.

Comment thread helm/config/custom.lua
local lower_path = string.lower(path)

if lower_path:find("/wmts/") then
local pattern = "/wmts/([^/]+)/([^/]+)/(%d+)/(%d+)/(%d+)%.(%w+)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zoom is captured as (%d+), so if the RESTful TileMatrix segment isn't a bare integer (e.g. gridset-prefixed EPSG:4326:10) the whole tile pattern fails, falls through to return nil, and the request is dropped from all metrics. Fine if our gridsets use numeric TileMatrix ids — worth confirming.

Comment thread helm/config/custom.lua
local function parse_query_string(query)
local params = {}
if not query or query == "" then return params end
for k, v in query:gmatch("([^&]+)=([^&]+)") do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (awareness only): ([^&]+)=([^&]+) silently skips valueless params (&flag& or key=). Harmless for the OGC params we parse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants