Skip to content

Commit dabdb2a

Browse files
committed
cli: add grep_logs function
1 parent 5eb7870 commit dabdb2a

File tree

2 files changed

+89
-30
lines changed

2 files changed

+89
-30
lines changed

src/warnet/cli/bitcoin.py

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import json
2+
import re
3+
14
import click
25

36
from .util import run_command
@@ -46,23 +49,74 @@ def debug_log(node, network):
4649
# print(rpc_call("tank_messages", {"network": network, "node_a": node_a, "node_b": node_b}))
4750
#
4851
#
49-
# @bitcoin.command()
50-
# @click.argument("pattern", type=str, required=True)
51-
# @click.option("--show-k8s-timestamps", is_flag=True, default=False, show_default=True)
52-
# @click.option("--no-sort", is_flag=True, default=False, show_default=True)
53-
# @click.option("--network", default="warnet", show_default=True)
54-
# def grep_logs(pattern, network, show_k8s_timestamps, no_sort):
55-
# """
56-
# Grep combined logs via fluentd using regex <pattern>
57-
# """
58-
# print(
59-
# rpc_call(
60-
# "logs_grep",
61-
# {
62-
# "network": network,
63-
# "pattern": pattern,
64-
# "k8s_timestamps": show_k8s_timestamps,
65-
# "no_sort": no_sort,
66-
# },
67-
# )
68-
# )
52+
53+
@bitcoin.command()
54+
@click.argument("pattern", type=str, required=True)
55+
@click.option("--show-k8s-timestamps", is_flag=True, default=False, show_default=True)
56+
@click.option("--no-sort", is_flag=True, default=False, show_default=True)
57+
@click.option("--network", default="warnet", show_default=True)
58+
def grep_logs(pattern, network, show_k8s_timestamps, no_sort):
59+
"""
60+
Grep combined logs via fluentd using regex <pattern>
61+
"""
62+
63+
# Get all pods in the namespace
64+
command = f"kubectl get pods -n {network} -o json"
65+
pods_json = run_command(command, return_output=True)
66+
67+
if pods_json is False:
68+
print("Error: Failed to get pods information")
69+
return
70+
71+
try:
72+
pods = json.loads(pods_json)
73+
except json.JSONDecodeError as e:
74+
print(f"Error decoding JSON: {e}")
75+
return
76+
77+
matching_logs = []
78+
79+
for pod in pods.get("items", []):
80+
pod_name = pod.get("metadata", {}).get("name", "")
81+
if "warnet" in pod_name:
82+
# Get container names for this pod
83+
containers = pod.get("spec", {}).get("containers", [])
84+
if not containers:
85+
continue
86+
87+
# Use the first container name
88+
container_name = containers[0].get("name", "")
89+
if not container_name:
90+
continue
91+
92+
# Get logs from the specific container
93+
command = f"kubectl logs {pod_name} -c {container_name} -n {network} --timestamps"
94+
logs = run_command(command, return_output=True)
95+
96+
if logs is not False:
97+
# Process logs
98+
for log_entry in logs.splitlines():
99+
if re.search(pattern, log_entry):
100+
matching_logs.append((log_entry, pod_name))
101+
102+
# Sort logs if needed
103+
if not no_sort:
104+
matching_logs.sort(key=lambda x: x[0])
105+
106+
# Print matching logs
107+
for log_entry, pod_name in matching_logs:
108+
try:
109+
# Split the log entry into Kubernetes timestamp, Bitcoin timestamp, and the rest of the log
110+
k8s_timestamp, rest = log_entry.split(' ', 1)
111+
bitcoin_timestamp, log_message = rest.split(' ', 1)
112+
113+
# Format the output based on the show_k8s_timestamps option
114+
if show_k8s_timestamps:
115+
print(f"{pod_name}: {k8s_timestamp} {bitcoin_timestamp} {log_message}")
116+
else:
117+
print(f"{pod_name}: {bitcoin_timestamp} {log_message}")
118+
except ValueError:
119+
# If we can't parse the timestamps, just print the original log entry
120+
print(f"{pod_name}: {log_entry}")
121+
122+
return matching_logs

src/warnet/cli/util.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
SRC_DIR = files("warnet")
2020

2121

22-
def run_command(command, stream_output=False, env=None):
22+
def run_command(command, stream_output=False, env=None, return_output=False):
2323
# Merge the current environment with the provided env
2424
full_env = os.environ.copy()
2525
if env:
@@ -37,26 +37,31 @@ def run_command(command, stream_output=False, env=None):
3737
universal_newlines=True,
3838
env=full_env,
3939
)
40-
40+
output = []
4141
for line in iter(process.stdout.readline, ""):
4242
print(line, end="")
43-
43+
output.append(line)
4444
process.stdout.close()
4545
return_code = process.wait()
46-
4746
if return_code != 0:
4847
print(f"Command failed with return code {return_code}")
49-
return False
50-
return True
48+
return False if not return_output else "".join(output)
49+
return True if not return_output else "".join(output)
5150
else:
5251
result = subprocess.run(
53-
command, shell=True, capture_output=True, text=True, executable="/bin/bash"
52+
command,
53+
shell=True,
54+
capture_output=True,
55+
text=True,
56+
executable="/bin/bash",
57+
env=full_env,
5458
)
5559
if result.returncode != 0:
5660
print(f"Error: {result.stderr}")
57-
return False
58-
print(result.stdout)
59-
return True
61+
return False if not return_output else result.stderr
62+
if not return_output:
63+
print(result.stdout)
64+
return True if not return_output else result.stdout
6065

6166

6267
def create_cycle_graph(n: int, version: str, bitcoin_conf: str | None, random_version: bool):

0 commit comments

Comments
 (0)