Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
@file:Suppress("UnusedPrivateClass")

package software.aws.toolkits.jetbrains.services.telemetry.otel

import com.intellij.openapi.Disposable
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.util.SystemInfoRt
import com.intellij.platform.util.http.ContentType
import com.intellij.platform.util.http.httpPost
import com.intellij.serviceContainer.NonInjectable
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator
import io.opentelemetry.context.Context
import io.opentelemetry.context.propagation.ContextPropagators
import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.sdk.trace.ReadWriteSpan
import io.opentelemetry.sdk.trace.ReadableSpan
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.SpanProcessor
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider
import software.amazon.awssdk.http.ContentStreamProvider
import software.amazon.awssdk.http.HttpExecuteRequest
import software.amazon.awssdk.http.SdkHttpMethod
import software.amazon.awssdk.http.SdkHttpRequest
import software.amazon.awssdk.http.apache.ApacheHttpClient
import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner
import java.io.ByteArrayOutputStream
import java.net.ConnectException

private class BasicOtlpSpanProcessor(

Check warning on line 40 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Class "BasicOtlpSpanProcessor" is never used

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Class "BasicOtlpSpanProcessor" is never used
private val coroutineScope: CoroutineScope,
private val traceUrl: String = "http://127.0.0.1:4318/v1/traces",
) : SpanProcessor {
override fun onStart(parentContext: Context, span: ReadWriteSpan) {}
override fun isStartRequired() = false
override fun isEndRequired() = true

Check warning on line 46 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L40-L46

Added lines #L40 - L46 were not covered by tests

override fun onEnd(span: ReadableSpan) {
val data = span.toSpanData()
coroutineScope.launch {
try {
val item = TraceRequestMarshaler.create(listOf(data))

Check warning on line 52 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L49-L52

Added lines #L49 - L52 were not covered by tests

httpPost(traceUrl, contentLength = item.binarySerializedSize.toLong(), contentType = ContentType.XProtobuf) {

Check warning on line 54 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unstable API Usage

'httpPost(java.lang.String, long, com.intellij.platform.util.http.ContentType, kotlin.jvm.functions.Function2,? extends java.lang.Object\>, kotlin.coroutines.Continuation)' is marked unstable with @ApiStatus.Internal

Check warning

Code scanning / QDJVMC

Unstable API Usage Warning

'httpPost(java.lang.String, long, com.intellij.platform.util.http.ContentType, kotlin.jvm.functions.Function2,? extends java.lang.Object>, kotlin.coroutines.Continuation)' is marked unstable with @ApiStatus.Internal
item.writeBinaryTo(this)
}
} catch (e: CancellationException) {
throw e
} catch (e: ConnectException) {
thisLogger().warn("Cannot export (url=$traceUrl): ${e.message}")

Check notice on line 60 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Non-distinguishable logging calls

Similar log messages

Check notice

Code scanning / QDJVMC

Non-distinguishable logging calls Note

Similar log messages
} catch (e: Throwable) {
thisLogger().error("Cannot export (url=$traceUrl)", e)

Check warning on line 62 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L55-L62

Added lines #L55 - L62 were not covered by tests
}
}
}

Check warning on line 65 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L64-L65

Added lines #L64 - L65 were not covered by tests
}

