Skip to content

Commit 1ed1b3d

Browse files
committed
feat: send GCP logs as a formatted JSON document via Telegram
1 parent 5e1533d commit 1ed1b3d

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

bot_logic.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -571,36 +571,50 @@ async def get_logs(update: Update, context: ContextTypes.DEFAULT_TYPE):
571571

572572
try:
573573
from google.cloud import logging as gcp_logging
574-
import html
574+
import json
575+
import io
575576

576577
await update.message.reply_text("Buscando errores en Google Cloud Logging...")
577578
client = gcp_logging.Client()
578579

579580
# Query logs for the cloud_run_revision with severity>=ERROR
580581
filter_str = 'resource.type="cloud_run_revision" AND severity>=ERROR AND resource.labels.service_name="dcubabot"'
581-
entries = client.list_entries(filter_=filter_str, order_by=gcp_logging.DESCENDING, max_results=10)
582+
entries = client.list_entries(filter_=filter_str, order_by=gcp_logging.DESCENDING, max_results=50)
582583

583584
log_msgs = []
584585
for entry in entries:
585-
# GCP logs can have payload in text_payload or json_payload
586+
# Prepare a structured dictionary for each log entry
587+
log_data = {
588+
"timestamp": entry.timestamp.isoformat(),
589+
"severity": entry.severity,
590+
}
591+
586592
payload = entry.payload
587593
if isinstance(payload, dict):
588-
import json
589-
payload = json.dumps(payload)
590-
elif payload is None:
591-
payload = str(entry.resource)
594+
log_data["json_payload"] = payload
595+
elif payload is not None:
596+
log_data["text_payload"] = str(payload)
597+
else:
598+
log_data["resource"] = str(entry.resource)
592599

593-
log_msgs.append(f"[{entry.timestamp.strftime('%Y-%m-%d %H:%M:%S')}] {payload}")
600+
log_msgs.append(log_data)
594601

595602
if not log_msgs:
596603
await update.message.reply_text("✅ No se encontraron errores recientes en GCP.")
597604
return
598605

599-
msg = "\n\n".join(log_msgs)
600-
# Split message if it's too long for Telegram (4096 chars limit)
601-
for i in range(0, len(msg), 3800):
602-
chunk = msg[i:i+3800]
603-
await update.message.reply_text(f"Últimos errores:\n<pre>{html.escape(chunk)}</pre>", parse_mode=ParseMode.HTML)
606+
# Convert list of dicts to a formatted JSON string
607+
logs_json_str = json.dumps(log_msgs, indent=2, ensure_ascii=False)
608+
609+
# Create an in-memory file
610+
file_obj = io.BytesIO(logs_json_str.encode('utf-8'))
611+
file_obj.name = f"gcp_error_logs_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
612+
613+
await context.bot.send_document(
614+
chat_id=update.effective_chat.id,
615+
document=file_obj,
616+
caption="Acá tenés el archivo con los últimos errores registrados en GCP 🕵️‍♂️"
617+
)
604618
except Exception as e:
605619
await update.message.reply_text(f"Error al leer logs (¿falta permiso roles/logging.viewer en la Service Account?): {e}")
606620

0 commit comments

Comments
 (0)