diff --git a/endpoints/v1/index.py b/endpoints/v1/index.py index 2440cf11a..82d26837e 100644 --- a/endpoints/v1/index.py +++ b/endpoints/v1/index.py @@ -7,7 +7,7 @@ from functools import wraps from flask import request, make_response, jsonify, session from data import model -from app import authentication, userevents +from app import authentication, userevents, metric_queue from auth.auth import process_auth, generate_signed_token from auth.auth_context import get_authenticated_user, get_validated_token, get_validated_oauth_token from auth.permissions import (ModifyRepositoryPermission, UserAdminPermission, @@ -247,6 +247,7 @@ def update_images(namespace_name, repo_name): track_and_log('push_repo', repo) spawn_notification(repo, 'repo_push', event_data) + metric_queue.repository_push.Inc(labelvalues=[namespace_name, repo_name, 'v1']) return make_response('Updated', 204) abort(403) @@ -273,6 +274,7 @@ def get_repository_images(namespace_name, repo_name): resp.mimetype = 'application/json' track_and_log('pull_repo', repo, analytics_name='pull_repo_100x', analytics_sample=0.01) + metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v1']) return resp abort(403) diff --git a/endpoints/v2/manifest.py b/endpoints/v2/manifest.py index eb07bcf11..b1302d1b8 100644 --- a/endpoints/v2/manifest.py +++ b/endpoints/v2/manifest.py @@ -14,7 +14,7 @@ from jwkest.jws import SIGNER_ALGS, keyrep import features -from app import docker_v2_signing_key, app +from app import docker_v2_signing_key, app, metric_queue from auth.registry_jwt_auth import process_registry_jwt_auth from endpoints.common import parse_repository_name from endpoints.decorators import anon_protect @@ -261,6 +261,7 @@ def fetch_manifest_by_tagname(namespace_name, repo_name, manifest_ref): repo = model.repository.get_repository(namespace_name, repo_name) if repo is not None: track_and_log('pull_repo', repo, analytics_name='pull_repo_100x', analytics_sample=0.01) + metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2']) response = make_response(manifest.json_data, 200) response.headers['Content-Type'] = MANIFEST_CONTENT_TYPE @@ -283,6 +284,7 @@ def fetch_manifest_by_digest(namespace_name, repo_name, manifest_ref): repo = model.repository.get_repository(namespace_name, repo_name) if repo is not None: track_and_log('pull_repo', repo) + metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2']) response = make_response(manifest.json_data, 200) response.headers['Content-Type'] = MANIFEST_CONTENT_TYPE @@ -487,6 +489,7 @@ def _write_manifest(namespace_name, repo_name, manifest): track_and_log('push_repo', repo, tag=tag_name) spawn_notification(repo, 'repo_push', event_data) + metric_queue.repository_push.Inc(labelvalues=[namespace_name, repo_name, 'v2']) response = make_response('OK', 202) response.headers['Docker-Content-Digest'] = manifest_digest diff --git a/endpoints/verbs.py b/endpoints/verbs.py index 8a3a9a1bb..eff2ca35c 100644 --- a/endpoints/verbs.py +++ b/endpoints/verbs.py @@ -249,10 +249,12 @@ def _repo_verb(namespace, repository, tag, verb, formatter, sign=False, checker= # Check for torrent. If found, we return a torrent for the repo verb image (if the derived # image already exists). if request.accept_mimetypes.best == 'application/x-bittorrent': + metric_queue.repository_pull.Inc(labelvalues=[namespace, repository, verb + '+torrent']) return _torrent_repo_verb(repo_image, tag, verb, **kwargs) # Log the action. track_and_log('repo_verb', repo_image.repository, tag=tag, verb=verb, **kwargs) + metric_queue.repository_pull.Inc(labelvalues=[namespace, repository, verb]) # Lookup/create the derived image storage for the verb and repo image. derived = model.image.find_or_create_derived_storage(repo_image, verb, @@ -402,4 +404,5 @@ def get_tag_torrent(namespace_name, repo_name, digest): except model.BlobDoesNotExist: abort(404) + metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'torrent']) return _torrent_for_storage(blob, public_repo) diff --git a/util/metrics/metricqueue.py b/util/metrics/metricqueue.py index 303f677ef..522b0d7d1 100644 --- a/util/metrics/metricqueue.py +++ b/util/metrics/metricqueue.py @@ -28,8 +28,8 @@ class MetricQueue(object): self.non_200 = prom.create_counter('response_non200', 'Non-200 HTTP response codes', labelnames=['endpoint']) self.multipart_upload_start = prom.create_counter('multipart_upload_start', - 'Multipart upload startse') - self.multipart_upload_end = prom.create_counter('self._metric_queue.multipart_upload_end', + 'Multipart upload started') + self.multipart_upload_end = prom.create_counter('multipart_upload_end', 'Multipart upload ends.', labelnames=['type']) self.build_capacity_shortage = prom.create_gauge('build_capacity_shortage', 'Build capacity shortage.') @@ -46,6 +46,12 @@ class MetricQueue(object): 'Available items in a queue', labelnames=['queue_name']) + self.repository_pull = prom.create_counter('repository_pull', 'Repository Pull Count', + labelnames=['namespace', 'repo_name', 'protocol']) + + self.repository_push = prom.create_counter('repository_push', 'Repository Push Count', + labelnames=['namespace', 'repo_name', 'protocol']) + # Deprecated: Define an in-memory queue for reporting metrics to CloudWatch or another # provider. self._queue = None