Mira dentro de tu código C++: por qué la observabilidad no es un lujo, sino una necesidad
\n\nImagina: has lanzado un servicio de alta carga en C++. Pasa una hora, dos, un día, todo funciona. Y luego, ¡pum! Los usuarios se quejan de lentitud, y tú estás adivinando: ¿dónde está el cuello de botella? ¿En la memoria? ¿En la red? ¿O simplemente alguien olvidó liberar un recurso? Sin un sistema de observabilidad, eres como el capitán de un barco con las ventanillas tapadas. Sientes que algo va mal, pero no ves qué.
\n\nObservabilidad en C++ es tu conjunto de periscopios y radares. No es solo registro, son tres pilares: trazado, métricas y logs. En este artículo, analizaremos cada uno con ejemplos de código reales, mostraremos cómo integrar C++ con OpenTelemetry y Prometheus, y daremos recetas listas para producción. ¡Vamos allá!
\n\nLos tres pilares de la observabilidad: trazado, métricas, logs
\n\nAntes de sumergirnos en el código, definamos claramente en qué se diferencian estos conceptos y cómo se complementan. Muchos confunden observabilidad con simple registro, y es un error. Es como comparar una linterna con un reflector.
\n\n- \n
- Logs son eventos. "¿Qué ocurrió?" (por ejemplo, "Usuario autenticado" o "Error de conexión con la BD"). Son detallados, pero sin contexto pueden ser inútiles. \n
- Métricas son números. "¿Cuánto?" (cantidad de solicitudes por segundo, uso de CPU, tiempo de respuesta). Son agregadas y muestran tendencias. \n
- Trazado es el camino de una solicitud. "¿Cómo exactamente ocurrió?" (desde la entrada al servicio hasta la llamada a la base de datos y la respuesta al cliente). Es el vínculo entre logs y métricas. \n
La observabilidad ideal en C++ es cuando, al mirar un panel, puedes entender en 10 segundos: dónde, cuándo y por qué ocurrió una anomalía. Sin esto, estarás jugando a adivinar con producción.
\n\nTrazado en C++: cómo implementar OpenTelemetry
\n\nEmpecemos con la herramienta más potente, pero también la más compleja: el trazado. OpenTelemetry es el estándar de facto para la recopilación de telemetría. En C++, no tiene un soporte tan rico como en Go o Java, pero funciona de manera estable.
\n\nSupongamos que tenemos un servidor HTTP simple en C++ (usamos la idea, no una biblioteca específica). Necesitamos rastrear cuánto tarda en procesarse cada solicitud y qué llamadas ocurren dentro de ella.
\n\nConfiguración de OpenTelemetry en C++
\n\nPrimero, instalamos las dependencias. En CMakeLists.txt agregamos:
\n\nfind_package(opentelemetry-cpp REQUIRED)\ntarget_link_libraries(my_app PRIVATE opentelemetry::api opentelemetry::exporter_ostream)\n\nAhora creamos un trazador y spans (span es una unidad de trabajo). Aquí hay un ejemplo mínimo:
\n\n#include <opentelemetry/trace/provider.h>\n#include <opentelemetry/exporters/ostream/span_exporter.h>\n#include <opentelemetry/sdk/trace/tracer_provider.h>\n#include <opentelemetry/sdk/trace/simple_processor.h>\n\nnamespace trace_api = opentelemetry::trace;\nnamespace trace_sdk = opentelemetry::sdk::trace;\nnamespace trace_exporter = opentelemetry::exporter::trace;\n\nvoid init_tracer() {\n auto exporter = std::unique_ptr<trace_sdk::SpanExporter>(\n new trace_exporter::OStreamSpanExporter(std::cout));\n auto processor = std::unique_ptr<trace_sdk::SpanProcessor>(\n new trace_sdk::SimpleSpanProcessor(std::move(exporter)));\n auto provider = std::make_shared<trace_sdk::TracerProvider>(std::move(processor));\n trace_api::Provider::SetTracerProvider(provider);\n}\n\nvoid process_request(const std::string& user_id) {\n auto tracer = trace_api::Provider::GetTracerProvider()->GetTracer("my_service");\n auto span = tracer->StartSpan("process_request");\n span->SetAttribute("user.id", user_id);\n\n // Simulación de trabajo\n std::this_thread::sleep_for(std::chrono::milliseconds(100));\n\n span->End();\n}\n\nint main