Skip to content

Commit f6148cc

Browse files
committed
[system] Next batch of docstrings
1 parent aacb086 commit f6148cc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+6707
-858
lines changed

sebs/aws/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
"""AWS module for the Serverless Benchmarking Suite (SeBS).
2+
3+
This module provides the AWS implementation of the SeBS framework, enabling
4+
deployment and management of serverless functions on AWS Lambda. It includes
5+
comprehensive support for AWS services including Lambda, S3, DynamoDB, ECR,
6+
and API Gateway.
7+
8+
Key components:
9+
AWS: Main AWS system implementation
10+
LambdaFunction: AWS Lambda function representation
11+
AWSConfig: AWS-specific configuration management
12+
S3: S3 storage implementation
13+
14+
The module handles AWS-specific functionality including:
15+
- Lambda function deployment and management
16+
- Container deployments via ECR
17+
- S3 storage for code packages and data
18+
- DynamoDB NoSQL storage
19+
- API Gateway HTTP triggers
20+
- IAM role management
21+
- CloudWatch metrics collection
22+
"""
23+
124
from .aws import AWS, LambdaFunction # noqa
225
from .config import AWSConfig # noqa
326
from .s3 import S3 # noqa

sebs/aws/aws.py

Lines changed: 162 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,15 @@ def create_function(
402402

403403
return lambda_function
404404

405-
def cached_function(self, function: Function):
405+
def cached_function(self, function: Function) -> None:
406+
"""Set up triggers for a cached function.
407+
408+
Configures triggers for a function that was loaded from cache,
409+
ensuring they have proper logging handlers and deployment client references.
410+
411+
Args:
412+
function: Function instance to configure triggers for
413+
"""
406414

407415
from sebs.aws.triggers import LibraryTrigger
408416

@@ -477,7 +485,21 @@ def update_function(
477485

478486
def update_function_configuration(
479487
self, function: Function, code_package: Benchmark, env_variables: dict = {}
480-
):
488+
) -> None:
489+
"""Update Lambda function configuration.
490+
491+
Updates the function's timeout, memory, and environment variables.
492+
Automatically adds environment variables for NoSQL storage table names
493+
if the benchmark uses NoSQL storage.
494+
495+
Args:
496+
function: Function to update
497+
code_package: Benchmark code package with configuration
498+
env_variables: Additional environment variables to set
499+
500+
Raises:
501+
AssertionError: If code package input has not been processed
502+
"""
481503

482504
# We can only update storage configuration once it has been processed for this benchmark
483505
assert code_package.has_input_processed
@@ -523,6 +545,19 @@ def update_function_configuration(
523545
def default_function_name(
524546
self, code_package: Benchmark, resources: Optional[Resources] = None
525547
) -> str:
548+
"""Generate default function name for a benchmark.
549+
550+
Creates a standardized function name based on resource ID, benchmark name,
551+
language, version, and architecture. Ensures the name is compatible with
552+
AWS Lambda naming requirements.
553+
554+
Args:
555+
code_package: Benchmark code package
556+
resources: Optional resources object (uses default if not provided)
557+
558+
Returns:
559+
str: Formatted function name suitable for AWS Lambda
560+
"""
526561
# Create function name
527562
resource_id = resources.resources_id if resources else self.config.resources.resources_id
528563
func_name = "sebs-{}-{}-{}-{}-{}".format(
@@ -538,47 +573,59 @@ def default_function_name(
538573

539574
@staticmethod
540575
def format_function_name(func_name: str) -> str:
576+
"""Format function name for AWS Lambda compatibility.
577+
578+
AWS Lambda has specific naming requirements. This method ensures
579+
the function name complies with AWS Lambda naming rules.
580+
581+
Args:
582+
func_name: Raw function name
583+
584+
Returns:
585+
str: Formatted function name with illegal characters replaced
586+
"""
541587
# AWS Lambda does not allow hyphens in function names
542588
func_name = func_name.replace("-", "_")
543589
func_name = func_name.replace(".", "_")
544590
return func_name
545591

546-
"""
547-
FIXME: does not clean the cache
548-
"""
549-
550-
def delete_function(self, func_name: Optional[str]):
592+
def delete_function(self, func_name: Optional[str]) -> None:
593+
"""Delete an AWS Lambda function.
594+
595+
Args:
596+
func_name: Name of the function to delete
597+
598+
Note:
599+
FIXME: does not clean the cache
600+
"""
551601
self.logging.debug("Deleting function {}".format(func_name))
552602
try:
553603
self.client.delete_function(FunctionName=func_name)
554604
except Exception:
555605
self.logging.debug("Function {} does not exist!".format(func_name))
556606

557-
"""
558-
Prepare AWS resources to store experiment results.
559-
Allocate one bucket.
560-
561-
:param benchmark: benchmark name
562-
:return: name of bucket to store experiment results
563-
"""
564-
565-
# def prepare_experiment(self, benchmark: str):
566-
# logs_bucket = self.get_storage().add_output_bucket(benchmark, suffix="logs")
567-
# return logs_bucket
568-
569-
"""
570-
Accepts AWS report after function invocation.
571-
Returns a dictionary filled with values with various metrics such as
572-
time, invocation time and memory consumed.
573-
574-
:param log: decoded log from CloudWatch or from synchronuous invocation
575-
:return: dictionary with parsed values
576-
"""
577-
578607
@staticmethod
579608
def parse_aws_report(
580609
log: str, requests: Union[ExecutionResult, Dict[str, ExecutionResult]]
581610
) -> str:
611+
"""Parse AWS Lambda execution report from CloudWatch logs.
612+
613+
Extracts execution metrics from AWS Lambda log entries and updates
614+
the corresponding ExecutionResult objects with timing, memory, and
615+
billing information.
616+
617+
Args:
618+
log: Raw log string from CloudWatch or synchronous invocation
619+
requests: Either a single ExecutionResult or dictionary mapping
620+
request IDs to ExecutionResult objects
621+
622+
Returns:
623+
str: Request ID of the parsed execution
624+
625+
Example:
626+
The log format expected is tab-separated AWS Lambda report format:
627+
"REPORT RequestId: abc123\tDuration: 100.00 ms\tBilled Duration: 100 ms\t..."
628+
"""
582629
aws_vals = {}
583630
for line in log.split("\t"):
584631
if not line.isspace():
@@ -605,9 +652,23 @@ def parse_aws_report(
605652
return request_id
606653

607654
def shutdown(self) -> None:
655+
"""Shutdown the AWS system and clean up resources.
656+
657+
Calls the parent shutdown method to perform standard cleanup.
658+
"""
608659
super().shutdown()
609660

610-
def get_invocation_error(self, function_name: str, start_time: int, end_time: int):
661+
def get_invocation_error(self, function_name: str, start_time: int, end_time: int) -> None:
662+
"""Retrieve and log invocation errors from CloudWatch Logs.
663+
664+
Queries CloudWatch Logs for error messages during the specified time range
665+
and logs them for debugging purposes.
666+
667+
Args:
668+
function_name: Name of the Lambda function
669+
start_time: Start time for log query (Unix timestamp)
670+
end_time: End time for log query (Unix timestamp)
671+
"""
611672
if not self.logs_client:
612673
self.logs_client = boto3.client(
613674
service_name="logs",
@@ -650,7 +711,19 @@ def download_metrics(
650711
end_time: int,
651712
requests: Dict[str, ExecutionResult],
652713
metrics: dict,
653-
):
714+
) -> None:
715+
"""Download execution metrics from CloudWatch Logs.
716+
717+
Queries CloudWatch Logs for Lambda execution reports and parses them
718+
to extract performance metrics for each request.
719+
720+
Args:
721+
function_name: Name of the Lambda function
722+
start_time: Start time for metrics collection (Unix timestamp)
723+
end_time: End time for metrics collection (Unix timestamp)
724+
requests: Dictionary mapping request IDs to ExecutionResult objects
725+
metrics: Dictionary to store collected metrics
726+
"""
654727

655728
if not self.logs_client:
656729
self.logs_client = boto3.client(
@@ -694,6 +767,21 @@ def download_metrics(
694767
)
695768

696769
def create_trigger(self, func: Function, trigger_type: Trigger.TriggerType) -> Trigger:
770+
"""Create a trigger for the specified function.
771+
772+
Creates and configures a trigger based on the specified type. Currently
773+
supports HTTP triggers (via API Gateway) and library triggers.
774+
775+
Args:
776+
func: Function to create trigger for
777+
trigger_type: Type of trigger to create (HTTP or LIBRARY)
778+
779+
Returns:
780+
Trigger: The created trigger instance
781+
782+
Raises:
783+
RuntimeError: If trigger type is not supported
784+
"""
697785
from sebs.aws.triggers import HTTPTrigger
698786

699787
function = cast(LambdaFunction, func)
@@ -728,13 +816,31 @@ def create_trigger(self, func: Function, trigger_type: Trigger.TriggerType) -> T
728816
self.cache_client.update_function(function)
729817
return trigger
730818

731-
def _enforce_cold_start(self, function: Function, code_package: Benchmark):
819+
def _enforce_cold_start(self, function: Function, code_package: Benchmark) -> None:
820+
"""Enforce cold start for a single function.
821+
822+
Updates the function's environment variables to force a cold start
823+
on the next invocation.
824+
825+
Args:
826+
function: Function to enforce cold start for
827+
code_package: Benchmark code package with configuration
828+
"""
732829
func = cast(LambdaFunction, function)
733830
self.update_function_configuration(
734831
func, code_package, {"ForceColdStart": str(self.cold_start_counter)}
735832
)
736833

737-
def enforce_cold_start(self, functions: List[Function], code_package: Benchmark):
834+
def enforce_cold_start(self, functions: List[Function], code_package: Benchmark) -> None:
835+
"""Enforce cold start for multiple functions.
836+
837+
Updates all specified functions to force cold starts on their next invocations.
838+
This is useful for ensuring consistent performance measurements.
839+
840+
Args:
841+
functions: List of functions to enforce cold start for
842+
code_package: Benchmark code package with configuration
843+
"""
738844
self.cold_start_counter += 1
739845
for func in functions:
740846
self._enforce_cold_start(func, code_package)
@@ -744,19 +850,40 @@ def enforce_cold_start(self, functions: List[Function], code_package: Benchmark)
744850
self.wait_function_updated(lambda_function)
745851
self.logging.info("Finished function updates enforcing cold starts.")
746852

747-
def wait_function_active(self, func: LambdaFunction):
853+
def wait_function_active(self, func: LambdaFunction) -> None:
854+
"""Wait for Lambda function to become active after creation.
855+
856+
Uses AWS Lambda waiter to wait until the function is in Active state
857+
and ready to be invoked.
858+
859+
Args:
860+
func: Lambda function to wait for
861+
"""
748862

749863
self.logging.info("Waiting for Lambda function to be created...")
750864
waiter = self.client.get_waiter("function_active_v2")
751865
waiter.wait(FunctionName=func.name)
752866
self.logging.info("Lambda function has been created.")
753867

754-
def wait_function_updated(self, func: LambdaFunction):
868+
def wait_function_updated(self, func: LambdaFunction) -> None:
869+
"""Wait for Lambda function to complete update process.
870+
871+
Uses AWS Lambda waiter to wait until the function update is complete
872+
and the function is ready to be invoked with new configuration.
873+
874+
Args:
875+
func: Lambda function to wait for
876+
"""
755877

756878
self.logging.info("Waiting for Lambda function to be updated...")
757879
waiter = self.client.get_waiter("function_updated_v2")
758880
waiter.wait(FunctionName=func.name)
759881
self.logging.info("Lambda function has been updated.")
760882

761-
def disable_rich_output(self):
883+
def disable_rich_output(self) -> None:
884+
"""Disable rich output formatting for ECR operations.
885+
886+
Disables colored/formatted output in the ECR container client,
887+
useful for CI/CD environments or when plain text output is preferred.
888+
"""
762889
self.ecr_client.disable_rich_output = True

0 commit comments

Comments
 (0)