
Este script solo roza la superficie de lo que es posible utilizando Python, Plotly Dash y nuestras API.
Hace casi un año, Tom Mairs, el director de éxito del cliente de Bird, escribió una herramienta de correo utilizando Bird APIs. En este artículo, retomo donde él lo dejó. Su herramienta permite la transmisión programada de trabajos, pero ¿qué pasa si queremos crear nuestros propios paneles de control y registros de eventos?
Tal vez quiera crear un panel de control específico para un grupo empresarial o uno dirigido a clientes, pero sin proporcionar a los usuarios acceso completo a la interfaz de Bird. Este script solo toca la superficie de lo que es posible utilizando Python, Plotly Dash y nuestros APIs. Al construir paneles que procesan datos de API de alto volumen, tenga en cuenta que los componentes de infraestructura como el DNS pueden convertirse en cuellos de botella; hemos experimentado desafíos de escalado de AWS DNS que afectaron nuestras capacidades de procesamiento de datos. Para los entusiastas del flujo de trabajo visual, también pueden explorar integrar Flow Builder con Google Cloud Functions y Vision API para agregar automatización potenciada por IA a sus flujos de procesamiento de datos.
Cuando comencé mi búsqueda en línea, quería encontrar el camino de menor resistencia. Podría haber creado todos los paneles de control y la interfaz de usuario por mí mismo en HTML y Python, sin embargo, después de algunas búsquedas en Google, me encontré con Plotly’s Dash, que se integra fácilmente con Python. Elegí Dash por 2 razones: 1) es de código abierto, y 2) después de leer la documentación, parecía fácilmente personalizable para lo que quería hacer. Dash es una biblioteca de código abierto que es ideal para construir y desplegar aplicaciones de datos con interfaces de usuario personalizadas. Esto hizo que crear una interfaz de usuario fuera extremadamente simple. La pregunta entonces se convirtió en, ¿cuán complejo quería hacer esta aplicación? Cuanto más tiempo dedicaba, más características quería agregar.
Para el proyecto inicial, quería asegurarme de tener un panel de control con métricas personalizables y un marco de tiempo seleccionable. Inicialmente, comencé con un panel de control donde solo podías elegir una métrica del menú desplegable. Luego, a medida que recibía comentarios de colegas, refiné un poco el panel de control para agregar multiselección y títulos de ejes. También decidí agregar una pestaña adicional para un registro de eventos. Llegué al punto en que me satisfacía con lo que tenía como un buen punto de partida para cualquiera que desee desarrollar sus propios paneles de control. Para los desarrolladores que quieren alimentar datos de webhook en tiempo real en sus paneles, echa un vistazo a nuestra guía sobre cómo construir consumidores de webhook con Azure Functions. Por supuesto, puse el proyecto en Github para que puedas clonarlo o crear tu propia rama.
Empezando
Para acceder a esta app, necesitará asegurarse de que está ejecutando python 3.10 o superior e instalar las siguientes bibliotecas:
requests
dash
pandas
Luego, introduzca su clave API en App.py y ejecute la app. Se ejecutará en http://localhost:8050. Para obtener más información sobre cómo implementar esto en un servidor público (como AWS), consulte los siguientes recursos:
Creando la Página del Dashboard
Creando la Event Details Page
La página de detalles del evento era un poco más difícil porque no sabía la mejor manera de presentar todas las métricas de los eventos de una manera fácil de leer. Consideré agregar parámetros de filtrado a esta página, sin embargo, decidí que eso añadiría una cantidad significativa de tiempo a este proyecto, ya que la tabla tendría que ser dinámica (junto con agregar los parámetros, devoluciones de llamada, etc.). Me decidí por mostrar todos los eventos y colocar la marca de tiempo primero (ya que sin poner la marca de tiempo primero, el gráfico no era fácil de leer). Inicialmente, descubrí que con solo el HTML sin procesar, la tabla era increíblemente difícil de leer. No había bordes ni diferencias de color entre el encabezado y las filas. Para hacer que la tabla fuera más fácil de leer, pude usar CSS dentro de Dash.
La idea para los detalles del evento es casi la misma que el panel de control, excepto que esta vez, llamo al Events API y traigo todos los eventos. Note que los detalles del evento solo muestran los 10 eventos más recientes (utilizando el parámetro max_rows y el filtrado de API). Esto puede aumentarse, sin embargo, decidí mostrar los 10 eventos más recientes porque mientras más eventos se muestren, más tiempo toma la llamada de la API. Una mejora significativa que se podría hacer sería la capacidad de paginar e incluir una Página Siguiente / Página Anterior en la interfaz de usuario.
Para construir la pestaña de eventos (página), primero, llamo al Events API y analizo la respuesta JSON en un marco de datos. Luego ordeno y reordeno el marco de datos para poner la marca de tiempo como la primera columna. Finalmente, construyo la tabla HTML iterando a través del marco de datos.
#Construir y llamar a los parámetros del Events API params = { "events" : "delivery,injection,bounce,delay,policy_rejection,out_of_band,open,click,generation_failure,generation_rejection,spam_complaint,list_unsubscribe,link_unsubscribe", "delimiter" : ",", "page" : "1", "per_page" : "10" } api_url = BASE_URL + "/events/message" response_API = requests.get(api_url, headers = {"Authorization" : API_KEY}, params=params) response_info = json.loads(response_API.text) new_df = pd.json_normalize(response_info, record_path=['results']) max_rows=10 #Número máximo de resultados mostrados en la tabla de eventos #Colocar la marca de tiempo como la primera columna en la tabla new_df = new_df.reindex(sorted(new_df.columns), axis=1) cols = ['timestamp'] new_df = new_df[cols + [c for c in new_df.columns if c not in cols]] #Mostrar el nuevo HTML con la tabla de eventos (note, esta tabla también hace referencia a table.css) return html.Div([ html.H2("Event Details"), html.Table([ html.Thead( html.Tr([html.Th(col) for col in new_df.columns],className="table_css") ), html.Tbody([ html.Tr([ html.Td(new_df.iloc[i][col],className="table_css") for col in new_df.columns ]) for i in range(min(len(new_df), max_rows)) ]) ]) ])
Que se ve así en la interfaz de usuario.

Siguientes pasos
Para alguien que busca crear su propio panel o registro de eventos, este es un buen comienzo. Con la personalización aquí, el cielo es el límite.
Como se discutió anteriormente, algunas mejoras futuras que podrían hacerse son:
Agregar analíticas de entregabilidad al panel
Agregar más filtros al panel
Opciones de almacenamiento en caché posibles para que el API no se llame cada vez para mostrar las páginas
Mejoras de UI
Agregar filtrado y paginación a la página de detalles del evento
Me interesaría escuchar cualquier comentario o sugerencias para expandir este proyecto.
~ Zach Samuels, Bird Senior Solutions Engineer