|
| 1 | +import json |
| 2 | +import re |
| 3 | + |
1 | 4 | import click |
2 | 5 |
|
3 | 6 | from .util import run_command |
@@ -46,23 +49,74 @@ def debug_log(node, network): |
46 | 49 | # print(rpc_call("tank_messages", {"network": network, "node_a": node_a, "node_b": node_b})) |
47 | 50 | # |
48 | 51 | # |
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 |
0 commit comments