33from __future__ import annotations
44
55from collections .abc import Generator
6+ from contextlib import suppress
67from os import environ
78from typing import TYPE_CHECKING , Any
89
1516 from mypy_boto3_ecs .type_defs import ContainerDefinitionOutputTypeDef , TaskDefinitionTypeDef
1617 from mypy_boto3_logs .client import CloudWatchLogsClient
1718 from mypy_boto3_logs .type_defs import (
19+ FilteredLogEventTypeDef ,
1820 LiveTailSessionLogEventTypeDef ,
1921 OutputLogEventTypeDef ,
2022 StartLiveTailResponseStreamTypeDef ,
@@ -106,6 +108,20 @@ def get_container_logs(self, log_group: str, log_stream: str, lines: int = 50) -
106108 )
107109 return response .get ("events" , [])
108110
111+ def get_container_logs_filtered (
112+ self , log_group : str , log_stream : str , filter_pattern : str , lines : int = 50
113+ ) -> list [FilteredLogEventTypeDef ]:
114+ """Get container logs with CloudWatch filter pattern applied."""
115+ if not self .logs_client :
116+ return []
117+ response = self .logs_client .filter_log_events (
118+ logGroupName = log_group ,
119+ logStreamNames = [log_stream ],
120+ filterPattern = filter_pattern ,
121+ limit = lines ,
122+ )
123+ return response .get ("events" , [])
124+
109125 def get_live_container_logs_tail (
110126 self , log_group : str , log_stream : str , event_filter_pattern : str = ""
111127 ) -> Generator [StartLiveTailResponseStreamTypeDef | LiveTailSessionLogEventTypeDef ]:
@@ -127,14 +143,20 @@ def get_live_container_logs_tail(
127143 logEventFilterPattern = event_filter_pattern ,
128144 )
129145 response_stream = response .get ("responseStream" )
130- for event in response_stream :
131- if "sessionStart" in event :
132- continue
133- elif "sessionUpdate" in event :
134- log_events = event .get ("sessionUpdate" , {}).get ("sessionResults" , [])
135- yield from log_events
136- else :
137- yield event
146+ try :
147+ for event in response_stream :
148+ if "sessionStart" in event :
149+ continue
150+ elif "sessionUpdate" in event :
151+ log_events = event .get ("sessionUpdate" , {}).get ("sessionResults" , [])
152+ yield from log_events
153+ else :
154+ yield event
155+ finally :
156+ # Properly close the response stream
157+ if hasattr (response_stream , "close" ):
158+ with suppress (Exception ):
159+ response_stream .close ()
138160
139161 def list_log_groups (self , cluster_name : str , container_name : str ) -> list [str ]:
140162 if not self .logs_client :
0 commit comments