Repository: rucio/rucio

Issue:
Metrics API endpoint: allow option to return RSEs identified by RSE attribute
### Description

Related: https://gitlab.cern.ch/atlas-adc-ddm/flux-rucio/-/issues/10

Example calls:
- `requests/metrics?group=site`
- `requests/metrics?group=tier`

### Motivation

_No response_

### Change

_No response_
Metrics API endpoint: allow option to return RSEs identified by RSE attribute
### Description

Related: https://gitlab.cern.ch/atlas-adc-ddm/flux-rucio/-/issues/10

Example calls:
- `requests/metrics?group=site`
- `requests/metrics?group=tier`

### Motivation

_No response_

### Change

_No response_


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/request.py b/lib/rucio/core/request.py
--- a/lib/rucio/core/request.py
+++ b/lib/rucio/core/request.py
@@ -114,7 +114,6 @@ def __init__(
             transfertool: str,
             requested_at: Optional[datetime.datetime] = None,
     ):
-
         self.request_id = id_
         self.request_type = request_type
         self.rule_id = rule_id
@@ -1856,6 +1855,7 @@ def get_request_metrics(
         dest_rse_id: "Optional[str]" = None,
         src_rse_id: "Optional[str]" = None,
         activity: "Optional[str]" = None,
+        group_by_rse_attribute: "Optional[str]" = None,
         *,
         session: "Session"
 ):
@@ -1934,7 +1934,13 @@ def get_request_metrics(
         metric['src_rse'] = src_rse.name
         metric['dst_rse'] = dst_rse.name
 
-        response[f'{src_rse.name}:{dst_rse.name}'] = metric
+        if group_by_rse_attribute:
+            src_rse_group = src_rse.attributes.get(group_by_rse_attribute, 'UNKNOWN')
+            dst_rse_group = dst_rse.attributes.get(group_by_rse_attribute, 'UNKNOWN')
+            if src_rse_group is not None and dst_rse_group is not None:
+                response[f'{src_rse_group}:{dst_rse_group}'] = metric
+        else:
+            response[f'{src_rse.name}:{dst_rse.name}'] = metric
 
     return response
 
diff --git a/lib/rucio/gateway/request.py b/lib/rucio/gateway/request.py
--- a/lib/rucio/gateway/request.py
+++ b/lib/rucio/gateway/request.py
@@ -219,13 +219,14 @@ def list_requests_history(src_rses, dst_rses, states, issuer, vo='def', offset=N
 
 
 @read_session
-def get_request_metrics(src_rse: Optional[str], dst_rse: Optional[str], activity: Optional[str], issuer, vo='def', *, session: "Session"):
+def get_request_metrics(src_rse: Optional[str], dst_rse: Optional[str], activity: Optional[str], group_by_rse_attribute: Optional[str], issuer, vo='def', *, session: "Session"):
     """
     Get statistics of requests in a specific state grouped by source RSE, destination RSE, and activity.
 
     :param src_rse: source RSE.
     :param dst_rse: destination RSE.
     :param activity: activity
+    :param group_by_rse_attribute: The parameter to group the RSEs by.
     :param issuer: Issuing account as a string.
     :param session: The database session in use.
     """
@@ -239,4 +240,4 @@ def get_request_metrics(src_rse: Optional[str], dst_rse: Optional[str], activity
     if not permission.has_permission(issuer=issuer, vo=vo, action='get_request_metrics', kwargs=kwargs, session=session):
         raise exception.AccessDenied(f'{issuer} cannot get request statistics')
 
-    return request.get_request_metrics(dest_rse_id=dst_rse_id, src_rse_id=src_rse_id, activity=activity, session=session)
+    return request.get_request_metrics(dest_rse_id=dst_rse_id, src_rse_id=src_rse_id, activity=activity, group_by_rse_attribute=group_by_rse_attribute, session=session)
diff --git a/lib/rucio/web/rest/flaskapi/v1/requests.py b/lib/rucio/web/rest/flaskapi/v1/requests.py
--- a/lib/rucio/web/rest/flaskapi/v1/requests.py
+++ b/lib/rucio/web/rest/flaskapi/v1/requests.py
@@ -847,6 +847,11 @@ def get(self):
           description: The activity
           schema:
             type: string
+        - name: group_by_rse_attribute
+          in: query
+          description: The parameter to group the RSEs by.
+          schema:
+            type: string
         responses:
           200:
             description: OK
@@ -947,12 +952,14 @@ def get(self):
         dst_rse = flask.request.args.get('dst_rse', default=None)
         src_rse = flask.request.args.get('src_rse', default=None)
         activity = flask.request.args.get('activity', default=None)
+        group_by_rse_attribute = flask.request.args.get('group_by_rse_attribute', default=None)
         format = flask.request.args.get('format', default=None)
 
         metrics = request.get_request_metrics(
             dst_rse=dst_rse,
             src_rse=src_rse,
             activity=activity,
+            group_by_rse_attribute=group_by_rse_attribute,
             issuer=flask.request.environ.get('issuer'),
             vo=flask.request.environ.get('vo')
         )


Test patch: