diff --git a/progs/registry.mtail b/progs/registry.mtail index 1b6bdb0..34e9261 100644 --- a/progs/registry.mtail +++ b/progs/registry.mtail @@ -9,44 +9,46 @@ counter registry_push_upload_bytes_total by repo, user, node counter registry_push_upload_seconds_total by repo, user, node # -------- Field extraction (order-independent) -/\"method\":\"([A-Z]+)\"/ { method = $1 } -/\"path\":\"([^\"]+)\"/ { path = $1 } -/\"remote_address\":\"([^\"]*)\"/ { node = $1 } -/\"remote_user\":\"([^\"]*)\"/ { user = $1 } -/\"status\":([0-9]{3})/ { status = $1 } -/\"request_time\":([0-9.]+)/ { request_time = $1 } -/\"body_bytes_sent\":([0-9]+)/ { body_bytes_sent = $1 } -/\"upstream_range\":\"([^\"]*)\"/ { up_range = $1 } -/\"docker_upload_uuid\":\"([^\"]*)\"/ { upload_uuid = $1 } -/\"docker_content_digest\":\"([^\"]*)\"/ { digest = $1 } +/"method":"([A-Z]+)"/ { method = $1 } +/"path":"([^"]+)"/ { path = $1 } +/"remote_address":"([^"]*)"/ { node = $1 } +/"remote_user":"([^"]*)"/ { user = $1 } +/"status":([0-9]{3})/ { status = $1 } +/"request_time":([0-9.]+)/ { request_time = $1 } +/"body_bytes_sent":([0-9]+)/ { body_bytes_sent = $1 } +/"upstream_range":"([^"]*)"/ { up_range = $1 } +/"docker_upload_uuid":"([^"]*)"/ { upload_uuid = $1 } +/"docker_content_digest":"([^"]*)"/ { digest = $1 } -/\"path\":\"\/v2\/(.+?)\/(blobs|manifests|tags|_catalog)/ { - repo = $1 # supports namespaces like org/team/repo +# Capture namespace/repo between /v2/ and the next section (blobs|manifests|tags|_catalog) +/"path":"\/v2\/(.+?)\/(blobs|manifests|tags|_catalog)/ { + repo = $1 } -# Defaults per line +# Defaults per line (and a tiny reset) /$/ { if repo == "" { repo = "unknown" } if user == "" { user = "anonymous" } if node == "" { node = "unknown" } + if uploaded_bytes == 0 { uploaded_bytes = 0 } # explicit init per line } # Helper: parse upstream_range "a-b" => bytes = b+1 -/\"upstream_range\":\"([0-9]+)-([0-9]+)\"/ { +/"upstream_range":"([0-9]+)-([0-9]+)"/ { uploaded_bytes = int($2) + 1 } # -------- Classify & emit # Downloaded blob bytes/time: GET /v2//blobs/sha256:... -/\"method\":\"GET\".*\"\/v2\/.+\/blobs\/sha256:[a-f0-9]+\"/ { +/"method":"GET".*"\/v2\/.+\/blobs\/sha256:[a-f0-9]+"/ { registry_pull_blob_bytes_total[repo=repo, user=user, node=node] += body_bytes_sent registry_pull_blob_seconds_total[repo=repo, user=user, node=node] += request_time registry_requests_total[method=method, path_class="pull_blob", status=string(status), repo=repo, user=user, node=node]++ } # Upload data transfer: PATCH /v2//blobs/uploads/ 202 -/\"method\":\"PATCH\".*\"\/v2\/.+\/blobs\/uploads\/[a-f0-9-]+\"/ { +/"method":"PATCH".*"\/v2\/.+\/blobs\/uploads\/[a-f0-9-]+"/ { if uploaded_bytes > 0 { registry_push_upload_bytes_total[repo=repo, user=user, node=node] += uploaded_bytes } @@ -56,24 +58,24 @@ counter registry_push_upload_seconds_total by repo, user, node } # Upload session start/end (bookkeeping) -/\"method\":\"POST\".*\"\/v2\/.+\/blobs\/uploads\/\"/ { +/"method":"POST".*"\/v2\/.+\/blobs\/uploads\/"/ { registry_requests_total[method=method, path_class="push_start", status=string(status), repo=repo, user=user, node=node]++ } -/\"method\":\"PUT\".*\"\/v2\/.+\/blobs\/uploads\/[a-f0-9-]+/ { +/"method":"PUT".*"\/v2\/.+\/blobs\/uploads\/[a-f0-9-]+"/ { registry_requests_total[method=method, path_class="push_commit", status=string(status), repo=repo, user=user, node=node]++ } # Manifest pulls -/\"method\":\"GET\".*\"\/v2\/.+\/manifests\/[^\"]+\"/ { +/"method":"GET".*"\/v2\/.+\/manifests\/[^"]+"/ { registry_requests_total[method=method, path_class="pull_manifest", status=string(status), repo=repo, user=user, node=node]++ } # Manifest writes -/\"method\":\"PUT\".*\"\/v2\/.+\/manifests\/[^\"]+\"/ { +/"method":"PUT".*"\/v2\/.+\/manifests\/[^"]+"/ { registry_requests_total[method=method, path_class="push_manifest", status=string(status), repo=repo, user=user, node=node]++ } # Root auth probe -/\"path\":\"\/v2\/\"/ { +/"path":"\/v2\/"/ { registry_requests_total[method=method, path_class="v2_root", status=string(status), repo="none", user=user, node=node]++ }