-
Notifications
You must be signed in to change notification settings - Fork 274
Add OpenTelemetry base classes #4982
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
Conversation
Qodana Community for JVM8 new problems were found
💡 Qodana analysis was run in the pull request mode: only the changed files were checked Contact Qodana teamContact us at [email protected]
|
...tbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt
Fixed
Show fixed
Hide fixed
| try { | ||
| val item = TraceRequestMarshaler.create(listOf(data)) | ||
|
|
||
| httpPost(traceUrl, contentLength = item.binarySerializedSize.toLong(), contentType = ContentType.XProtobuf) { |
Check warning
Code scanning / QDJVMC
Unstable API Usage Warning
| } catch (e: CancellationException) { | ||
| throw e | ||
| } catch (e: ConnectException) { | ||
| thisLogger().warn("Cannot export (url=$traceUrl): ${e.message}") |
Check notice
Code scanning / QDJVMC
Non-distinguishable logging calls Note
...tbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt
Fixed
Show fixed
Hide fixed
| } catch (e: CancellationException) { | ||
| throw e | ||
| } catch (e: ConnectException) { | ||
| thisLogger().warn("Cannot export (url=$traceUrl): ${e.message}") |
Check notice
Code scanning / QDJVMC
Non-distinguishable logging calls Note
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
| import java.io.ByteArrayOutputStream | ||
| import java.net.ConnectException | ||
|
|
||
| private class BasicOtlpSpanProcessor( |
Check warning
Code scanning / QDJVMC
Unused symbol Warning
| } | ||
| } | ||
|
|
||
| private class SigV4OtlpSpanProcessor( |
Check warning
Code scanning / QDJVMC
Unused symbol Warning
...tbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt
Fixed
Show fixed
Hide fixed
...tbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OTelService.kt
Fixed
Show fixed
Hide fixed
| } | ||
|
|
||
| companion object { | ||
| fun getSdk() = service<OTelService>().sdk |
Check warning
Code scanning / QDJVMC
Unused symbol Warning
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
| 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
Code scanning / QDJVMC
Function or property has platform type Note
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
.../jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/otel/OtelBase.kt
Fixed
Show fixed
Hide fixed
| it.identity(creds.resolveIdentity().get()) | ||
| it.request(httpRequest) | ||
| it.payload(payload) | ||
| it.putProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "osis") |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
open search ingestion service
| .setResource( | ||
| Resource.create( | ||
| Attributes.builder() | ||
| .put(AttributeKey.stringKey("os.type"), SystemInfoRt.OS_NAME) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
| fun `context propagates from parent to child when child overrides context`() { | ||
| spanBuilder("tracer", "parentSpan").use { | ||
| // parent->child relationship is still maintained because Context.current() will return parent context | ||
| spanBuilder("anotherTracer", "childSpan").setParent(Context.current().with(AWS_PRODUCT_CONTEXT_KEY, AWSProduct.AMAZON_Q_FOR_VS_CODE)).use {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change this to AMAZON_Q_FOR_JETBRAINS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
intentional so we know for sure it's working and not just picking up a default field somewhere
| assertThat(parent.parentSpanContext.traceId).isEqualTo(TraceId.getInvalid()) | ||
| assertThat(child.parentSpanContext.traceId).isEqualTo(parent.spanContext.traceId) | ||
| assertThat(parent.getAttribute(PLUGIN_ATTRIBUTE_KEY)).isNotEqualTo(child.getAttribute(PLUGIN_ATTRIBUTE_KEY)) | ||
| assertThat(child.getAttribute(PLUGIN_ATTRIBUTE_KEY)).isEqualTo("Amazon Q For VS Code") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would also change to JB?
| } | ||
|
|
||
| override fun onEnd(span: ReadableSpan) { | ||
| println(span) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
helpful for debugging without a debugger but this one can be removed
| } catch (e: CancellationException) { | ||
| throw e | ||
| } catch (e: ConnectException) { | ||
| thisLogger().warn("Cannot export (url=$traceUrl): ${e.message}") |
There was a problem hiding this comment.
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?
| abstract class AbstractSpanBuilder< | ||
| BuilderType : AbstractSpanBuilder<BuilderType, SpanType>, | ||
| SpanType : AbstractBaseSpan<SpanType>, | ||
| >( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should the > be on the previous line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't get formatter to do it
| parent = if (s is AbstractBaseSpan<*> && s.context != null) { | ||
| s.context.with(Span.fromContext(parent)) | ||
| } else { | ||
| parent.with(AWS_PRODUCT_CONTEXT_KEY, resolvePluginName()) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returns null if fails
## Problem At the moment, metrics in the JetBrains extensions are collected as singular datapoints independent of each other. Modern observability frameworks, as well as our long-term goals are to be able to correlate these data flows over a single user flow. This requires the 'trace ID' concept which is high-friction in the current model. ## Solution Generate 'fluent builders' that wrap the OpenTelemetry SDK to allow us to leverage the SDK to record trace/span IDs automatically, but still expose a good amount of type safety based on the metric schema. This PR references base classes proposed in aws/aws-toolkit-jetbrains#4982. ## License By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
…5027) * Depends on #4982 * Depends on aws/aws-toolkit-common#899 * Rename Unit -> MetricUnit directly in SDK codegen * Use newer provider convention syntax for input/output in generator task * expose `passive`/`unit`/`value` as special fields * add smoke test for `validateRequiredAttributes`
The OpenTelemetry SDK can automatically attach the same trace ID to spans recorded under the same 'context'. This is somewhat challenging because the JetBrains platform frequently requires switching threads and coroutine scope contexts, which loses the
ThreadLocalstate needed to connect parent->child when spans are started.This on its own is not too difficult, but becomes a significant ergonomic challenge when we also want to bring some type-safety to how span metadata is built. This PR allows spans generated in aws/aws-toolkit-common#899 to automatically perform context propagation.
See internal documentation for details. A contributor-friendly version of the doc will be written after we validate this pattern with some initial metrics.
License
I confirm that my contribution is made under the terms of the Apache 2.0 license.