Skip to content

Commit bdfa9e5

Browse files
authored
Python: Add log group argument to CloudWatchQuery. Addresses #7022 (#7066)
1 parent 62fbeae commit bdfa9e5

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

python/example_code/cloudwatch-logs/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ python -m pip install -r requirements.txt
3838

3939
Code excerpts that show you how to call individual service functions.
4040

41-
- [GetQueryResults](scenarios/large-query/cloudwatch_query.py#L200)
42-
- [StartQuery](scenarios/large-query/cloudwatch_query.py#L126)
41+
- [GetQueryResults](scenarios/large-query/cloudwatch_query.py#L204)
42+
- [StartQuery](scenarios/large-query/cloudwatch_query.py#L130)
4343

4444
### Scenarios
4545

@@ -106,4 +106,4 @@ in the `python` folder.
106106

107107
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
108108

109-
SPDX-License-Identifier: Apache-2.0
109+
SPDX-License-Identifier: Apache-2.0

python/example_code/cloudwatch-logs/scenarios/large-query/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Use the following steps to create the necessary resources in AWS CloudFormation
3333
1. Run `aws cloudformation deploy --template-file stack.yaml --stack-name CloudWatchLargeQuery`
3434
1. Run `./make-log-files.sh`. This will output two timestamps for use in the following step.
3535
1. Run `export QUERY_START_DATE=<QUERY_START_DATE>`. Replace `<QUERY_START_DATE>` with the output from the previous step. Repeat this for `QUERY_END_DATE`.
36+
1. Optional: Run `export QUERY_LOG_GROUP=<QUERY_LOG_GROUP>`. Replace `<QUERY_LOG_GROUP>` with your preferred log group.
3637
1. Run `./put-log-events.sh`.
3738
1. Wait five minutes for logs to settle and to make sure you're not querying for logs that exist in the future.
3839

python/example_code/cloudwatch-logs/scenarios/large-query/cloudwatch_query.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
from date_utilities import DateUtilities
1010

11+
DEFAULT_QUERY = "fields @timestamp, @message | sort @timestamp asc"
12+
DEFAULT_LOG_GROUP = "/workflows/cloudwatch-logs/large-query"
1113

1214
class DateOutOfBoundsError(Exception):
1315
"""Exception raised when the date range for a query is out of bounds."""
@@ -19,17 +21,18 @@ class CloudWatchQuery:
1921
"""
2022
A class to query AWS CloudWatch logs within a specified date range.
2123
22-
:ivar date_range: Start and end datetime for the query.
2324
:vartype date_range: tuple
2425
:ivar limit: Maximum number of log entries to return.
2526
:vartype limit: int
27+
:log_group str: Name of the log group to query
28+
:query_string str: query
2629
"""
2730

28-
def __init__(self, date_range):
31+
def __init__(self, log_group: str = DEFAULT_LOG_GROUP, query_string: str=DEFAULT_QUERY) -> None:
2932
self.lock = threading.Lock()
30-
self.log_groups = "/workflows/cloudwatch-logs/large-query"
33+
self.log_group = log_group
34+
self.query_string = query_string
3135
self.query_results = []
32-
self.date_range = date_range
3336
self.query_duration = None
3437
self.datetime_format = "%Y-%m-%d %H:%M:%S.%f"
3538
self.date_utilities = DateUtilities()
@@ -50,8 +53,9 @@ def query_logs(self, date_range):
5053

5154
logging.info(
5255
f"Original query:"
53-
f"\n START: {start_date}"
54-
f"\n END: {end_date}"
56+
f"\n START: {start_date}"
57+
f"\n END: {end_date}"
58+
f"\n LOG GROUP: {self.log_group}"
5559
)
5660
self.recursive_query((start_date, end_date))
5761
end_time = datetime.now()
@@ -143,10 +147,10 @@ def perform_query(self, date_range):
143147
self.date_utilities.convert_iso8601_to_unix_timestamp(date_range[1])
144148
)
145149
response = client.start_query(
146-
logGroupName=self.log_groups,
150+
logGroupName=self.log_group,
147151
startTime=start_time,
148152
endTime=end_time,
149-
queryString="fields @timestamp, @message | sort @timestamp asc",
153+
queryString=self.query_string,
150154
limit=self.limit,
151155
)
152156
query_id = response["queryId"]
@@ -185,10 +189,10 @@ def _initiate_query(self, client, date_range, max_logs):
185189
self.date_utilities.convert_iso8601_to_unix_timestamp(date_range[1])
186190
)
187191
response = client.start_query(
188-
logGroupName=self.log_groups,
192+
logGroupName=self.log_group,
189193
startTime=start_time,
190194
endTime=end_time,
191-
queryString="fields @timestamp, @message | sort @timestamp asc",
195+
queryString=self.query_string,
192196
limit=max_logs,
193197
)
194198
return response["queryId"]

python/example_code/cloudwatch-logs/scenarios/large-query/exec.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s",
1717
)
1818

19+
DEFAULT_QUERY_LOG_GROUP = "/workflows/cloudwatch-logs/large-query"
20+
1921

2022
class CloudWatchLogsQueryRunner:
2123
def __init__(self):
@@ -42,8 +44,10 @@ def create_cloudwatch_logs_client(self):
4244
def fetch_environment_variables(self):
4345
"""
4446
Fetches and validates required environment variables for query start and end dates.
47+
Fetches the environment variable for log group, returning the default value if it
48+
does not exist.
4549
46-
:return: Tuple of query start date and end date as integers.
50+
:return: Tuple of query start date and end date as integers and the log group.
4751
:rtype: tuple
4852
:raises SystemExit: If required environment variables are missing or invalid.
4953
"""
@@ -58,8 +62,14 @@ def fetch_environment_variables(self):
5862
except ValueError as e:
5963
logging.error(f"Error parsing date environment variables: {e}")
6064
sys.exit(1)
65+
66+
try:
67+
log_group = os.environ["QUERY_LOG_GROUP"]
68+
except KeyError:
69+
logging.warning("No QUERY_LOG_GROUP environment variable, using default value")
70+
log_group = DEFAULT_QUERY_LOG_GROUP
6171

62-
return query_start_date, query_end_date
72+
return query_start_date, query_end_date, log_group
6373

6474
def convert_dates_to_iso8601(self, start_date, end_date):
6575
"""
@@ -85,6 +95,7 @@ def execute_query(
8595
start_date_iso8601,
8696
end_date_iso8601,
8797
log_group="/workflows/cloudwatch-logs/large-query",
98+
query="fields @timestamp, @message | sort @timestamp asc"
8899
):
89100
"""
90101
Creates a CloudWatchQuery instance and executes the query with provided date range.
@@ -95,9 +106,12 @@ def execute_query(
95106
:type end_date_iso8601: str
96107
:param log_group: Log group to search: "/workflows/cloudwatch-logs/large-query"
97108
:type log_group: str
109+
:param query: Query string to pass to the CloudWatchQuery instance
110+
:type query: str
98111
"""
99112
cloudwatch_query = CloudWatchQuery(
100-
[start_date_iso8601, end_date_iso8601],
113+
log_group=log_group,
114+
query_string=query
101115
)
102116
cloudwatch_query.query_logs((start_date_iso8601, end_date_iso8601))
103117
logging.info("Query executed successfully.")
@@ -113,12 +127,12 @@ def main():
113127
"""
114128
logging.info("Starting a recursive CloudWatch logs query...")
115129
runner = CloudWatchLogsQueryRunner()
116-
query_start_date, query_end_date = runner.fetch_environment_variables()
130+
query_start_date, query_end_date, log_group = runner.fetch_environment_variables()
117131
start_date_iso8601 = DateUtilities.convert_unix_timestamp_to_iso8601(
118132
query_start_date
119133
)
120134
end_date_iso8601 = DateUtilities.convert_unix_timestamp_to_iso8601(query_end_date)
121-
runner.execute_query(start_date_iso8601, end_date_iso8601)
135+
runner.execute_query(start_date_iso8601, end_date_iso8601, log_group=log_group)
122136

123137

124138
if __name__ == "__main__":

0 commit comments

Comments
 (0)