File indexing completed on 2026-04-09 07:58:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 import datetime
0012 from traceback import format_exc
0013
0014 from flask import Blueprint
0015
0016 from idds.common import exceptions
0017 from idds.common.constants import HTTP_STATUS_CODE
0018 from idds.core.requests import get_requests
0019 from idds.rest.v1.controller import IDDSController
0020
0021
0022 class Monitor(IDDSController):
0023 """ Monitor """
0024
0025 def get_month_list(self, start, end):
0026 mlist = []
0027 total_months = lambda dt: dt.month + 12 * dt.year
0028 for tot_m in range(total_months(start) - 1, total_months(end)):
0029 y, m = divmod(tot_m, 12)
0030 mlist.append(datetime.datetime(y, m + 1, 1).strftime("%Y-%m"))
0031 return mlist
0032
0033 def get_requests(self, request_id, workload_id, with_request=False, with_transform=False, with_processing=False):
0034
0035 if with_request:
0036 rets, ret_reqs = [], {}
0037 reqs = get_requests(request_id=request_id, workload_id=workload_id,
0038 with_request=False, with_transform=True, with_processing=with_processing,
0039 with_detail=False, with_metadata=False)
0040 for req in reqs:
0041 if req['request_id'] not in ret_reqs:
0042 ret_reqs[req['request_id']] = {'request_id': req['request_id'],
0043 'workload_id': req['workload_id'],
0044 'status': req['status'].name if req['status'] else req['status'],
0045 'created_at': req['created_at'],
0046 'updated_at': req['updated_at'],
0047 'transforms': {},
0048 'input_total_files': 0,
0049 'input_coll_bytes': 0,
0050 'input_processed_files': 0,
0051 'input_processing_files': 0,
0052 'output_total_files': 0,
0053 'output_coll_bytes': 0,
0054 'output_processed_files': 0,
0055 'output_processing_files': 0
0056 }
0057 if req['transform_status']:
0058 if req['transform_status'].name not in ret_reqs[req['request_id']]['transforms']:
0059 ret_reqs[req['request_id']]['transforms'][req['transform_status'].name] = 0
0060 ret_reqs[req['request_id']]['transforms'][req['transform_status'].name] += 1
0061
0062 if 'input_total_files' in req and req['input_total_files']:
0063 ret_reqs[req['request_id']]['input_total_files'] += req['input_total_files']
0064 if 'input_coll_bytes' in req and req['input_coll_bytes']:
0065 ret_reqs[req['request_id']]['input_coll_bytes'] += req['input_coll_bytes']
0066 if 'input_processed_files' in req and req['input_processed_files']:
0067 ret_reqs[req['request_id']]['input_processed_files'] += req['input_processed_files']
0068 if 'input_processing_files' in req and req['input_processing_files']:
0069 ret_reqs[req['request_id']]['input_processing_files'] += req['input_processing_files']
0070
0071 if 'output_total_files' in req and req['output_total_files']:
0072 ret_reqs[req['request_id']]['output_total_files'] += req['output_total_files']
0073 if 'output_coll_bytes' in req and req['output_coll_bytes']:
0074 ret_reqs[req['request_id']]['output_coll_bytes'] += req['output_coll_bytes']
0075 if 'output_processed_files' in req and req['output_processed_files']:
0076 ret_reqs[req['request_id']]['output_processed_files'] += req['output_processed_files']
0077 if 'output_processing_files' in req and req['output_processing_files']:
0078 ret_reqs[req['request_id']]['output_processing_files'] += req['output_processing_files']
0079
0080 for req_id in ret_reqs:
0081 rets.append(ret_reqs[req_id])
0082 return rets
0083 elif with_transform:
0084 rets = []
0085 reqs = get_requests(request_id=request_id, workload_id=workload_id,
0086 with_request=with_request, with_transform=with_transform, with_processing=with_processing,
0087 with_detail=False, with_metadata=False)
0088 for req in reqs:
0089 ret = {'request_id': req['request_id'],
0090 'transform_id': req['transform_id'],
0091 'workload_id': req['workload_id'],
0092 'transform_workload_id': req['transform_workload_id'],
0093 'transform_type': req['transform_type'].name if req['transform_type'] else req['transform_type'],
0094 'output_coll_scope': req['output_coll_scope'] if 'output_coll_scope' in req and req['output_coll_scope'] else 0,
0095 'output_coll_name': req['output_coll_name'] if 'output_coll_name' in req else '',
0096 'transform_status': req['transform_status'].name if req['transform_status'] else req['transform_status'],
0097 'transform_created_at': req['transform_created_at'],
0098 'transform_updated_at': req['transform_updated_at'],
0099 'transform_finished_at': req['transform_finished_at'],
0100 'input_total_files': req['input_total_files'] if 'input_total_files' in req and req['input_total_files'] else 0,
0101 'input_coll_bytes': req['input_coll_bytes'] if 'input_coll_bytes' in req and req['input_coll_bytes'] else 0,
0102 'input_processed_files': req['input_processed_files'] if 'input_processed_files' in req and req['input_processed_files'] else 0,
0103 'input_processing_files': req['input_processing_files'] if 'input_processing_files' in req and req['input_processing_files'] else 0,
0104 'output_total_files': req['output_total_files'] if 'output_total_files' in req and req['output_total_files'] else 0,
0105 'output_coll_bytes': req['output_coll_bytes'] if 'output_coll_bytes' in req and req['output_coll_bytes'] else 0,
0106 'output_processed_files': req['output_processed_files'] if 'output_processed_files' in req and req['output_processed_files'] else 0,
0107 'output_processing_files': req['output_processing_files'] if 'output_processing_files' in req and req['output_processing_files'] else 0,
0108 'errors': req['errors'] if 'errors' in req else ''
0109 }
0110 rets.append(ret)
0111 return rets
0112 elif with_processing:
0113 rets = []
0114 reqs = get_requests(request_id=request_id, workload_id=workload_id,
0115 with_request=with_request, with_transform=with_transform, with_processing=with_processing,
0116 with_detail=False, with_metadata=False)
0117 for req in reqs:
0118 ret = {'request_id': req['request_id'],
0119 'workload_id': req['processing_workload_id'],
0120 'processing_id': req['processing_id'],
0121 'processing_status': req['processing_status'].name if req['processing_status'] else req['processing_status'],
0122 'processing_created_at': req['processing_created_at'],
0123 'processing_updated_at': req['processing_updated_at'],
0124 'processing_finished_at': req['processing_finished_at']
0125 }
0126 rets.append(ret)
0127 return rets
0128 else:
0129 rets = []
0130 reqs = get_requests(request_id=request_id, workload_id=workload_id, with_detail=False, with_processing=False, with_metadata=False)
0131 for req in reqs:
0132 ret = {'request_id': req['request_id'],
0133 'workload_id': req['workload_id'],
0134 'status': req['status'].name if req['status'] else req['status'],
0135 'created_at': req['created_at'],
0136 'updated_at': req['updated_at']
0137 }
0138 rets.append(ret)
0139 return rets
0140
0141 def get(self, request_id, workload_id, with_request='false', with_transform='false', with_processing='false'):
0142 """ Get details about a specific Request with given id.
0143 HTTP Success:
0144 200 OK
0145 HTTP Error:
0146 404 Not Found
0147 500 InternalError
0148 :returns: dictionary of an request.
0149 """
0150
0151 try:
0152 if request_id == 'null':
0153 request_id = None
0154 if workload_id == 'null':
0155 workload_id = None
0156 if with_request and with_request.lower() in ['true']:
0157 with_request = True
0158 else:
0159 with_request = False
0160 if with_transform and with_transform.lower() in ['true']:
0161 with_transform = True
0162 else:
0163 with_transform = False
0164 if with_processing and with_processing.lower() in ['true']:
0165 with_processing = True
0166 else:
0167 with_processing = False
0168
0169 rets = self.get_requests(request_id=request_id, workload_id=workload_id,
0170 with_request=with_request,
0171 with_transform=with_transform,
0172 with_processing=with_processing)
0173 except exceptions.NoObject as error:
0174 return self.generate_http_response(HTTP_STATUS_CODE.NotFound, exc_cls=error.__class__.__name__, exc_msg=error)
0175 except exceptions.IDDSException as error:
0176 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=error.__class__.__name__, exc_msg=error)
0177 except Exception as error:
0178 print(error)
0179 print(format_exc())
0180 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=exceptions.CoreException.__name__, exc_msg=error)
0181
0182 return self.generate_http_response(HTTP_STATUS_CODE.OK, data=rets)
0183
0184 def post_test(self):
0185 import pprint
0186 pprint.pprint(self.get_request())
0187 pprint.pprint(self.get_request().endpoint)
0188 pprint.pprint(self.get_request().url_rule)
0189
0190
0191 class MonitorRequest(Monitor):
0192 """ Monitor Request """
0193
0194 def get(self, request_id, workload_id):
0195 """ Get details about a specific Request with given id.
0196 HTTP Success:
0197 200 OK
0198 HTTP Error:
0199 404 Not Found
0200 500 InternalError
0201 :returns: dictionary of an request.
0202 """
0203
0204 try:
0205 if request_id == 'null':
0206 request_id = None
0207 if workload_id == 'null':
0208 workload_id = None
0209
0210 rets = self.get_requests(request_id=request_id, workload_id=workload_id,
0211 with_request=True, with_transform=False,
0212 with_processing=False)
0213 status_dict = {'Total': {}}
0214 min_time, max_time = None, None
0215 for ret in rets:
0216 if ret['status'] not in status_dict:
0217 status_dict[ret['status']] = {}
0218 if min_time is None or ret['updated_at'] < min_time:
0219 min_time = ret['updated_at']
0220 if max_time is None or ret['updated_at'] > max_time:
0221 max_time = ret['updated_at']
0222
0223 month_list = self.get_month_list(min_time, max_time)
0224 for key in status_dict:
0225 for m in month_list:
0226 status_dict[key][m] = 0
0227
0228 for ret in rets:
0229 m_time = ret['updated_at'].strftime(r"%Y-%m")
0230 status_dict['Total'][m_time] += 1
0231 status_dict[ret['status']][m_time] += 1
0232
0233 status_dict_acc = {}
0234 for key in status_dict:
0235 status_dict_acc[key] = {}
0236 for i in range(len(month_list)):
0237 if i == 0:
0238 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]]
0239 else:
0240 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]] + status_dict_acc[key][month_list[i - 1]]
0241 ret_status = {'total': len(rets), 'month_status': status_dict, 'month_acc_status': status_dict_acc}
0242 except exceptions.NoObject as error:
0243 return self.generate_http_response(HTTP_STATUS_CODE.NotFound, exc_cls=error.__class__.__name__, exc_msg=error)
0244 except exceptions.IDDSException as error:
0245 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=error.__class__.__name__, exc_msg=error)
0246 except Exception as error:
0247 print(error)
0248 print(format_exc())
0249 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=exceptions.CoreException.__name__, exc_msg=error)
0250
0251 return self.generate_http_response(HTTP_STATUS_CODE.OK, data=ret_status)
0252
0253
0254 class MonitorTransform(Monitor):
0255 """ Monitor Transform """
0256
0257 def get(self, request_id, workload_id):
0258 """ Get details about a specific Request with given id.
0259 HTTP Success:
0260 200 OK
0261 HTTP Error:
0262 404 Not Found
0263 500 InternalError
0264 :returns: dictionary of an request.
0265 """
0266
0267 try:
0268 if request_id == 'null':
0269 request_id = None
0270 if workload_id == 'null':
0271 workload_id = None
0272
0273 rets = self.get_requests(request_id=request_id, workload_id=workload_id,
0274 with_request=False, with_transform=True, with_processing=False)
0275 status_dict = {'Total': {}}
0276 status_dict_by_type = {}
0277 processed_files, processed_bytes = {}, {}
0278 processed_files_by_type, processed_bytes_by_type = {}, {}
0279 min_time, max_time = None, None
0280 total_files, total_bytes = 0, 0
0281 for ret in rets:
0282 if ret['transform_status'] and ret['transform_status'] not in status_dict:
0283 status_dict[ret['transform_status']] = {}
0284 if ret['transform_type'] and ret['transform_type'] not in status_dict_by_type:
0285 status_dict_by_type[ret['transform_type']] = {}
0286 processed_files_by_type[ret['transform_type']] = {}
0287 processed_bytes_by_type[ret['transform_type']] = {}
0288 if ret['transform_updated_at'] and (min_time is None or ret['transform_updated_at'] < min_time):
0289 min_time = ret['transform_updated_at']
0290 if ret['transform_updated_at'] and (max_time is None or ret['transform_updated_at'] > max_time):
0291 max_time = ret['transform_updated_at']
0292
0293 month_list = self.get_month_list(min_time, max_time)
0294 for key in status_dict:
0295 processed_files[key] = {}
0296 processed_bytes[key] = {}
0297 for t_type in status_dict_by_type:
0298 status_dict_by_type[t_type][key] = {}
0299 processed_files_by_type[t_type][key] = {}
0300 processed_bytes_by_type[t_type][key] = {}
0301 for m in month_list:
0302 status_dict[key][m] = 0
0303 processed_files[key][m] = 0
0304 processed_bytes[key][m] = 0
0305 for t_type in status_dict_by_type:
0306 status_dict_by_type[t_type][key][m] = 0
0307 processed_files_by_type[t_type][key][m] = 0
0308 processed_bytes_by_type[t_type][key][m] = 0
0309
0310 for ret in rets:
0311 if not ret['transform_updated_at']:
0312 continue
0313 m_time = ret['transform_updated_at'].strftime(r"%Y-%m")
0314 status_dict['Total'][m_time] += 1
0315 status_dict[ret['transform_status']][m_time] += 1
0316 processed_files[ret['transform_status']][m_time] += ret['output_processed_files']
0317
0318
0319 processed_bytes[ret['transform_status']][m_time] += ret['input_coll_bytes']
0320 processed_files['Total'][m_time] += ret['output_processed_files']
0321
0322 processed_bytes['Total'][m_time] += ret['input_coll_bytes']
0323
0324 total_files += ret['output_processed_files']
0325 total_bytes += ret['output_coll_bytes']
0326 total_bytes += ret['input_coll_bytes']
0327
0328 t_type = ret['transform_type']
0329 status_dict_by_type[t_type][ret['transform_status']][m_time] += 1
0330 processed_files_by_type[t_type][ret['transform_status']][m_time] += ret['output_processed_files']
0331
0332 processed_bytes_by_type[t_type][ret['transform_status']][m_time] += ret['input_coll_bytes']
0333 status_dict_by_type[t_type]['Total'][m_time] += 1
0334 processed_files_by_type[t_type]['Total'][m_time] += ret['output_processed_files']
0335
0336 processed_bytes_by_type[t_type]['Total'][m_time] += ret['input_coll_bytes']
0337
0338 status_dict_acc = {}
0339 processed_files_acc, processed_bytes_acc = {}, {}
0340 status_dict_by_type_acc = {}
0341 processed_files_by_type_acc = {}
0342 processed_bytes_by_type_acc = {}
0343 for t_type in status_dict_by_type:
0344 status_dict_by_type_acc[t_type] = {}
0345 processed_files_by_type_acc[t_type] = {}
0346 processed_bytes_by_type_acc[t_type] = {}
0347 for key in status_dict:
0348 status_dict_acc[key] = {}
0349 processed_files_acc[key] = {}
0350 processed_bytes_acc[key] = {}
0351 for t_type in status_dict_by_type:
0352 status_dict_by_type_acc[t_type][key] = {}
0353 processed_files_by_type_acc[t_type][key] = {}
0354 processed_bytes_by_type_acc[t_type][key] = {}
0355
0356 for i in range(len(month_list)):
0357 if i == 0:
0358 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]]
0359 processed_files_acc[key][month_list[i]] = processed_files[key][month_list[i]]
0360 processed_bytes_acc[key][month_list[i]] = processed_bytes[key][month_list[i]]
0361 for t_type in status_dict_by_type_acc:
0362 status_dict_by_type_acc[t_type][key][month_list[i]] = status_dict_by_type[t_type][key][month_list[i]]
0363 processed_files_by_type_acc[t_type][key][month_list[i]] = processed_files_by_type[t_type][key][month_list[i]]
0364 processed_bytes_by_type_acc[t_type][key][month_list[i]] = processed_bytes_by_type[t_type][key][month_list[i]]
0365 else:
0366 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]] + status_dict_acc[key][month_list[i - 1]]
0367 processed_files_acc[key][month_list[i]] = processed_files[key][month_list[i]] + processed_files_acc[key][month_list[i - 1]]
0368 processed_bytes_acc[key][month_list[i]] = processed_bytes[key][month_list[i]] + processed_bytes_acc[key][month_list[i - 1]]
0369 for t_type in status_dict_by_type_acc:
0370 status_dict_by_type_acc[t_type][key][month_list[i]] = status_dict_by_type[t_type][key][month_list[i]] + status_dict_by_type_acc[t_type][key][month_list[i - 1]]
0371 processed_files_by_type_acc[t_type][key][month_list[i]] = processed_files_by_type[t_type][key][month_list[i]] + processed_files_by_type_acc[t_type][key][month_list[i - 1]]
0372 processed_bytes_by_type_acc[t_type][key][month_list[i]] = processed_bytes_by_type[t_type][key][month_list[i]] + processed_bytes_by_type_acc[t_type][key][month_list[i - 1]]
0373 ret_status = {'total': len(rets),
0374 'total_files': total_files,
0375 'total_bytes': total_bytes,
0376 'month_status': status_dict,
0377 'month_acc_status': status_dict_acc,
0378 'month_processed_files': processed_files,
0379 'month_acc_processed_files': processed_files_acc,
0380 'month_processed_bytes': processed_bytes,
0381 'month_acc_processed_bytes': processed_bytes_acc,
0382 'month_status_dict_by_type': status_dict_by_type,
0383 'month_acc_status_dict_by_type': status_dict_by_type_acc,
0384 'month_processed_files_by_type': processed_files_by_type,
0385 'month_acc_processed_files_by_type': processed_files_by_type_acc,
0386 'month_processed_bytes_by_type': processed_bytes_by_type,
0387 'month_acc_processed_bytes_by_type': processed_bytes_by_type_acc
0388 }
0389 except exceptions.NoObject as error:
0390 return self.generate_http_response(HTTP_STATUS_CODE.NotFound, exc_cls=error.__class__.__name__, exc_msg=error)
0391 except exceptions.IDDSException as error:
0392 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=error.__class__.__name__, exc_msg=error)
0393 except Exception as error:
0394 print(error)
0395 print(format_exc())
0396 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=exceptions.CoreException.__name__, exc_msg=error)
0397
0398 return self.generate_http_response(HTTP_STATUS_CODE.OK, data=ret_status)
0399
0400
0401 class MonitorProcessing(Monitor):
0402 """ Monitor Processing """
0403
0404 def get(self, request_id, workload_id):
0405 """ Get details about a specific Request with given id.
0406 HTTP Success:
0407 200 OK
0408 HTTP Error:
0409 404 Not Found
0410 500 InternalError
0411 :returns: dictionary of an request.
0412 """
0413
0414 try:
0415 if request_id == 'null':
0416 request_id = None
0417 if workload_id == 'null':
0418 workload_id = None
0419
0420 rets = self.get_requests(request_id=request_id, workload_id=workload_id,
0421 with_request=False, with_transform=False, with_processing=True)
0422 status_dict = {'Total': {}}
0423 min_time, max_time = None, None
0424 for ret in rets:
0425 if ret['processing_status'] and ret['processing_status'] not in status_dict:
0426 status_dict[ret['processing_status']] = {}
0427 if ret['processing_updated_at'] and (min_time is None or ret['processing_updated_at'] < min_time):
0428 min_time = ret['processing_updated_at']
0429 if ret['processing_updated_at'] and (max_time is None or ret['processing_updated_at'] > max_time):
0430 max_time = ret['processing_updated_at']
0431
0432 month_list = self.get_month_list(min_time, max_time)
0433 for key in status_dict:
0434 for m in month_list:
0435 status_dict[key][m] = 0
0436
0437 for ret in rets:
0438 if ret['processing_updated_at']:
0439 m_time = ret['processing_updated_at'].strftime(r"%Y-%m")
0440 status_dict['Total'][m_time] += 1
0441 status_dict[ret['processing_status']][m_time] += 1
0442
0443 status_dict_acc = {}
0444 for key in status_dict:
0445 status_dict_acc[key] = {}
0446 for i in range(len(month_list)):
0447 if i == 0:
0448 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]]
0449 else:
0450 status_dict_acc[key][month_list[i]] = status_dict[key][month_list[i]] + status_dict_acc[key][month_list[i - 1]]
0451 ret_status = {'total': len(rets), 'month_status': status_dict, 'month_acc_status': status_dict_acc}
0452 except exceptions.NoObject as error:
0453 return self.generate_http_response(HTTP_STATUS_CODE.NotFound, exc_cls=error.__class__.__name__, exc_msg=error)
0454 except exceptions.IDDSException as error:
0455 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=error.__class__.__name__, exc_msg=error)
0456 except Exception as error:
0457 print(error)
0458 print(format_exc())
0459 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=exceptions.CoreException.__name__, exc_msg=error)
0460
0461 return self.generate_http_response(HTTP_STATUS_CODE.OK, data=ret_status)
0462
0463
0464 class MonitorRequestRelation(Monitor):
0465 """ Monitor Request """
0466
0467 def get(self, request_id, workload_id):
0468 """ Get details about a specific Request with given id.
0469 HTTP Success:
0470 200 OK
0471 HTTP Error:
0472 404 Not Found
0473 500 InternalError
0474 :returns: dictionary of an request.
0475 """
0476
0477 try:
0478 if request_id == 'null':
0479 request_id = None
0480 if workload_id == 'null':
0481 workload_id = None
0482
0483 reqs = get_requests(request_id=request_id, workload_id=workload_id,
0484 with_request=True, with_transform=False, with_processing=False,
0485 with_detail=False, with_metadata=True)
0486
0487 for req in reqs:
0488 req['relation_map'] = []
0489 workflow = req['request_metadata']['workflow']
0490 if hasattr(workflow, 'get_relation_map'):
0491 req['relation_map'] = workflow.get_relation_map()
0492
0493 except exceptions.NoObject as error:
0494 return self.generate_http_response(HTTP_STATUS_CODE.NotFound, exc_cls=error.__class__.__name__, exc_msg=error)
0495 except exceptions.IDDSException as error:
0496 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=error.__class__.__name__, exc_msg=error)
0497 except Exception as error:
0498 print(error)
0499 print(format_exc())
0500 return self.generate_http_response(HTTP_STATUS_CODE.InternalError, exc_cls=exceptions.CoreException.__name__, exc_msg=error)
0501
0502 return self.generate_http_response(HTTP_STATUS_CODE.OK, data=reqs)
0503
0504
0505 """----------------------
0506 Web service url maps
0507 ----------------------"""
0508
0509
0510 def get_blueprint():
0511 bp = Blueprint('monitor', __name__)
0512
0513 monitor_view = Monitor.as_view('monitor')
0514 bp.add_url_rule('/monitor/<request_id>/<workload_id>/<with_request>/<with_transform>/<with_processing>', view_func=monitor_view, methods=['get', ])
0515
0516 monitor_request_view = MonitorRequest.as_view('monitor_request')
0517 bp.add_url_rule('/monitor_request/<request_id>/<workload_id>', view_func=monitor_request_view, methods=['get', ])
0518
0519 monitor_transform_view = MonitorTransform.as_view('monitor_transform')
0520 bp.add_url_rule('/monitor_transform/<request_id>/<workload_id>', view_func=monitor_transform_view, methods=['get', ])
0521
0522 monitor_processing_view = MonitorProcessing.as_view('monitor_processing')
0523 bp.add_url_rule('/monitor_processing/<request_id>/<workload_id>', view_func=monitor_processing_view, methods=['get', ])
0524
0525 monitor_relation_view = MonitorRequestRelation.as_view('monitor_request_relation')
0526 bp.add_url_rule('/monitor_request_relation/<request_id>/<workload_id>', view_func=monitor_relation_view, methods=['get', ])
0527
0528 return bp