private class SigV4OtlpSpanProcessor(

Check warning on line 68 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Class "SigV4OtlpSpanProcessor" is never used

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Class "SigV4OtlpSpanProcessor" is never used
private val coroutineScope: CoroutineScope,
private val traceUrl: String,
private val creds: AwsCredentialsProvider,

Check warning on line 71 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L68-L71

Added lines #L68 - L71 were not covered by tests
) : SpanProcessor {
override fun onStart(parentContext: Context, span: ReadWriteSpan) {}
override fun isStartRequired() = false
override fun isEndRequired() = true

Check warning on line 75 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L73-L75

Added lines #L73 - L75 were not covered by tests

private val client = ApacheHttpClient.create()

Check warning on line 77 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L77

Added line #L77 was not covered by tests

override fun onEnd(span: ReadableSpan) {
coroutineScope.launch {
val data = span.toSpanData()
try {
val item = TraceRequestMarshaler.create(listOf(data))

Check warning on line 83 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L81-L83

Added lines #L81 - L83 were not covered by tests
// calculate the sigv4 header
val signer = AwsV4HttpSigner.create()
val httpRequest =
SdkHttpRequest.builder()
.uri(traceUrl)
.method(SdkHttpMethod.POST)
.putHeader("Content-Type", "application/x-protobuf")
.build()

Check warning on line 91 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L85-L91

Added lines #L85 - L91 were not covered by tests

val baos = ByteArrayOutputStream()
item.writeBinaryTo(baos)
val payload = ContentStreamProvider.fromByteArray(baos.toByteArray())
val signedRequest = signer.sign {
it.identity(creds.resolveIdentity().get())
it.request(httpRequest)
it.payload(payload)
it.putProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "osis")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this property name stand for

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open search ingestion service

it.putProperty(AwsV4HttpSigner.REGION_NAME, "us-west-2")
}

Check warning on line 102 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L93-L102

Added lines #L93 - L102 were not covered by tests

// Create and HTTP client and send the request. ApacheHttpClient requires the 'apache-client' module.
client.prepareRequest(
HttpExecuteRequest.builder()
.request(signedRequest.request())
.contentStreamProvider(signedRequest.payload().orElse(null))
.build()
).call()
} catch (e: CancellationException) {
throw e
} catch (e: ConnectException) {
thisLogger().warn("Cannot export (url=$traceUrl): ${e.message}")

Check notice on line 114 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Non-distinguishable logging calls

Similar log messages

Check notice

Code scanning / QDJVMC

Non-distinguishable logging calls Note

Similar log messages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should this also be log.error?

} catch (e: Throwable) {
thisLogger().error("Cannot export (url=$traceUrl)", e)

Check warning on line 116 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L105-L116

Added lines #L105 - L116 were not covered by tests
}
}
}

Check warning on line 119 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L118-L119

Added lines #L118 - L119 were not covered by tests
}

private object StdoutSpanProcessor : SpanProcessor {
override fun onStart(parentContext: Context, span: ReadWriteSpan) {}
override fun isStartRequired() = false
override fun isEndRequired() = true

Check warning on line 125 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L123-L125

Added lines #L123 - L125 were not covered by tests

override fun onEnd(span: ReadableSpan) {
println(span.toSpanData())
}

Check warning on line 129 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L128-L129

Added lines #L128 - L129 were not covered by tests
}

@Service
class OTelService @NonInjectable internal constructor(spanProcessors: List<SpanProcessor>) : Disposable {
@Suppress("unused")
constructor() : this(listOf(StdoutSpanProcessor))

Check warning on line 135 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L135

Added line #L135 was not covered by tests

private val sdkDelegate = lazy {
OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.apply {
spanProcessors.forEach {
addSpanProcessor(it)
}
}
.setResource(
Resource.create(
Attributes.builder()
.put(AttributeKey.stringKey("os.type"), SystemInfoRt.OS_NAME)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would we use this recorded information other than telemetry?
Should this have all the fields that we record for the telemetry publisher?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are common fields understood by OTLP processors

.put(AttributeKey.stringKey("os.version"), SystemInfoRt.OS_VERSION)
.put(AttributeKey.stringKey("host.arch"), System.getProperty("os.arch"))
.build()
)
)
.build()
)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.build()
}
internal val sdk: OpenTelemetrySdk by sdkDelegate

override fun dispose() {
if (sdkDelegate.isInitialized()) {
sdk.close()

Check warning on line 164 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L164

Added line #L164 was not covered by tests
}
}

Check warning on line 166 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L166

Added line #L166 was not covered by tests

