• EnglishEspañol日本語한국어Português
  • Log inStart now

Scala instrumentation

The New Relic Java agent is compatible with Scala, and supports New Relic API calls, annotations, and custom instrumentation. All information below is supplemental to New Relic's Java agent installation directions.

Tip

For Heroku, see Java agent with Scala on Heroku.

Scala frameworks

If your framework is not natively supported by New Relic, or if you want to set up additional monitoring, custom instrumentation is a great way to dig deeper into your application.

Instrument Scala with the Scala API

The New Relic Scala agent API lets you control, customize, and extend the functionality of the APM Java agent using idiomatic Scala code. It can be used alongside the New Relic Java API as well as allow users to

  • Create segments for synchronous and asynchronous anonymous functions
  • Create segments for synchronous and asynchronous code blocks
  • Create a transaction if one has not already been started

Important

For best results when using the API, ensure that you have the latest Java agent release. The New Relic Scala API requires Java agent 7.1.0 or higher.

Use the Scala API

To access the API class add the following information to your Scala configuration file:

Supported Scala versions are 2.10, 2.11, 2.12 and 2.13. Scala 3.0 users can use the 2.13 jar. The jar is deployed to Maven Central and it is also in the New Relic Java agent's installation zip file. You can call the API when the Java agent is not running. The underlying API methods are just stubs; the implementation is added when the Java agent is running.

Segments

To create segment for a synchronous code block use TraceOps.trace. For example:

import com.newrelic.scala.api.TraceOps.trace
trace("statement segment") {
val i = 1
val j = 2
println(i + j)
}
// trace can also be used as an expression
val x: Int = trace("expression segment") {
val i = 1
val j = 2
i + j
}
println(x) // 2

trace can also be used in Scala For comprehensions

import scala.concurrent.{ExecutionContext, Future}
import com.newrelic.scala.api.TraceOps.trace
// implicit execution
implicit val ec: ExecutionContext = ???
val x: Option[Int] = for {
one <- trace("segment one")(Option(1))
two <- trace("segment two")(Option(one + 1))
three <- trace("segment three")(Option(two + 1))
} yield three
println(x) // Some(3)

If you want to create segment for an asynchronous code block containing a Scala Future use TraceOps.asyncTrace. This will ensure the timing for the segment includes the time taken for the Future to complete.

In the example below segment time will be no less than 5 seconds due to the delay created in the wrapped Future.

import scala.concurrent.{ExecutionContext, Future}
import com.newrelic.scala.api.TraceOps.asyncTrace
// implicit execution
implicit val ec: ExecutionContext = ???
val x: Future[Int] = asyncTrace("segment name")(Future {
Thread.sleep(5000)
1
})
x.foreach(println) // prints 1 on completion of Future

asyncTrace can also be used in Scala For comprehensions

import scala.concurrent.{ExecutionContext, Future}
import com.newrelic.scala.api.TraceOps.asyncTrace
// implicit execution
implicit val ec: ExecutionContext = ???
val x: Future[Int] = for {
one <- asyncTrace("segment one")(Future(1))
two <- asyncTrace("segment two")(Future(one + 1))
three <- asyncTrace("segment three")(Future(two + 1))
} yield three
x.foreach(println) // prints 3 on completion of Future

If you want to create segment for a synchronous anonymous function use TraceOps.traceFun. For example:

import com.newrelic.scala.api.TraceOps.traceFun
val x: Option[Int] = Option(1)
.map(traceFun("statement segment")(i => i + 1))
println(x) //Some(2)

If you want to create segment for an asynchronous function that returns a Scala Future use TraceOps.asyncTraceFun. This will ensure the timing for the segment includes the time taken for the function to complete.

In the example below segment time will be no less than 5 seconds due to the delay created in the wrapped Future.

import scala.concurrent.{ExecutionContext, Future}
import com.newrelic.scala.api.TraceOps.asyncTraceFun
// implicit execution
implicit val ec: ExecutionContext = ???
val x: Future[Int] = Future(1)
.flatMap(asyncTraceFun("statement segment")(i => Future(i + 1)))
x.foreach(println) // prints 2 on completion of Future

Transactions

Transactions can be created using the TraceOps.txn method. For example:

import com.newrelic.scala.api.TraceOps.txn
txn {
val i = 1
val j = 2
println(i + j)
}

txn can be used as a statement (as above) or as an expression

import com.newrelic.scala.api.TraceOps.txn
val i: Int = txn(1 + 2) //transaction created
println(i) // 3

txn can be used with any of the TraceOp methods to create segments. The example below create a transaction with 3 segments.

import scala.concurrent.{ExecutionContext, Future}
import com.newrelic.scala.api.TraceOps.{txn, asyncTrace}
// implicit execution
implicit val ec: ExecutionContext = ???
val x: Future[Int] = txn(
for {
one <- asyncTrace("segment one")(Future(1))
two <- asyncTrace("segment two")(Future(one + 1))
three <- asyncTrace("segment three")(Future(two + 1))
} yield three
)
x.foreach(println) // prints 3 on completion of Future

Instrument Scala with the Java agent API

Instrument Scala to use the New Relic API class or annotations.

  1. Add the following information to your Scala configuration file:

  2. Import the NewRelic class and use it in your application:

    import com.newrelic.api.agent.NewRelic
    ...
    NewRelic.setTransactionName(null, "/myTransaction");

More API functions

For more about the Java agent API and its functionality, see the Java agent API introduction.

Instrument Scala with XML instrumentation

XML instrumentation is available for any Scala application running with the Java agent. It allows instrumentation to be added without any changes to the code.

For more information, see Java instrumentation by XML.

Additional instrumentation

If you use Kamon, take a look at the New Relic Kamon reporter.

Copyright © 2024 New Relic Inc.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.