diff --git a/src/warnet/backend/kubernetes_backend.py b/src/warnet/backend/kubernetes_backend.py index 4143e4f83..f8821888d 100644 --- a/src/warnet/backend/kubernetes_backend.py +++ b/src/warnet/backend/kubernetes_backend.py @@ -313,34 +313,33 @@ def get_messages( messages.sort(key=lambda x: x["time"]) return messages - def logs_grep(self, pattern: str, network: str): + def logs_grep(self, pattern: str, network: str, k8s_timestamps=False, no_sort=False): compiled_pattern = re.compile(pattern) matching_logs = [] - pods = self.client.list_namespaced_pod(self.namespace) - - # TODO: Can adapt to only search lnd or bitcoind containers? relevant_pods = [pod for pod in pods.items if "warnet" in pod.metadata.name] - # Iterate through the filtered pods to fetch and search logs for pod in relevant_pods: try: log_stream = self.client.read_namespaced_pod_log( name=pod.metadata.name, container=BITCOIN_CONTAINER_NAME, namespace=self.namespace, - timestamps=True, + timestamps=k8s_timestamps, _preload_content=False, ) - for log_entry in log_stream: log_entry_str = log_entry.decode("utf-8").strip() if compiled_pattern.search(log_entry_str): - matching_logs.append(log_entry_str) + matching_logs.append((log_entry_str, pod.metadata.name)) except ApiException as e: print(f"Error fetching logs for pod {pod.metadata.name}: {e}") - return "\n".join(matching_logs) + sorted_logs = matching_logs if no_sort else sorted(matching_logs, key=lambda x: x[0]) + # Prepend pod names + formatted_logs = [f"{pod_name}: {log}" for log, pod_name in sorted_logs] + + return "\n".join(formatted_logs) def generate_deployment_file(self, warnet): """ diff --git a/src/warnet/cli/bitcoin.py b/src/warnet/cli/bitcoin.py index 8dea2a3a4..0c01f7d0d 100644 --- a/src/warnet/cli/bitcoin.py +++ b/src/warnet/cli/bitcoin.py @@ -47,9 +47,21 @@ def messages(node_a, node_b, network): @bitcoin.command() @click.argument("pattern", type=str, required=True) +@click.option("--show-k8s-timestamps", is_flag=True, default=False, show_default=True) +@click.option("--no-sort", is_flag=True, default=False, show_default=True) @click.option("--network", default="warnet", show_default=True) -def grep_logs(pattern, network): +def grep_logs(pattern, network, show_k8s_timestamps, no_sort): """ Grep combined logs via fluentd using regex """ - print(rpc_call("logs_grep", {"network": network, "pattern": pattern})) + print( + rpc_call( + "logs_grep", + { + "network": network, + "pattern": pattern, + "k8s_timestamps": show_k8s_timestamps, + "no_sort": no_sort, + }, + ) + ) diff --git a/src/warnet/server.py b/src/warnet/server.py index 13066482c..b3fbda6dd 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -570,13 +570,15 @@ def generate_deployment(self, graph_file: str, network: str = "warnet") -> str: self.logger.error(msg) raise ServerError(message=msg) from e - def logs_grep(self, pattern: str, network: str = "warnet") -> str: + def logs_grep( + self, pattern: str, network: str = "warnet", k8s_timestamps=False, no_sort=False + ) -> str: """ Grep the logs from the fluentd container for a regex pattern """ try: wn = self.get_warnet(network) - return wn.container_interface.logs_grep(pattern, network) + return wn.container_interface.logs_grep(pattern, network, k8s_timestamps, no_sort) except Exception as e: msg = f"Error grepping logs using pattern {pattern}: {e}" self.logger.error(msg)