def describe_log_streams( self, descending, limit, log_group_name, log_stream_name_prefix, next_token, order_by, ): if log_group_name not in self.groups: raise ResourceNotFoundException() if limit > 50: raise InvalidParameterException( constraint="Member must have value less than or equal to 50", parameter="limit", value=limit, ) if order_by not in ["LogStreamName", "LastEventTime"]: raise InvalidParameterException( constraint= "Member must satisfy enum value set: [LogStreamName, LastEventTime]", parameter="orderBy", value=order_by, ) if order_by == "LastEventTime" and log_stream_name_prefix: raise InvalidParameterException( msg="Cannot order by LastEventTime with a logStreamNamePrefix." ) log_group = self.groups[log_group_name] return log_group.describe_log_streams( descending=descending, limit=limit, log_group_name=log_group_name, log_stream_name_prefix=log_stream_name_prefix, next_token=next_token, order_by=order_by, )
def describe_log_groups(self, limit, log_group_name_prefix, next_token): if limit > 50: raise InvalidParameterException( constraint="Member must have value less than or equal to 50", parameter="limit", value=limit, ) if log_group_name_prefix is None: log_group_name_prefix = "" groups = [ group.to_describe_dict() for name, group in self.groups.items() if name.startswith(log_group_name_prefix) ] groups = sorted(groups, key=lambda x: x["logGroupName"]) index_start = 0 if next_token: try: index_start = ( next( index for (index, d) in enumerate(groups) if d["logGroupName"] == next_token ) + 1 ) except StopIteration: index_start = 0 # AWS returns an empty list if it receives an invalid token. groups = [] index_end = index_start + limit if index_end > len(groups): index_end = len(groups) groups_page = groups[index_start:index_end] next_token = None if groups_page and index_end < len(groups): next_token = groups_page[-1]["logGroupName"] return groups_page, next_token
def get_log_events( self, log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head, ): if log_group_name not in self.groups: raise ResourceNotFoundException() if limit and limit > 1000: raise InvalidParameterException( constraint="Member must have value less than or equal to 10000", parameter="limit", value=limit, ) log_group = self.groups[log_group_name] return log_group.get_log_events(log_stream_name, start_time, end_time, limit, next_token, start_from_head)
def put_subscription_filter(self, log_group_name, filter_name, filter_pattern, destination_arn, role_arn): # TODO: support other destinations like Kinesis stream from moto.awslambda import lambda_backends # due to circular dependency log_group = self.groups.get(log_group_name) if not log_group: raise ResourceNotFoundException() lambda_func = lambda_backends[self.region_name].get_function( destination_arn) # no specific permission check implemented if not lambda_func: raise InvalidParameterException( "Could not execute the lambda function. " "Make sure you have given CloudWatch Logs permission to execute your function." ) log_group.put_subscription_filter(filter_name, filter_pattern, destination_arn, role_arn)
def get_log_events( self, log_group_name, log_stream_name, start_time, end_time, limit, next_token, start_from_head, ): if limit is None: limit = 10000 def filter_func(event): if start_time and event.timestamp < start_time: return False if end_time and event.timestamp > end_time: return False return True def get_index_and_direction_from_token(token): if token is not None: try: return token[0], int(token[2:]) except Exception: raise InvalidParameterException( "The specified nextToken is invalid.") return None, 0 events = sorted(filter(filter_func, self.events), key=lambda event: event.timestamp) direction, index = get_index_and_direction_from_token(next_token) limit_index = limit - 1 final_index = len(events) - 1 if direction is None: if start_from_head: start_index = 0 end_index = start_index + limit_index else: end_index = final_index start_index = end_index - limit_index elif direction == "f": start_index = index + 1 end_index = start_index + limit_index elif direction == "b": end_index = index - 1 start_index = end_index - limit_index else: raise InvalidParameterException( "The specified nextToken is invalid.") if start_index < 0: start_index = 0 elif start_index > final_index: return ( [], "b/{:056d}".format(final_index), "f/{:056d}".format(final_index), ) if end_index > final_index: end_index = final_index elif end_index < 0: return ([], "b/{:056d}".format(0), "f/{:056d}".format(0)) events_page = [ event.to_response_dict() for event in events[start_index:end_index + 1] ] return ( events_page, "b/{:056d}".format(start_index), "f/{:056d}".format(end_index), )