Skip to content

Commit 4a263e1

Browse files
Change table behaviour in snow logs (#2190)
* Change table behaviour in snow logs * Update src/snowflake/cli/_plugins/logs/commands.py Co-authored-by: Jakub Wilkowski <[email protected]> --------- Co-authored-by: Jakub Wilkowski <[email protected]>
1 parent f6c408b commit 4a263e1

File tree

5 files changed

+85
-57
lines changed

5 files changed

+85
-57
lines changed

src/snowflake/cli/_plugins/logs/commands.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ def get_logs(
3636
"--refresh",
3737
help="If set, the logs will be streamed with the given refresh time in seconds",
3838
),
39+
event_table: Optional[str] = typer.Option(
40+
None,
41+
"--table",
42+
help="The table to query for logs. If not provided, the default table will be used",
43+
),
3944
**options,
4045
):
4146
"""
@@ -55,6 +60,7 @@ def get_logs(
5560
object_name=object_name,
5661
from_time=from_time,
5762
refresh_time=refresh_time,
63+
event_table=event_table,
5864
)
5965
logs = itertools.chain(
6066
(MessageResult(log.log_message) for logs in logs_stream for log in logs)
@@ -65,6 +71,7 @@ def get_logs(
6571
object_name=object_name,
6672
from_time=from_time,
6773
to_time=to_time,
74+
event_table=event_table,
6875
)
6976
logs = (MessageResult(log.log_message) for log in logs_iterable) # type: ignore
7077

src/snowflake/cli/_plugins/logs/manager.py

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import functools
21
import time
32
from datetime import datetime
43
from textwrap import dedent
@@ -10,18 +9,6 @@
109
from snowflake.cli.api.sql_execution import SqlExecutionMixin
1110
from snowflake.connector.cursor import SnowflakeCursor
1211

13-
LogsTableQueryResult = NamedTuple(
14-
"LogsTableQueryResult",
15-
[
16-
("key", str),
17-
("table_name", str),
18-
("default", str),
19-
("level", str),
20-
("description", str),
21-
("type", str),
22-
],
23-
)
24-
2512
LogsQueryRow = NamedTuple(
2613
"LogsQueryRow",
2714
[
@@ -42,13 +29,18 @@ def stream_logs(
4229
object_type: str = ObjectArgument,
4330
object_name: FQN = NameArgument,
4431
from_time: Optional[datetime] = None,
32+
event_table: Optional[str] = None,
4533
) -> Iterable[List[LogsQueryRow]]:
4634
try:
4735
previous_end = from_time
4836

4937
while True:
5038
raw_logs = self.get_raw_logs(
51-
object_type, object_name, previous_end, None
39+
object_type=object_type,
40+
object_name=object_name,
41+
from_time=previous_end,
42+
to_time=None,
43+
event_table=event_table,
5244
).fetchall()
5345

5446
if raw_logs:
@@ -67,12 +59,19 @@ def get_logs(
6759
object_name: FQN = NameArgument,
6860
from_time: Optional[datetime] = None,
6961
to_time: Optional[datetime] = None,
62+
event_table: Optional[str] = None,
7063
) -> Iterable[LogsQueryRow]:
7164
"""
7265
Basic function to get a single batch of logs from the server
7366
"""
7467

75-
logs = self.get_raw_logs(object_type, object_name, from_time, to_time)
68+
logs = self.get_raw_logs(
69+
object_type=object_type,
70+
object_name=object_name,
71+
from_time=from_time,
72+
to_time=to_time,
73+
event_table=event_table,
74+
)
7675

7776
return self.sanitize_logs(logs)
7877

@@ -82,7 +81,11 @@ def get_raw_logs(
8281
object_name: FQN = NameArgument,
8382
from_time: Optional[datetime] = None,
8483
to_time: Optional[datetime] = None,
84+
event_table: Optional[str] = None,
8585
) -> SnowflakeCursor:
86+
87+
table = event_table if event_table else "SNOWFLAKE.TELEMETRY.EVENTS"
88+
8689
query = dedent(
8790
f"""
8891
SELECT
@@ -92,7 +95,7 @@ def get_raw_logs(
9295
resource_attributes:"snow.{object_type}.name"::string as object_name,
9396
record:severity_text::string as log_level,
9497
value::string as log_message
95-
FROM {self.logs_table}
98+
FROM {table}
9699
WHERE record_type = 'LOG'
97100
AND (record:severity_text = 'INFO' or record:severity_text is NULL )
98101
AND object_name = '{object_name}'
@@ -105,22 +108,6 @@ def get_raw_logs(
105108

106109
return result
107110

108-
@functools.cached_property
109-
def logs_table(self) -> str:
110-
"""
111-
Get the table where logs are."""
112-
query_result = self.execute_query(
113-
f"SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;"
114-
).fetchone()
115-
116-
try:
117-
logs_table_query_result = LogsTableQueryResult(*query_result)
118-
except TypeError:
119-
raise ClickException(
120-
"Encountered error while querying for logs table. Please check if your account has an event_table"
121-
)
122-
return logs_table_query_result.table_name
123-
124111
def _get_timestamp_query(
125112
self, from_time: Optional[datetime], to_time: Optional[datetime]
126113
):

tests/__snapshots__/test_help_messages.ambr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5127,6 +5127,9 @@
51275127
| --refresh INTEGER If set, the logs will be streamed with the given |
51285128
| refresh time in seconds |
51295129
| [default: None] |
5130+
| --table TEXT The table to query for logs. If not provided, |
5131+
| the default table will be used |
5132+
| [default: None] |
51305133
| --help -h Show this message and exit. |
51315134
+------------------------------------------------------------------------------+
51325135
+- Connection configuration ---------------------------------------------------+

tests/logs/__snapshots__/test_logs.ambr

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# serializer version: 1
2-
# name: test_correct_query_is_constructed
2+
# name: test_correct_query_is_constructed[None]
3+
'''
4+
SELECT
5+
timestamp,
6+
resource_attributes:"snow.database.name"::string as database_name,
7+
resource_attributes:"snow.schema.name"::string as schema_name,
8+
resource_attributes:"snow.compute_pool.name"::string as object_name,
9+
record:severity_text::string as log_level,
10+
value::string as log_message
11+
FROM SNOWFLAKE.TELEMETRY.EVENTS
12+
WHERE record_type = 'LOG'
13+
AND (record:severity_text = 'INFO' or record:severity_text is NULL )
14+
AND object_name = 'bar'
15+
AND timestamp >= TO_TIMESTAMP_LTZ('2022-02-02T02:02:02')
16+
AND timestamp <= TO_TIMESTAMP_LTZ('2022-02-03T02:02:02')
17+
18+
ORDER BY timestamp;
19+
'''
20+
# ---
21+
# name: test_correct_query_is_constructed[bar]
22+
'''
23+
SELECT
24+
timestamp,
25+
resource_attributes:"snow.database.name"::string as database_name,
26+
resource_attributes:"snow.schema.name"::string as schema_name,
27+
resource_attributes:"snow.compute_pool.name"::string as object_name,
28+
record:severity_text::string as log_level,
29+
value::string as log_message
30+
FROM bar
31+
WHERE record_type = 'LOG'
32+
AND (record:severity_text = 'INFO' or record:severity_text is NULL )
33+
AND object_name = 'bar'
34+
AND timestamp >= TO_TIMESTAMP_LTZ('2022-02-02T02:02:02')
35+
AND timestamp <= TO_TIMESTAMP_LTZ('2022-02-03T02:02:02')
36+
37+
ORDER BY timestamp;
38+
'''
39+
# ---
40+
# name: test_correct_query_is_constructed[foo]
341
'''
442
SELECT
543
timestamp,

tests/logs/test_logs.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from unittest import mock
2-
31
import pytest
42

53

@@ -20,9 +18,7 @@ def test_providing_to_time_and_refresh_causes_error(runner):
2018
assert "You cannot set both --refresh and --to parameters" in result.output
2119

2220

23-
@mock.patch("snowflake.cli._plugins.logs.manager.LogsManager.logs_table")
24-
def test_providing_to_time_earlier_than_from_time_causes_error(mock_table, runner):
25-
mock_table.return_value = "test_table"
21+
def test_providing_to_time_earlier_than_from_time_causes_error(runner):
2622

2723
result = runner.invoke(
2824
[
@@ -58,28 +54,25 @@ def test_providing_time_in_incorrect_format_causes_error(
5854
assert result.output == snapshot
5955

6056

61-
@mock.patch(
62-
"snowflake.cli._plugins.logs.manager.LogsManager.logs_table",
63-
new_callable=mock.PropertyMock,
64-
)
65-
def test_correct_query_is_constructed(
66-
mock_table, mock_connect, mock_ctx, runner, snapshot
67-
):
68-
mock_table.return_value = "foo"
57+
@pytest.mark.parametrize("table", ["foo", "bar", None])
58+
def test_correct_query_is_constructed(mock_connect, mock_ctx, runner, snapshot, table):
6959
ctx = mock_ctx()
7060
mock_connect.return_value = ctx
7161

72-
_ = runner.invoke(
73-
[
74-
"logs",
75-
"compute_pool",
76-
"bar",
77-
"--from",
78-
"2022-02-02 02:02:02",
79-
"--to",
80-
"2022-02-03 02:02:02",
81-
]
82-
)
62+
args = [
63+
"logs",
64+
"compute_pool",
65+
"bar",
66+
"--from",
67+
"2022-02-02 02:02:02",
68+
"--to",
69+
"2022-02-03 02:02:02",
70+
]
71+
72+
if table:
73+
args.extend(["--table", table])
74+
75+
_ = runner.invoke(args)
8376

8477
queries = ctx.get_queries()
8578
assert len(queries) == 1

0 commit comments

Comments
 (0)