This episode covers Spark observability: collecting metrics and logs, reading the Spark web UI and History Server, integrating Prometheus and Grafana for dashboards, and setting up alerting for failed jobs and data skew.

Spark jobs can run for hours. Without good observability, failures are only detected when it's already too late — data doesn't arrive, quality drops, or the cluster sits idle unnoticed. Episode 13 covers observability: the ability to see what's happening inside the cluster in real time and comprehensively.
Observability is more than reading logs. It includes measurable metrics, readable dashboards, and alerts that arrive before a problem becomes serious. Engineers who master observability can answer the question "why is this job slow?" in minutes, not hours.
This episode covers four pillars: metrics, logs, and the Spark web UI; Prometheus and Grafana integration; the History Server with event logs; and alerting for failed jobs and skew.
The Spark UI on port 4040 is the first window into observability. Its pages show real-time status:
open http://localhost:4040From the Executors page, you can see if one executor is using far more memory than the others — an early indication of data skew. This is the first triage step before looking at other metrics.
Logs live in two places: driver logs appear in the terminal where spark-submit was run (client mode), and executor logs are scattered across worker nodes. In cluster mode, direct logs to a central location so they're easy to search:
spark.eventLog.enabled true
spark.eventLog.dir file:/var/log/spark/events
spark.history.fs.logDirectory file:/var/log/spark/eventsspark.eventLog.enabled writes event logs to the directory — this is the fuel for the History Server and also a data source for log aggregation.
Spark provides a Prometheus-format metrics endpoint through the sparkPrometheus module. Enable it in metrics.properties:
*.sink.prometheusServlet.class org.apache.spark.metrics.sink.PrometheusServlet
*.sink.prometheusServlet.path /metrics/prometheus
*.sink.prometheusServlet.period 10Once enabled, metrics are available at http://driver:4040/metrics/prometheus. For cluster mode applications whose driver moves, use spark.metrics.executorMetricsSource.enabled=true and let Prometheus do service discovery on YARN or Kubernetes.
Point Prometheus to scrape the driver and executors every few seconds:
scrape_configs:
- job_name: spark
static_configs:
- targets: ["driver-host:4040", "worker-1:4040", "worker-2:4040"]
labels:
cluster: produksiWith Prometheus data, build Grafana dashboards showing key metrics: shuffle read bytes, task completion time, memory used per executor, and active jobs. These dashboards become the data team's daily monitoring board.
The event logs enabled earlier can be re-read by the History Server, so the UI of finished applications can still be inspected:
/opt/spark/sbin/start-history-server.sh --properties-file /opt/spark/conf/spark-defaults.confOnce running, access http://localhost:18080 to see the list of applications along with their full UI. This is very useful for evaluating job performance after completion or investigating overnight failures.
Event log data can also be reprocessed for historical analysis: the average duration per job, which stages are most often slow, and how resources were used this week. The combination of Prometheus for real-time and the History Server for historical data gives a complete picture.
The goal of observability is early detection. Create alert rules in Prometheus and send notifications through Alertmanager to Slack, email, or PagerDuty:
groups:
- name: spark
rules:
- alert: SparkJobFailed
expr: spark_app_status == 0
for: 5m
labels:
severity: critical
- alert: StageDurationHigh
expr: spark_stage_duration > 1800
labels:
severity: warningspark_app_status == 0 triggers an alert when an application stops with a failed status. Rules like this ensure the team knows before users report it.
Skew rarely triggers failures, but it always steals time. Create alerts that watch for imbalance:
shuffle read per task that is wildly uneven.count(*) below the expected bound.Info
Too many alerts is as bad as no alerts. Start with the five most impactful rules — failed jobs, spike in stage duration, resources near the limit, detected skew, and declining data quality — then improve iteratively based on the team's needs.
Episode 13 equips you with observability skills: the Spark web UI and logs for quick diagnosis, Prometheus and Grafana for real-time metrics, the History Server with event logs for historical inspection, and alerting for early detection of failures and skew.
Key takeaways:
In the next episode, episode 14, we'll discuss resource management and deployment — deployment on standalone, YARN, Mesos, and Kubernetes, the Spark on Kubernetes pattern, managing executors, cores, and memory, plus dynamic allocation and workload isolation.