Quick start¶
Flare needs two JARs on every machine that runs a Spark JVM, driver and executors:
- the OpenTelemetry Java agent,
opentelemetry-javaagent.jar, unmodified, from the OpenTelemetry project; - the Flare JAR for your Spark and Scala version, see Choosing a JAR.
Both must be at the same path on every machine, and they must be there before the JVM
starts, because the agent loads at JVM start-up (premain). That rules out anything Spark fetches
after start-up, such as --jars or --packages. How to get them there is the platform-specific
part; Deploying has a recipe for each platform.
Download¶
AGENT=https://repo1.maven.org/maven2/io/opentelemetry/javaagent/opentelemetry-javaagent/2.31.1/opentelemetry-javaagent-2.31.1.jar
FLARE=https://repo1.maven.org/maven2/io/github/neutrinic/flare-spark-3-5_2.12/1.4.0/flare-spark-3-5_2.12-1.4.0.jar
mkdir -p /opt/flare
curl -fsSL -o /opt/flare/opentelemetry-javaagent.jar "$AGENT"
curl -fsSL -o /opt/flare/flare-spark.jar "$FLARE"
Replace 3-5_2.12 with the coordinate for your cluster. Downloading the JARs covers
Windows, Maven, checksums and clusters without internet access.
Submit¶
spark-submit \
--conf "spark.plugins=io.flare.spark.plugin.FlareSparkPlugin" \
--conf "spark.driver.extraClassPath=/opt/flare/flare-spark.jar" \
--conf "spark.executor.extraClassPath=/opt/flare/flare-spark.jar" \
--conf "spark.driver.extraJavaOptions=\
-javaagent:/opt/flare/opentelemetry-javaagent.jar \
-Dotel.javaagent.extensions=/opt/flare/flare-spark.jar \
-Dotel.service.name=my-app-driver \
-Dotel.exporter.otlp.endpoint=http://your-collector:4317 \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.compression=gzip" \
--conf "spark.executor.extraJavaOptions=\
-javaagent:/opt/flare/opentelemetry-javaagent.jar \
-Dotel.javaagent.extensions=/opt/flare/flare-spark.jar \
-Dotel.service.name=my-app-executor \
-Dotel.exporter.otlp.endpoint=http://your-collector:4317 \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.compression=gzip" \
my-app.jar
Each setting has a job:
| Setting | What it does |
|---|---|
-javaagent:…opentelemetry-javaagent.jar |
Starts the OpenTelemetry agent in the JVM |
-Dotel.javaagent.extensions=…flare-spark.jar |
Loads Flare into the agent. On the driver this is what gives every stage its own trace context |
spark.plugins=io.flare.spark.plugin.FlareSparkPlugin |
Loads Flare into Spark: the listener that creates driver spans, and the executor plugin that creates task spans |
spark.{driver,executor}.extraClassPath |
Puts the Flare JAR where spark.plugins can find it |
-Dotel.service.name |
How the driver and executors are named in your backend |
-Dotel.exporter.otlp.* |
Where the telemetry goes. See Exporting |
Some platforms already put a directory on Spark's classpath, such as /databricks/jars on
Databricks or /usr/lib/spark/jars in an EMR Serverless image. Copying the Flare JAR there
replaces the two extraClassPath settings. The platform pages say where.
Use TLS across untrusted networks
http:// sends telemetry unencrypted, which is fine for a collector on the same node or a
private network. Telemetry includes SQL plans, failure messages and, with log export, your logs,
so use an https:// endpoint for a collector reached over anything you do not control.
Compression
otel.exporter.otlp.compression defaults to none. Spark telemetry is unusually repetitive:
every export repeats the resource block, which on Spark carries the whole command line and
classpath. On the local stack, gzip cut the bytes sent by 56% with identical traces.
Check it worked¶
In your backend, search for the service my-app-driver. There should be one trace whose root span
is spark.application, with SQL, job and stage spans under it.
These settings leave FLARE_TRACE_GRANULARITY at its default, stages, which stops there. To see
every task as a spark.task.executor span from my-app-executor under its stage, add
-DFLARE_TRACE_GRANULARITY=all to both extraJavaOptions. Task spans are most of Flare's own
volume; see Telemetry volume.
If the trace is missing or looks wrong, see Troubleshooting.
If the extension can only be attached on the driver¶
The extension matters most on the driver, where the scheduler runs: that is what gives every stage
its own trace context. If you cannot pass -Dotel.javaagent.extensions to the executors, attach it
on the driver only and drop it from the executor extraJavaOptions. Task spans still parent to
their stage.
Everything else is unchanged on the executors: the agent (-javaagent), the Flare JAR on the
classpath and spark.plugins, because the executor plugin is what creates task spans at all.
What you lose on the executors: the flare.role resource attribute, and in-task context
restoration, so calls made inside a task (JDBC, HTTP) are not linked into the trace.