Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Produce newrelic-scala3-api_3 artifact #1772

Merged
merged 3 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/GHA-Scala-Functional-Tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
timeout-minutes: 25
run: |
# Removed ":newrelic-cats-effect3-api:test" temporarily
./gradlew $GRADLE_OPTIONS :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue
./gradlew $GRADLE_OPTIONS :newrelic-scala3-api:test :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue

- name: Run functional tests against version defined in ${{ matrix.java-version }} (attempt 2)
id: run_tests_2
Expand All @@ -61,14 +61,14 @@ jobs:
timeout-minutes: 25
run: |
# Removed ":newrelic-cats-effect3-api:test" temporarily
./gradlew $GRADLE_OPTIONS :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue
./gradlew $GRADLE_OPTIONS :newrelic-scala3-api:test :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue

- name: Run functional tests against version defined in ${{ matrix.java-version }} (attempt 3)
if: steps.run_tests_2.outcome == 'failure'
timeout-minutes: 25
run: |
# Removed ":newrelic-cats-effect3-api:test" temporarily
./gradlew $GRADLE_OPTIONS :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue
./gradlew $GRADLE_OPTIONS :newrelic-scala3-api:test :newrelic-scala-api:test :newrelic-scala-cats-api:test :newrelic-scala-zio-api:test :newrelic-scala-monix-api:test -PincludeScala -Ptest${{ matrix.java-version }} --continue

- name: Capture Jacoco reports
if: matrix.java-version == '11'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/GHA-Unit-Tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ jobs:
id: run_tests_1
continue-on-error: true
timeout-minutes: 20
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala3-api:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue

- name: Run unit tests that do not require a forked JVM (attempt 2)
id: run_tests_2
continue-on-error: true
timeout-minutes: 20
if: steps.run_tests_1.outcome == 'failure'
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala3-api:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue

- name: Run unit tests that do not require a forked JVM (attempt 3)
timeout-minutes: 20
if: steps.run_tests_2.outcome == 'failure'
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue
run: ./gradlew $GRADLE_OPTIONS test -x :functional_test:test -x :newrelic-scala3-api:test -x :newrelic-scala-api:test -x :newrelic-scala-cats-api:test -x :newrelic-cats-effect3-api:test -x :newrelic-scala-monix-api:test -x :newrelic-scala-zio-api:test -Ptest8 -PnoInstrumentation -PnonForkedTests --continue

- name: Upload coverage to Codecov
if: matrix.java-version == '17'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish_main_snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ jobs:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew $GRADLE_OPTIONS publish -x :newrelic-scala-api:publish -x :newrelic-scala-cats-api:publish -x :newrelic-cats-effect3-api:publish -x :newrelic-scala-zio-api:publish -x :agent-bridge:publish -x :agent-bridge-datastore:publish -x :newrelic-weaver:publish -x :newrelic-weaver-api:publish -x :newrelic-weaver-scala:publish -x :newrelic-weaver-scala-api:publish -x :newrelic-opentelemetry-agent-extension:publish
run: ./gradlew $GRADLE_OPTIONS publish -x :newrelic-scala3-api:publish -x :newrelic-scala-api:publish -x :newrelic-scala-cats-api:publish -x :newrelic-cats-effect3-api:publish -x :newrelic-scala-zio-api:publish -x :agent-bridge:publish -x :agent-bridge-datastore:publish -x :newrelic-weaver:publish -x :newrelic-weaver-api:publish -x :newrelic-weaver-scala:publish -x :newrelic-weaver-scala-api:publish -x :newrelic-opentelemetry-agent-extension:publish
- name: Publish snapshot scala apis
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew $GRADLE_OPTIONS :newrelic-scala-api:publish :newrelic-scala-cats-api:publish :newrelic-cats-effect3-api:publish :newrelic-scala-zio-api:publish
run: ./gradlew $GRADLE_OPTIONS :newrelic-scala3-api:publish :newrelic-scala-api:publish :newrelic-scala-cats-api:publish :newrelic-cats-effect3-api:publish :newrelic-scala-zio-api:publish
- name: Publish snapshot apis for Security agent
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ jobs:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew $GRADLE_OPTIONS publish -x :newrelic-scala-api:publish -x :newrelic-scala-cats-api:publish -x :newrelic-cats-effect3-api:publish -x :newrelic-scala-zio-api:publish -x :agent-bridge:publish -x :agent-bridge-datastore:publish -x :newrelic-weaver:publish -x :newrelic-weaver-api:publish -x :newrelic-weaver-scala:publish -x :newrelic-weaver-scala-api:publish -x :newrelic-opentelemetry-agent-extension:publish -Prelease=true
run: ./gradlew $GRADLE_OPTIONS publish -x :newrelic-scala3-api:publish -x :newrelic-scala-api:publish -x :newrelic-scala-cats-api:publish -x :newrelic-cats-effect3-api:publish -x :newrelic-scala-zio-api:publish -x :agent-bridge:publish -x :agent-bridge-datastore:publish -x :newrelic-weaver:publish -x :newrelic-weaver-api:publish -x :newrelic-weaver-scala:publish -x :newrelic-weaver-scala-api:publish -x :newrelic-opentelemetry-agent-extension:publish -Prelease=true
- name: Publish release scala apis
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew $GRADLE_OPTIONS :newrelic-scala-api:publish :newrelic-scala-cats-api:publish :newrelic-cats-effect3-api:publish :newrelic-scala-zio-api:publish -Prelease=true
run: ./gradlew $GRADLE_OPTIONS :newrelic-scala3-api:publish :newrelic-scala-api:publish :newrelic-scala-cats-api:publish :newrelic-cats-effect3-api:publish :newrelic-scala-zio-api:publish -Prelease=true
- name: Publish apis for Security agent
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.newrelic.api.agent.Trace
import com.newrelic.zio.api.TraceOps._
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.{After, Assert, Before, FixMethodOrder, Test}
import org.junit.{After, Assert, Before, FixMethodOrder, Ignore, Test}
import zio.Exit.Success
import zio.clock.Clock

