Scala
| Traces | Metrics | App Logs | Custom Logs | Profiling |
|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ |
1. Prerequisites
- Middleware Host Agent running on the same machine (or reachable). In containers, point apps to the agent with MW_AGENT_SERVICE: Docker 172.17.0.1, Kubernetes mw-service.mw-agent-ns.svc.cluster.local.
- Scala/SBT project (Scala 2.11.6+ is fine) and JDK 8+. Check using:
1scala --version 2java --version
1 Download the Middleware Java agent JAR
Grab the latest release of the Middleware Java agent JAR from GitHub and place it in your project (e.g., project root or a lib/ directory).
Keep the filename versioned (e.g., middleware-javaagent-1.x.y.jar) and commit it or fetch it during CI.
2 Wire the agent in build.sbt
Enable a forked JVM and pass -javaagent + service name via javaOptions. (Forking is required for SBT to apply javaOptions to your app’s run.)
1// build.sbt
2ThisBuild / scalaVersion := "2.13.14"
3
4// ensure SBT forks for run so javaOptions apply
5(run / fork) := true
6
7(run / javaOptions) ++= Seq(
8 // point to where you stored the agent jar
9 "-javaagent:middleware-javaagent-1.6.0.jar",
10 // logical service name shown in Middleware APM
11 "-Dotel.service.name={APM-SERVICE-NAME}"
12)(Your existing Scala page uses the same javaOptions structure; we’re just adding the fork so it takes effect.) Alternative: if you prefer, you can manage javaagents via the community sbt-javaagent plugin instead of manual javaOptions.
3 Run your app with your account key
Your Middleware API key is required; export it and run the app via SBT:
1MW_API_KEY="<API-key>" sbt runIf you’re not running a Host Agent, point the agent straight to Middleware’s ingest and keep the rest identical:
1// build.sbt (add one more property)
2(run / javaOptions) ++= Seq(
3 "-Dotel.exporter.otlp.endpoint=https://ruplp.middleware.io" // serverless ingest URL
4)OpenTelemetry Java agents accept the standard otel.exporter.otlp.endpoint property; the SDK constructs the signal-specific paths as needed for OTLP/HTTP. You’ll still export MW_API_KEY=... alongside sbt run.
(Optional) Custom logs from your Scala code
If you want to emit custom logs (INFO/WARN/DEBUG/ERROR) that correlate with traces, add the agent-apm-java library to your build and use its Logger:
- Add dependency (SBT):
1// build.sbt 2libraryDependencies += "io.github.middleware-labs" % "agent-apm-java" % "0.0.18" - Use the logger (Scala/Java interop):
1// anywhere in your app code 2import io.github.middlewarelabs.agentapmjava.Logger 3 4Logger.info("info message") 5Logger.debug("debug message") 6Logger.warn("warn message") 7Logger.error("error message") - Record stack errors Call
recordErrorfrom a catch block to attach stack traces to the active span:1try { 2 // ... 3} catch { 4 case e: Exception => 5 io.github.middlewarelabs.agentapmjava.Logger.recordError(e) 6 throw e 7}
View your data
After you start the app, wait 3–5 minutes, then open Traces, Logs, and Profiling in Middleware to verify data is flowing. (This mirrors your Scala page’s flow.)
SBT notes & tips
- Forking is required for
javaOptions(like-javaagent) to apply tosbt run. Configure(run / fork) := true. - If you package with sbt-native-packager, you can also push Java options into start scripts via
Universal / javaOptionsor add extra defines to scripts. - When sending data without a local collector,
otel.exporter.otlp.endpointis the standard knob; OTLP exporters also support header-based auth viaotel.exporter.otlp.headersif you ever need it.
Environment variables
| Key/Option | Where it's used | Purpose | Example |
|---|---|---|---|
MW_AGENT_SERVICE | Containerized host-based | Route app → Host Agent | 172.17.0.1 (Docker), mw-service.mw-agent-ns.svc.cluster.local (K8s). |
MW_API_KEY | Runtime env | Your Middleware account key, required for export | export MW_API_KEY="…"; then sbt run. |
-Dotel.service.name | javaOptions | Logical service name shown in APM | -Dotel.service.name=payments-scala |
-Dotel.exporter.otlp.endpoint | javaOptions(serverless) | Send telemetry directly to Middleware ingest (no Host Agent) | -Dotel.exporter.otlp.endpoint=https://ruplp.middleware.io. |
Troubleshooting
- No telemetry appears → Confirm
(run / fork) := trueand the-javaagent:path is correct. SBT only applies javaOptions to a forked run. - Still no data on serverless → Ensure the endpoint property is set (
otel.exporter.otlp.endpoint) and that your key is present. OTLP HTTP exporters derive/v1/{signal}paths automatically when you set a base endpoint. - Packaging instead of
sbt run→ Use sbt-native-packager’sUniversal / javaOptionsor script defines so the agent flags end up in the generated start scripts.
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.