companion object {
fun getSdk() = service<OTelService>().sdk

Check warning on line 169 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Function "getSdk" is never used

Check warning on line 169 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt#L169

Added line #L169 was not covered by tests

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Function "getSdk" is never used
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.telemetry.otel

import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanBuilder
import io.opentelemetry.api.trace.SpanContext
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.context.Context
import io.opentelemetry.context.ContextKey
import io.opentelemetry.context.Scope
import kotlinx.coroutines.CoroutineScope
import software.amazon.awssdk.services.toolkittelemetry.model.AWSProduct
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.services.telemetry.PluginResolver
import java.time.Instant
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import com.intellij.platform.diagnostic.telemetry.helpers.use as ijUse
import com.intellij.platform.diagnostic.telemetry.helpers.useWithScope as ijUseWithScope

val AWS_PRODUCT_CONTEXT_KEY = ContextKey.named<AWSProduct>("pluginDescriptor")

Check notice on line 27 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Function or property has platform type

Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.

Check notice

Code scanning / QDJVMC

Function or property has platform type Note

Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.
internal val PLUGIN_ATTRIBUTE_KEY = AttributeKey.stringKey("plugin")

class DefaultSpanBuilder(delegate: SpanBuilder) : AbstractSpanBuilder<DefaultSpanBuilder, AbstractBaseSpan>(delegate) {
override fun doStartSpan() = BaseSpan(parent, delegate.startSpan())
}

abstract class AbstractSpanBuilder<Builder : AbstractSpanBuilder<Builder, Span>, Span : AbstractBaseSpan>(protected val delegate: SpanBuilder) : SpanBuilder {
/**
* Same as [com.intellij.platform.diagnostic.telemetry.helpers.use] except downcasts to specific subclass of [BaseSpan]
*
* @inheritdoc
*/
inline fun<T> use(operation: (Span) -> T): T =
startSpan().ijUse { span ->
operation(span as Span)
}

Check warning on line 43 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L41-L43

Added lines #L41 - L43 were not covered by tests

/**
* Same as [com.intellij.platform.diagnostic.telemetry.helpers.useWithScope] except downcasts to specific subclass of [BaseSpan]
*
* @inheritdoc
*/
suspend inline fun<T> useWithScope(
context: CoroutineContext = EmptyCoroutineContext,

Check warning on line 51 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L50-L51

Added lines #L50 - L51 were not covered by tests
crossinline operation: suspend CoroutineScope.(Span) -> T,
): T =
ijUseWithScope(context) { span ->

Check warning on line 54 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L54

Added line #L54 was not covered by tests
operation(span as Span)
}

Check warning on line 56 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L56

Added line #L56 was not covered by tests

protected var parent: Context? = null
override fun setParent(context: Context): Builder {
parent = context
delegate.setParent(context)
return this as Builder
}

override fun setNoParent(): Builder {
parent = null
delegate.setNoParent()
return this as Builder

Check warning on line 68 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L66-L68

Added lines #L66 - L68 were not covered by tests
}

override fun addLink(spanContext: SpanContext): Builder {
delegate.addLink(spanContext)
return this as Builder

Check warning on line 73 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L72-L73

Added lines #L72 - L73 were not covered by tests
}

override fun addLink(
spanContext: SpanContext,
attributes: Attributes,
): Builder {
delegate.addLink(spanContext, attributes)
return this as Builder

Check warning on line 81 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L80-L81

Added lines #L80 - L81 were not covered by tests
}

override fun setAttribute(key: String, value: String): Builder {
delegate.setAttribute(key, value)
return this as Builder

Check warning on line 86 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L85-L86

Added lines #L85 - L86 were not covered by tests
}

override fun setAttribute(key: String, value: Long): Builder {
delegate.setAttribute(key, value)
return this as Builder

Check warning on line 91 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L90-L91

Added lines #L90 - L91 were not covered by tests
}

override fun setAttribute(key: String, value: Double): Builder {
delegate.setAttribute(key, value)
return this as Builder

Check warning on line 96 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L95-L96

Added lines #L95 - L96 were not covered by tests
}

override fun setAttribute(key: String, value: Boolean): Builder {
delegate.setAttribute(key, value)
return this as Builder

Check warning on line 101 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L100-L101

Added lines #L100 - L101 were not covered by tests
}

override fun <V : Any?> setAttribute(
key: AttributeKey<V?>,
value: V & Any,
): Builder {
delegate.setAttribute(key, value)
return this as Builder
}

override fun setAllAttributes(attributes: Attributes): Builder {
delegate.setAllAttributes(attributes)
return this as Builder

Check warning on line 114 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L113-L114

Added lines #L113 - L114 were not covered by tests
}

override fun setSpanKind(spanKind: SpanKind): Builder {
delegate.setSpanKind(spanKind)
return this as Builder

Check warning on line 119 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L118-L119

Added lines #L118 - L119 were not covered by tests
}

override fun setStartTimestamp(startTimestamp: Long, unit: TimeUnit): Builder {
delegate.setStartTimestamp(startTimestamp, unit)
return this as Builder

Check warning on line 124 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L123-L124

Added lines #L123 - L124 were not covered by tests
}

override fun setStartTimestamp(startTimestamp: Instant): Builder {
delegate.setStartTimestamp(startTimestamp)
return this as Builder

Check warning on line 129 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L128-L129

Added lines #L128 - L129 were not covered by tests
}

protected abstract fun doStartSpan(): Span

override fun startSpan(): Span {
var parent = parent
if (parent == null) {
parent = Context.current()
}
requireNotNull(parent)

val contextValue = parent.get(AWS_PRODUCT_CONTEXT_KEY)
if (contextValue == null) {
// FIX_WHEN_MIN_IS_243: Kotlin compiler can't figure out difference between class/type parameter until 2.x
val s = io.opentelemetry.api.trace.Span.fromContextOrNull(parent)
parent = if (s is AbstractBaseSpan && s.context != null) {
s.context.with(io.opentelemetry.api.trace.Span.fromContext(parent))
} else {
parent.with(AWS_PRODUCT_CONTEXT_KEY, resolvePluginName())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should resolvePluginName be under a try catch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns null if fails

}
setParent(parent)
}
requireNotNull(parent)

Check notice

Code scanning / QDJVMC

Redundant 'requireNotNull' or 'checkNotNull' call Note

Redundant 'requireNotNull' call

parent.get(AWS_PRODUCT_CONTEXT_KEY)?.toString()?.let {
setAttribute(PLUGIN_ATTRIBUTE_KEY, it)
} ?: run {
LOG.warn { "Reached setAttribute with null AWS_PRODUCT_CONTEXT_KEY, but should not be possible" }
}

Check warning on line 158 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L157-L158

Added lines #L157 - L158 were not covered by tests

return doStartSpan()
}

private companion object {
val LOG = getLogger<AbstractSpanBuilder<*, *>>()
fun resolvePluginName() = PluginResolver.Companion.fromStackTrace(Thread.currentThread().stackTrace).product

Check warning on line 165 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Redundant 'Companion' reference

Redundant Companion reference
}
}

abstract class AbstractBaseSpan(internal val context: Context?, private val delegate: Span) : Span by delegate {
/**
* Same as [com.intellij.platform.diagnostic.telemetry.helpers.use] except downcasts to specific subclass of [BaseSpan]
*
* @inheritdoc
*/
inline fun<T> use(operation: (Span) -> T): T =
ijUse { span ->
operation(span as Span)

Check warning on line 177 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Usage of redundant or deprecated syntax or deprecated symbols

No cast needed
}

Check warning on line 178 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L176-L178

Added lines #L176 - L178 were not covered by tests

fun metadata(key: String, value: String) = setAttribute(key, value)

Check notice on line 180 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Function or property has platform type

Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.

Check warning on line 180 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L180

Added line #L180 was not covered by tests

override fun makeCurrent(): Scope =
context?.with(this)?.makeCurrent() ?: super.makeCurrent()
}

/**
* Placeholder; will be generated
*/
class BaseSpan(context: Context?, delegate: Span) : AbstractBaseSpan(context, delegate) {
fun reason(reason: String) = metadata("reason", reason)

Check notice on line 190 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Function or property has platform type

Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.

Check warning on line 190 in plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt

View check run for this annotation

Codecov / codecov/patch

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt#L190

Added line #L190 was not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.intellij.openapi.util.ThrowableComputable
import com.intellij.util.ExceptionUtil
import com.intellij.util.concurrency.AppExecutorUtil
import com.intellij.util.concurrency.Semaphore
import io.opentelemetry.context.Context
import software.aws.toolkits.jetbrains.services.telemetry.PluginResolver
import java.time.Duration
import java.util.concurrent.Future
Expand Down Expand Up @@ -81,8 +82,9 @@ fun <T> pluginAwareExecuteOnPooledThread(action: () -> T): Future<T> {
* worker thread will not contain original call stack. Necessary for telemetry.
*/
val pluginResolver = PluginResolver.fromCurrentThread()
val context = Context.current()
return ApplicationManager.getApplication().executeOnPooledThread<T> {
PluginResolver.setThreadLocal(pluginResolver)
action()
context.wrap(action).call()
}
}
Loading
Loading