Skip to content
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
11 changes: 9 additions & 2 deletions plugins/core/jetbrains-community/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,22 @@ buildscript {
}
}

private val generatedSrcDir = project.layout.buildDirectory.dir("generated-src")
sourceSets {
main {
java.srcDir(project.layout.buildDirectory.dir("generated-src"))
java.srcDir(generatedSrcDir)
}
}

idea {
module {
generatedSourceDirs = generatedSourceDirs.toMutableSet() + generatedSrcDir.get().asFile
}
}

val generateTelemetry = tasks.register<GenerateTelemetry>("generateTelemetry") {
inputFiles = listOf(file("${project.projectDir}/resources/telemetryOverride.json"))
outputDirectory = project.layout.buildDirectory.dir("generated-src").get().asFile
outputDirectory = generatedSrcDir.get().asFile

doFirst {
outputDirectory.deleteRecursively()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.intellij.platform.diagnostic.telemetry.helpers

import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.StatusCode
import kotlin.coroutines.cancellation.CancellationException

val EXCEPTION_ESCAPED = AttributeKey.booleanKey("exception.escaped")

inline fun <T> Span.useWithoutActiveScope(operation: (Span) -> T): T {
try {
return operation(this)
} catch (e: CancellationException) {
recordException(e, Attributes.of(EXCEPTION_ESCAPED, true))
throw e
} catch (e: Throwable) {
recordException(e, Attributes.of(EXCEPTION_ESCAPED, true))
setStatus(StatusCode.ERROR)
throw e
} finally {
end()
}
}
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
}
}
Loading
Loading