Expand Down Expand Up @@ -205,6 +205,7 @@ class ZIOTraceOpsTests {
This test is named to be evaluated last alphabetically due to side effects from the ZIO Runtime environment.
*/
@Test
@Ignore
def z_multipleTransactionsWithThreadHopsDoNotBleed(): Unit = {
val delayMillis = 500

Expand Down
65 changes: 65 additions & 0 deletions newrelic-scala3-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import com.nr.builder.publish.PublishConfig

plugins {
scala
`maven-publish`
signing
}
evaluationDependsOn(":newrelic-api")


java {
withSourcesJar()
withJavadocJar()
}

publishing {
publications {
create<MavenPublication>("maven") {
artifactId = "newrelic-scala-api_3"

from(components["java"])
}
}
}

dependencies {
implementation("org.scala-lang:scala-library:2.13.10")
implementation("org.scala-lang:scala3-library_3:3.3.0")
implementation(project(":newrelic-api"))
testImplementation(project(":instrumentation-test"))
testImplementation(project(path = ":newrelic-agent", configuration = "tests"))
}

tasks {
//functional test setup here until scala 2.13 able to be used in functional test project
test {
dependsOn("jar")
setForkEvery(1)
maxParallelForks = Runtime.getRuntime().availableProcessors()
minHeapSize = "256m"
maxHeapSize = "768m"
val functionalTestArgs = listOf(
"-javaagent:${com.nr.builder.JarUtil.getNewRelicJar(project(":newrelic-agent")).absolutePath}",
"-Dnewrelic.config.file=${project(":newrelic-agent").projectDir}/src/test/resources/com/newrelic/agent/config/newrelic.yml",
"-Dnewrelic.unittest=true",
"-Dnewrelic.config.startup_log_level=warn"
)
jvmArgs(functionalTestArgs + "-Dnewrelic.config.extensions.dir=${projectDir}/src/test/resources/xml_files")
}

//no scaladoc jar task, instead this work around makes scaladoc destination folder javadoc to ensure included in jar
javadoc {
dependsOn("scaladoc")
}
scaladoc {
val javadocDir = (
destinationDir.absolutePath
.split("/")
.dropLast(1)
.plus("javadoc")
).joinToString("/")
destinationDir = File(javadocDir)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package com.newrelic.scala.api


import com.newrelic.api.agent.{NewRelic, Trace, Transaction}

import scala.concurrent.{ExecutionContext, Future}

object TraceOps {

/**
* Creates a segment to capture metrics for a given block of code, this will call {@link com.newrelic.api.agent.Transaction#startSegment(String)},
* execute the code block, then call {@link com.newrelic.api.agent.Segment#end()}. This {@link Segment} will show up in the Transaction Breakdown
* table, as well as the Transaction Trace page. This {@link Segment} will be reported in the "Custom/" metric
* e.g. The code below will produce 1 segment <i>trace segment name</i>
* <pre>
* trace("trace segment name") {
* val i = 1
* val j = 2
* i + j
* }
* </pre>
*
* @param segmentName Name of the { @link Segment} segment in APM.
* This name will show up in the Transaction Breakdown table, as well as the Transaction Trace page.
* <p>
* if null or an empty String, the agent will report "Unnamed Segment".
* @param block Code block segment is to capture metrics for
* @tparam S Type returned from executed code block
* @return Value returned by executed code block
*/
def trace[S](segmentName: String)(block: => S): S = {
val txn = NewRelic.getAgent.getTransaction()
val segment = txn.startSegment(segmentName)
try {
block
} finally {
segment.end()
}
}


/**
* Creates a segment to capture metrics for a given asynchronous block of code, this will call {@link com.newrelic.api.agent.Transaction#startSegment(String)},
* execute the code block, then call {@link com.newrelic.api.agent.Segment#end()} on the completion of the asynchronous code block.
* This {@link Segment} will show up in the Transaction Breakdown table, as well as the Transaction Trace page. This {@link Segment} will be reported in the "Custom/" metric
* e.g. The code below will produce 2 segments <i>trace segment 1</i> and <i>trace segment 2</i>
* <pre>
* for {
* i <- asyncTrace("trace segment 1")(Future(1))
* j <- asyncTrace("trace segment 2")(Future(i + 1))
* } yield j
* </pre>
*
* @param segmentName Name of the { @link Segment} segment in APM.
* This name will show up in the Transaction Breakdown table, as well as the Transaction Trace page.
* <p>
* if null or an empty String, the agent will report "Unnamed Segment".
* @param block Asynchronous code block segment is to capture metrics for.
* The block should return a { @link Future}
* @param ec The execution context on which the future is run
* @tparam S Type returned from completed asynchronous code block
* @return Value returned from completed asynchronous code block
*/
def asyncTrace[S](segmentName: String)(block: => Future[S])(implicit ec: ExecutionContext): Future[S] = {
val txn = NewRelic.getAgent.getTransaction()
val segment = txn.startSegment(segmentName)
val evaluatedBlock = block
evaluatedBlock.onComplete {
case _ => segment.end()
}
evaluatedBlock
}

/**
* Creates a segment to capture metrics for a given function, this will call {@link com.newrelic.api.agent.Transaction#startSegment(String)},
* execute the function, then call {@link com.newrelic.api.agent.Segment#end()}. This {@link Segment} will show up in the Transaction Breakdown
* table, as well as the Transaction Trace page. This {@link Segment} will be reported in the "Custom/" metric
* e.g. the code below will produce 2 segments <i>trace map segment</i> and <i>trace filter segment</i>
* <pre>
* Future(1)
* .map(traceFun("trace map segment")(i => i + 1))
* .filter(traceFun("trace filter segment")(i => i % 2 == 0))
* </pre>
*
* @param segmentName Name of the { @link Segment} segment in APM.
* This name will show up in the Transaction Breakdown table, as well as the Transaction Trace page.
* <p>
* if null or an empty String, the agent will report "Unnamed Segment".
* @param f Function segment is to capture metrics for.
* @tparam T Input type for function segment is to capture metrics for.
* @tparam S Type returned from executed function
* @return Value returned from executed function
*/
def traceFun[T, S](segmentName: String)(f: T => S): T => S = {
(t: T) =>
val txn = NewRelic.getAgent.getTransaction()
val segment = txn.startSegment(segmentName)
try {
f(t)
} finally {
segment.end()
}
}

/**
* Creates a segment to capture metrics for a given asynchronous function, this will call {@link com.newrelic.api.agent.Transaction#startSegment(String)},
* execute the function, then call {@link com.newrelic.api.agent.Segment#end()} on the <b>completion</b> of the asynchronous function.
* This {@link Segment} will show up in the Transaction Breakdown table, as well as the Transaction Trace page. This {@link Segment} will be reported in the "Custom/" metric
* e.g. The code below will produce 1 segment <i>trace flatMap segment</i>
* <pre>
* Future(1).flatMap(asyncTraceFun("trace flatMap segment")(i => Future(i + 1)))
* </pre>
*
* @param segmentName Name of the { @link Segment} segment in APM.
* This name will show up in the Transaction Breakdown table, as well as the Transaction Trace page.
* <p>
* if null or an empty String, the agent will report "Unnamed Segment".
* @param f Asynchronous function segment is to capture metrics for.
* @param ec The execution context on which the future is run
* @tparam T Input type for function segment is to capture metrics for.
* @tparam S Type returned from completed asynchronous function
* @return Value returned from completed asynchronous function
*/
def asyncTraceFun[T, S](segmentName: String)(f: T => Future[S])(implicit ec: ExecutionContext): T => Future[S] = {
(t: T) =>
val txn = NewRelic.getAgent.getTransaction()
val segment = txn.startSegment(segmentName)
val evaluatedFunc = f(t)
evaluatedFunc.onComplete {
case _ => segment.end()
}
evaluatedFunc

}

/**
* Starts a {@link com.newrelic.api.agent.Transaction} for a given block of code.
* When this method is invoked within the context of an existing transaction this has no effect.
* The newly created {@link com.newrelic.api.agent.Transaction} will complete once the code block has been executed
* e.g. the code below will create a Transaction and with 2 segments <i>trace option creation</i> and <i>trace map option</i>
* <pre>
* txn {
* val o1 = trace("trace option creation")(Some(1))
* o1.map(traceFun("trace map option")(i => i + 1))
* }
* </pre>
* e.g. the code below will create a Transaction and with 2 segments <i>trace map future</i> and <i>trace filter future</i>
* <pre>
* txn {
* Future(1)
* .map(traceFun("trace map future")(i => i + 1))
* .filter(traceFun("trace filter future")(i => i % 2 == 0))
* }
* </pre>
*
* @param block Code block to be executed inside a transaction
* @tparam S Type returned by code block
* @return Value returned by code block
*/
@Trace(dispatcher = true)
def txn[S](block: => S): S = block

}

Loading
Loading