33
44# Copyright (c) Alibaba, Inc. and its affiliates.
55
6+ import time
67from typing import Union , List , Optional , ClassVar , Dict , Any
78from typing_extensions import Self
89
4344from dashscope .finetune .reinforcement .common .errors import (
4445 RegistrationError ,
4546 ValidationError ,
47+ InstanceQueryError ,
4648 RuntimeErrorWithCode ,
4749 ValueErrorWithCode ,
4850 DatasetsError ,
@@ -426,7 +428,28 @@ async def test_functions(
426428 functype : FunctionType ,
427429 input_data : Dict [str , Any ],
428430 api_key : str = None ,
431+ pull_logs : bool = False ,
432+ log_page_size : int = 100 ,
433+ start_time : Optional [int ] = None ,
434+ end_time : Optional [int ] = None ,
429435 ):
436+ """Test a deployed function instance with custom input data.
437+
438+ Args:
439+ instance_id: Target function instance ID.
440+ functype: Function type (ROLLOUT/REWARD/GROUP_REWARD).
441+ input_data: Test input payload.
442+ api_key: DashScope API key (uses DASHSCOPE_API_KEY env var
443+ if omitted).
444+ pull_logs: If True, pull all logs of the function instance
445+ (with pagination) after verification and print them
446+ between separator markers.
447+ log_page_size: Page size used when pulling logs.
448+ start_time: Optional start time filter (in seconds) for log
449+ pulling. Defaults to 24 hours before ``end_time``.
450+ end_time: Optional end time filter (in seconds) for log
451+ pulling. Defaults to the current time (now).
452+ """
430453 try :
431454 set_api_key (api_key )
432455
@@ -450,13 +473,197 @@ async def test_functions(
450473 },
451474 )
452475
453- return await AgenticRLFunctionComponent .verify_function (
476+ result = await AgenticRLFunctionComponent .verify_function (
454477 value ,
455478 instance_id ,
456479 )
457480
481+ if pull_logs :
482+ await cls ._pull_function_instance_logs (
483+ function_instance_id = instance_id ,
484+ page_size = log_page_size ,
485+ start_time = start_time ,
486+ end_time = end_time ,
487+ )
488+
489+ return result
490+
458491 except Exception as e :
459492 raise ValidationError (
460493 "Function test failed" ,
461494 error_code = 3008 ,
462495 ) from e
496+
497+ @classmethod
498+ async def query_function_instance_logs (
499+ cls ,
500+ function_instance_id : str ,
501+ page_number : int = 1 ,
502+ page_size : int = 100 ,
503+ start_time : Optional [int ] = None ,
504+ end_time : Optional [int ] = None ,
505+ keywords : Optional [List [str ]] = None ,
506+ api_key : str = None ,
507+ ) -> Dict [str , Any ]:
508+ """Query one page of logs for a function (faas) instance.
509+
510+ Args:
511+ function_instance_id: Target function instance ID.
512+ page_number: Page number, starting from 1.
513+ page_size: Number of log entries per page.
514+ start_time: Optional start time filter (in seconds).
515+ end_time: Optional end time filter (in seconds).
516+ keywords: Optional keyword filters for log messages.
517+ api_key: DashScope API key (uses DASHSCOPE_API_KEY env var
518+ if omitted).
519+
520+ Returns:
521+ Raw response dict of the log query API.
522+ """
523+ try :
524+ set_api_key (api_key )
525+
526+ fc_component = AgenticRLFunctionComponent
527+ return await fc_component .query_function_instance_logs (
528+ function_instance_id = function_instance_id ,
529+ page_number = page_number ,
530+ page_size = page_size ,
531+ start_time = start_time ,
532+ end_time = end_time ,
533+ keywords = keywords ,
534+ )
535+
536+ except Exception as e :
537+ if hasattr (e , "error_code" ):
538+ raise
539+ raise InstanceQueryError (
540+ "Function instance log query failed" ,
541+ error_code = 3009 ,
542+ ) from e
543+
544+ @classmethod
545+ async def query_all_function_instance_logs (
546+ cls ,
547+ function_instance_id : str ,
548+ page_size : int = 100 ,
549+ start_time : Optional [int ] = None ,
550+ end_time : Optional [int ] = None ,
551+ keywords : Optional [List [str ]] = None ,
552+ api_key : str = None ,
553+ ) -> List [str ]:
554+ """Fetch all logs of a function (faas) instance.
555+
556+ Pages are fetched one by one via the paginated log query until
557+ all entries are collected.
558+
559+ Args:
560+ function_instance_id: Target function instance ID.
561+ page_size: Number of log entries per page.
562+ start_time: Optional start time filter (in seconds).
563+ end_time: Optional end time filter (in seconds).
564+ keywords: Optional keyword filters for log messages.
565+ api_key: DashScope API key (uses DASHSCOPE_API_KEY env var
566+ if omitted).
567+
568+ Returns:
569+ Aggregated list of log messages across all pages.
570+ """
571+ try :
572+ set_api_key (api_key )
573+
574+ fc_component = AgenticRLFunctionComponent
575+ return await fc_component .query_all_function_instance_logs (
576+ function_instance_id = function_instance_id ,
577+ page_size = page_size ,
578+ start_time = start_time ,
579+ end_time = end_time ,
580+ keywords = keywords ,
581+ )
582+
583+ except Exception as e :
584+ if hasattr (e , "error_code" ):
585+ raise
586+ raise InstanceQueryError (
587+ "Function instance log query failed" ,
588+ error_code = 3010 ,
589+ ) from e
590+
591+ @classmethod
592+ async def delete_function_instance (
593+ cls ,
594+ function_instance_id : str ,
595+ api_key : str = None ,
596+ ) -> Dict [str , Any ]:
597+ """Delete a function (faas) runtime instance.
598+
599+ Args:
600+ function_instance_id: Target function instance ID.
601+ api_key: DashScope API key (uses DASHSCOPE_API_KEY env var
602+ if omitted).
603+
604+ Returns:
605+ Raw response dict of the delete API, containing
606+ ``data.status`` (e.g. "deleted") and
607+ ``data.sandbox_code``.
608+
609+ Raises:
610+ InstanceQueryError: If the deletion fails.
611+ """
612+ try :
613+ set_api_key (api_key )
614+
615+ fc_component = AgenticRLFunctionComponent
616+ return await fc_component .delete_function_instance (
617+ function_instance_id = function_instance_id ,
618+ )
619+
620+ except Exception as e :
621+ if hasattr (e , "error_code" ):
622+ raise
623+ raise InstanceQueryError (
624+ "Function instance deletion failed" ,
625+ error_code = 3011 ,
626+ ) from e
627+
628+ @classmethod
629+ async def _pull_function_instance_logs (
630+ cls ,
631+ function_instance_id : str ,
632+ page_size : int = 100 ,
633+ start_time : Optional [int ] = None ,
634+ end_time : Optional [int ] = None ,
635+ ) -> None :
636+ """Pull all logs of a function instance and print them between
637+ separator markers (best effort, never raises).
638+
639+ When ``start_time``/``end_time`` are not provided, defaults to
640+ pulling logs from 24 hours ago until now.
641+ """
642+ if end_time is None :
643+ end_time = int (time .time ())
644+ if start_time is None :
645+ start_time = end_time - 24 * 60 * 60
646+ logger .info (
647+ "************start query log "
648+ f"(function_instance_id={ function_instance_id } )*******" ,
649+ )
650+ try :
651+ logs = await cls .query_all_function_instance_logs (
652+ function_instance_id = function_instance_id ,
653+ page_size = page_size ,
654+ start_time = start_time ,
655+ end_time = end_time ,
656+ )
657+ for entry in logs :
658+ logger .info (f"[function instance log] { entry } " )
659+ logger .info (
660+ f"Pulled { len (logs )} log entries for function instance "
661+ f"{ function_instance_id } " ,
662+ )
663+ except Exception as e :
664+ logger .warning (
665+ f"Failed to pull logs for function instance "
666+ f"{ function_instance_id } : { e } " ,
667+ )
668+ finally :
669+ logger .info ("************end query log *******" )
0 commit comments