In today’s fast-paced software development environment, ensuring optimal application performance is crucial. Monitoring real-time metrics such as response times, error rates, and resource utilization can help maintain high availability and deliver a seamless user experience. Apache Pinot, an open-source OLAP datastore, offers the ability to handle real-time data ingestion and low-latency querying, making it a suitable solution for monitoring application performance at scale. In this article, we’ll explore how to implement a real-time monitoring system using Apache Pinot, with a focus on setting up Kafka for data streaming, defining Pinot schemas and tables, querying performance data with Python, and visualizing metrics with tools like Grafana.
This article was published as a part of the Data Science Blogathon.
Let’s explore a scenario where we ’re managing a distributed application serving millions of users across multiple regions. To maintain optimal performance, we need to monitor various performance metrics:
Deploy Apache Pinot to create a real-time monitoring system that ingests, stores, and queries performance data, enabling quick detection and response to issues.
The first step is to set up Apache Kafka to handle real-time streaming of our application’s logs and metrics. Kafka is a distributed streaming platform that allows us to publish and subscribe to streams of records in real-time. Each microservice in our application can produce log messages or metrics to Kafka topics, which Pinot will later consume
To run Kafka, we will be installing Java on our system-
sudo apt install openjdk-11-jre-headless -y
java –version
wget https://downloads.apache.org/kafka/3.4.0/kafka_2.13-3.4.0.tgz
sudo mkdir /usr/local/kafka-server
sudo tar xzf kafka_2.13-3.4.0.tgz
Also we need to move the extracted files to the folder given below-
sudo mv kafka_2.13-3.4.0/* /usr/local/kafka-server
sudo systemctl daemon-reload
Assuming Kafka and Zookeeper are already installed, Kafka can be started using below commands:
# Start Zookeeper
zookeeper-server-start.sh config/zookeeper.properties
# Start Kafka server
kafka-server-start.sh config/server.properties
Next, creation of a Kafka topic for our application metrics. Topics are the channels through which data flows in Kafka. Here, we’ve created a topic named app-metrics with 3 partitions and a replication factor of 1. The number of partitions distributes the data across Kafka brokers, while the replication factor controls the level of redundancy by determining how many copies of the data exist.
kafka-topics.sh --create --topic app-metrics --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
Our application can publish metrics to the Kafka topic in real-time. This script simulates sending application metrics to the Kafka topic every second. The metrics include details such as service name, endpoint, status code, response time, CPU usage, memory usage, and timestamp.
from confluent_kafka import Producer
import json
import time
# Kafka producer configuration
conf = {'bootstrap.servers': "localhost:9092"}
producer = Producer(**conf)
# Function to send a message to Kafka
def send_metrics():
metrics = {
"service_name": "auth-service",
"endpoint": "/login",
"status_code": 200,
"response_time_ms": 123.45,
"cpu_usage": 55.2,
"memory_usage": 1024.7,
"timestamp": int(time.time() * 1000)
}
producer.produce('app-metrics', value=json.dumps(metrics))
producer.flush()
# Simulate sending metrics every 2 seconds
while True:
send_metrics()
time.sleep(2)
With Kafka set up and streaming data, the next step is to configure Apache Pinot to ingest and store this data. This involves defining a schema and creating a table in Pinot.
The schema defines the structure of the data that Pinot will ingest. It specifies the dimensions (attributes) and metrics (measurable quantities) that will be stored, as well as the data types for each field. Create a JSON file named “app_performance_ms_schema.json” with the following content:
{
"schemaName": "app_performance_ms",
"dimensionFieldSpecs": [
{"name": "service", "dataType": "STRING"},
{"name": "endpoint", "dataType": "STRING"},
{"name": "s_code", "dataType": "INT"}
],
"metricFieldSpecs": [
{"name": "response_time", "dataType": "DOUBLE"},
{"name": "cpu_usage", "dataType": "DOUBLE"},
{"name": "memory_usage", "dataType": "DOUBLE"}
],
"dateTimeFieldSpecs": [
{
"name": "timestamp",
"dataType": "LONG",
"format": "1:MILLISECONDS:EPOCH",
"granularity": "1:MILLISECONDS"
}
]
}
The table configuration file tells Pinot how to manage the data, including details on data ingestion from Kafka, indexing strategies, and retention policies.
Create another JSON file named “app_performance_metrics_table.json” with the following content:
{
"tableName": "appPerformanceMetrics",
"tableType": "REALTIME",
"segmentsConfig": {
"timeColumnName": "timestamp",
"schemaName": "appMetrics",
"replication": "1"
},
"tableIndexConfig": {
"loadMode": "MMAP",
"streamConfigs": {
"streamType": "kafka",
"stream.kafka.topic.name": "app_performance_metrics",
"stream.kafka.broker.list": "localhost:9092",
"stream.kafka.consumer.type": "lowlevel"
}
}
}
This configuration specifies that the table will ingest data from the app_performance_metrics Kafka topic in real-time. It uses the timestamp column as the primary time column and configures indexing to support efficient queries.
Once the schema and table configuration are ready, we can deploy them to Pinot using the following commands:
bin/pinot-admin.sh AddSchema -schemaFile app_performance_ms_schema.json -exec
bin/pinot-admin.sh AddTable -tableConfigFile app_performance_metrics_table.json -schemaFile app_performance_ms_schema.json -exec
After deployment, Apache Pinot will start ingesting data from the Kafka topic app-metrics and making it available for querying.
As Pinot ingests data, you can now start querying it to monitor key performance indicators (KPIs). Pinot supports SQL-like queries, allowing us to retrieve and analyze data quickly. Here’s a Python script that queries the average response time and error rate for each service over the past five minutes:
import requests
import json
# Pinot broker URL
pinot_broker_url = "http://localhost:8099/query/sql"
# SQL query to get average response time and error rate
query = """
SELECT service_name,
AVG(response_time_ms) AS avg_response_time,
SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) / COUNT(*) AS error_rate
FROM appPerformanceMetrics
WHERE timestamp >= ago('PT5M')
GROUP BY service_name
"""
# Execute the query
response = requests.post(pinot_broker_url, data=query, headers={"Content-Type": "application/json"})
if response.status_code == 200:
result = response.json()
print(json.dumps(result, indent=4))
else:
print("Query failed with status code:", response.status_code)
This script sends a SQL query to Pinot to calculate the average response time and error rate for each service in the last five minutes. These metrics are crucial for understanding the real-time performance of our application.
Grafana is a popular open-source visualization tool that supports integration with Apache Pinot. By connecting Grafana to Pinot, we can create real-time dashboards that display metrics like response times, error rates, and resource usage. Example dashboard can include the following information-
This visualization setup provides a comprehensive view of our application’s health and performance, enabling us to monitor KPIs continuously and take proactive measures when issues arise.
As our real-time monitoring system with Apache Pinot expands, there are several advanced aspects to manage for maintaining its effectiveness:
Effective real-time monitoring is essential for ensuring the performance and reliability of modern applications. Apache Pinot offers a powerful solution for real-time data processing and querying, making it well-suited for comprehensive monitoring systems. By implementing the strategies discussed and considering advanced topics like scaling and security, you can build a robust and scalable monitoring system that helps you stay ahead of potential performance issues, ensuring a smooth experience for your users.
A. Apache Pinot is optimized for low-latency querying, making it ideal for scenarios where real-time insights are crucial. Its ability to ingest data from streaming sources like Kafka and handle large-scale, high-throughput data sets allows it to provide up-to-the-minute analytics on application performance metrics.
A. Apache Pinot is designed to ingest real-time data by directly consuming messages from Kafka topics. It supports both low-level and high-level Kafka consumers, allowing Pinot to process and store data with minimal delay, making it available for immediate querying.
A. To set up a real-time monitoring system with Apache Pinot, you need:
Data Sources: Application logs and metrics streamed to Kafka.
Apache Pinot: For real-time data ingestion and querying.
Schema and Table Configuration: Definitions in Pinot for storing and indexing the metrics data.
Visualization Tools: Tools like Grafana or Apache Superset for creating real-time dashboards
A. Yes, Apache Pinot supports integration with other data streaming platforms like Apache Pulsar and AWS Kinesis. While this article focuses on Kafka, the same principles apply when using different streaming platforms, though configuration details will vary.
The media shown in this article is not owned by Analytics Vidhya and is used at the Author’s discretion.