mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
[maven] IDEA-340498 trace maven server calls
GitOrigin-RevId: 014b3b0549e7e5a7ac74f219d94d38b235bd24a4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
48f1e64951
commit
bdf57a7c4b
@@ -25,4 +25,8 @@ public class MavenServerResponse<T extends Serializable> implements Serializable
|
||||
public LongRunningTaskStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public byte[] getTelemetryTrace() {
|
||||
return telemetryTrace;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,8 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.backend.observation" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
||||
<orderEntry type="module" module-name="intellij.platform.diagnostic.telemetry" />
|
||||
<orderEntry type="module" module-name="intellij.platform.diagnostic.telemetry.impl" />
|
||||
<orderEntry type="module" module-name="intellij.maven.server.telemetry" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.rt" />
|
||||
<orderEntry type="module" module-name="intellij.maven.server" />
|
||||
<orderEntry type="library" name="jetbrains-annotations" level="project" />
|
||||
<orderEntry type="library" name="opentelemetry" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.maven.server" />
|
||||
<orderEntry type="library" name="opentelemetry-exporter-otlp-common" level="project" />
|
||||
<orderEntry type="library" name="jackson" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -125,9 +125,7 @@ final class MavenServerOpenTelemetryImpl implements MavenServerOpenTelemetry {
|
||||
@Override
|
||||
public byte[] shutdown() {
|
||||
try {
|
||||
if (null != rootSpan) {
|
||||
rootSpan.end();
|
||||
}
|
||||
rootSpan.end();
|
||||
if (myScope != null) {
|
||||
myScope.close();
|
||||
}
|
||||
@@ -135,15 +133,12 @@ final class MavenServerOpenTelemetryImpl implements MavenServerOpenTelemetry {
|
||||
((Closeable)myOpenTelemetry).close();
|
||||
}
|
||||
// the data should be exported only after OpenTelemetry was closed to prevent data loss
|
||||
if (mySpanDataCollector != null) {
|
||||
Collection<SpanData> collectedSpans = mySpanDataCollector.getCollectedSpans();
|
||||
return MavenSpanDataSerializer.serialize(collectedSpans);
|
||||
}
|
||||
Collection<SpanData> collectedSpans = mySpanDataCollector.getCollectedSpans();
|
||||
return MavenSpanDataSerializer.serialize(collectedSpans);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return ArrayUtilRt.EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
private static @NotNull Scope injectTracingContext(@NotNull OpenTelemetry telemetry, @NotNull MavenTracingContext context) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.maven.server.telemetry;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize;
|
||||
import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
public final class MavenServerTelemetryClasspathUtil {
|
||||
public static final Collection<Class<?>> TELEMETRY_CLASSES = Arrays.asList(
|
||||
SpanExporter.class,
|
||||
TextMapPropagator.class,
|
||||
OpenTelemetry.class,
|
||||
OpenTelemetrySdk.class,
|
||||
Clock.class,
|
||||
SdkMeterProvider.class,
|
||||
SdkLoggerProvider.class,
|
||||
TraceRequestMarshaler.class,
|
||||
MarshalerWithSize.class,
|
||||
JsonGenerator.class
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.maven.server.telemetry;
|
||||
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -16,7 +15,7 @@ public class MavenSpanDataSerializer {
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return ArrayUtilRt.EMPTY_BYTE_ARRAY;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.maven.maven3;
|
||||
|
||||
import com.intellij.maven.server.telemetry.MavenServerTelemetryClasspathUtil;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PathUtil;
|
||||
@@ -94,14 +95,7 @@ final class Maven3Support implements MavenVersionAwareSupportExtension {
|
||||
classpath.add(new File(root, "intellij.maven.server"));
|
||||
|
||||
classpath.add(new File(root, "intellij.maven.server.telemetry"));
|
||||
try {
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.sdk.trace.export.SpanExporter"))));
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.context.propagation.TextMapPropagator"))));
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.api.OpenTelemetry"))));
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
MavenLog.LOG.error(e);
|
||||
}
|
||||
classpath.addAll(MavenUtil.collectClasspath(MavenServerTelemetryClasspathUtil.TELEMETRY_CLASSES));
|
||||
|
||||
File parentFile = MavenUtil.getMavenPluginParentFile();
|
||||
classpath.add(new File(root, "intellij.maven.server.m3.common"));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.maven.maven4;
|
||||
|
||||
import com.intellij.maven.server.telemetry.MavenServerTelemetryClasspathUtil;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PathUtil;
|
||||
@@ -91,14 +92,7 @@ final class Maven4Support implements MavenVersionAwareSupportExtension {
|
||||
classpath.add(new File(root, "intellij.maven.server"));
|
||||
|
||||
classpath.add(new File(root, "intellij.maven.server.telemetry"));
|
||||
try {
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.sdk.trace.export.SpanExporter"))));
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.context.propagation.TextMapPropagator"))));
|
||||
classpath.add(new File(PathUtil.getJarPathForClass(Class.forName("io.opentelemetry.api.OpenTelemetry"))));
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
MavenLog.LOG.error(e);
|
||||
}
|
||||
classpath.addAll(MavenUtil.collectClasspath(MavenServerTelemetryClasspathUtil.TELEMETRY_CLASSES));
|
||||
|
||||
File parentFile = MavenUtil.getMavenPluginParentFile();
|
||||
addDir(classpath, new File(parentFile, "maven40-server-impl/lib"), f -> true);
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.idea.maven.model.*
|
||||
import org.jetbrains.idea.maven.project.MavenResolveResultProblemProcessor.BLOCKED_MIRROR_FOR_REPOSITORIES
|
||||
import org.jetbrains.idea.maven.project.MavenResolveResultProblemProcessor.MavenResolveProblemHolder
|
||||
import org.jetbrains.idea.maven.server.*
|
||||
import org.jetbrains.idea.maven.telemetry.tracer
|
||||
import org.jetbrains.idea.maven.utils.MavenLog
|
||||
import org.jetbrains.idea.maven.utils.MavenUtil
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.intellij.openapi.startup.ProjectActivity
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.platform.backend.observation.trackActivity
|
||||
import com.intellij.platform.diagnostic.telemetry.Scope
|
||||
import com.intellij.platform.diagnostic.telemetry.TelemetryManager
|
||||
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||
import com.intellij.platform.ide.progress.withBackgroundProgress
|
||||
import com.intellij.platform.util.progress.RawProgressReporter
|
||||
@@ -45,6 +43,7 @@ import org.jetbrains.idea.maven.model.MavenExplicitProfiles
|
||||
import org.jetbrains.idea.maven.project.preimport.MavenProjectStaticImporter
|
||||
import org.jetbrains.idea.maven.server.MavenWrapperDownloader
|
||||
import org.jetbrains.idea.maven.server.showUntrustedProjectNotification
|
||||
import org.jetbrains.idea.maven.telemetry.tracer
|
||||
import org.jetbrains.idea.maven.utils.MavenActivityKey
|
||||
import org.jetbrains.idea.maven.utils.MavenLog
|
||||
import org.jetbrains.idea.maven.utils.MavenUtil
|
||||
@@ -91,8 +90,6 @@ interface MavenAsyncProjectsManager {
|
||||
previewModule: Module?): List<Module>
|
||||
}
|
||||
|
||||
internal val tracer by lazy { TelemetryManager.getSimpleTracer(Scope("maven")) }
|
||||
|
||||
open class MavenProjectsManagerEx(project: Project, private val cs: CoroutineScope) : MavenProjectsManager(project) {
|
||||
override suspend fun addManagedFilesWithProfilesAndUpdate(files: List<VirtualFile>,
|
||||
profiles: MavenExplicitProfiles,
|
||||
|
||||
@@ -17,6 +17,9 @@ import org.jetbrains.idea.maven.buildtool.MavenSyncConsole
|
||||
import org.jetbrains.idea.maven.model.*
|
||||
import org.jetbrains.idea.maven.project.MavenConsole
|
||||
import org.jetbrains.idea.maven.server.MavenEmbedderWrapper.LongRunningEmbedderTask
|
||||
import org.jetbrains.idea.maven.telemetry.getCurrentTelemetryIds
|
||||
import org.jetbrains.idea.maven.telemetry.scheduleExportTelemetryTrace
|
||||
import org.jetbrains.idea.maven.telemetry.tracer
|
||||
import org.jetbrains.idea.maven.utils.MavenLog
|
||||
import org.jetbrains.idea.maven.utils.MavenProcessCanceledException
|
||||
import java.io.File
|
||||
@@ -268,13 +271,15 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr
|
||||
}
|
||||
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
withContext(Dispatchers.IO + tracer.span("runLongRunningTask")) {
|
||||
val telemetryIds = getCurrentTelemetryIds()
|
||||
blockingContext {
|
||||
val longRunningTaskInput = LongRunningTaskInput(longRunningTaskId, null, null)
|
||||
val longRunningTaskInput = LongRunningTaskInput(longRunningTaskId, telemetryIds.traceId, telemetryIds.spanId)
|
||||
val response = task.run(embedder, longRunningTaskInput)
|
||||
val status = response.status
|
||||
eventHandler.handleConsoleEvents(status.consoleEvents())
|
||||
eventHandler.handleDownloadEvents(status.downloadEvents())
|
||||
scheduleExportTelemetryTrace(project, response.telemetryTrace)
|
||||
response.result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.maven.telemetry
|
||||
|
||||
import com.intellij.diagnostic.ActivityImpl
|
||||
import com.intellij.diagnostic.CoroutineTracerShim
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.diagnostic.telemetry.Scope
|
||||
import com.intellij.platform.diagnostic.telemetry.TelemetryManager
|
||||
import com.intellij.platform.diagnostic.telemetry.impl.computeSpanId
|
||||
import com.intellij.platform.diagnostic.telemetry.impl.computeTraceId
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.idea.maven.utils.MavenCoroutineScopeProvider
|
||||
import org.jetbrains.idea.maven.utils.MavenLog
|
||||
import org.jetbrains.idea.maven.utils.MavenUtil
|
||||
import java.net.URI
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpRequest
|
||||
import java.net.http.HttpResponse
|
||||
|
||||
internal val tracer by lazy { TelemetryManager.getSimpleTracer(Scope(MavenUtil.MAVEN_NAME)) }
|
||||
|
||||
data class TelemetryIds(val traceId: String?, val spanId: String?)
|
||||
|
||||
private val emptyIds = TelemetryIds(null, null)
|
||||
|
||||
suspend fun getCurrentTelemetryIds(): TelemetryIds {
|
||||
val activity = CoroutineTracerShim.coroutineTracer.getTraceActivity()
|
||||
if (null == activity) return emptyIds
|
||||
if (activity !is ActivityImpl) {
|
||||
MavenLog.LOG.error("ActivityImpl expected")
|
||||
return emptyIds
|
||||
}
|
||||
val traceId = bytesToHex(computeTraceId(activity))
|
||||
val spanId = bytesToHex(computeSpanId(activity))
|
||||
|
||||
return TelemetryIds(traceId, spanId)
|
||||
}
|
||||
|
||||
private fun bytesToHex(bytes: ByteArray): String {
|
||||
val hexString = StringBuilder()
|
||||
for (b in bytes) {
|
||||
val hex = Integer.toHexString(0xff and b.toInt())
|
||||
if (hex.length == 1) {
|
||||
hexString.append('0')
|
||||
}
|
||||
hexString.append(hex)
|
||||
}
|
||||
return hexString.toString()
|
||||
}
|
||||
|
||||
private fun getOpenTelemetryAddress(): URI? {
|
||||
val property = System.getProperty("idea.diagnostic.opentelemetry.otlp")
|
||||
if (property == null) {
|
||||
return null
|
||||
}
|
||||
if (property.endsWith("/")) {
|
||||
return URI.create(property + "v1/traces")
|
||||
}
|
||||
return URI.create("$property/v1/traces")
|
||||
}
|
||||
|
||||
fun scheduleExportTelemetryTrace(project: Project, binaryTrace: ByteArray) {
|
||||
if (binaryTrace.isEmpty()) return
|
||||
|
||||
val telemetryHost = getOpenTelemetryAddress()
|
||||
if (null == telemetryHost) return
|
||||
|
||||
val cs = MavenCoroutineScopeProvider.getCoroutineScope(project)
|
||||
cs.launch {
|
||||
try {
|
||||
HttpClient.newHttpClient()
|
||||
.send(HttpRequest.newBuilder()
|
||||
.POST(HttpRequest.BodyPublishers.ofByteArray(binaryTrace))
|
||||
.uri(telemetryHost)
|
||||
.header("Content-Type", "application/x-protobuf")
|
||||
.build(),
|
||||
HttpResponse.BodyHandlers.discarding())
|
||||
}
|
||||
catch (e: java.lang.Exception) {
|
||||
MavenLog.LOG.error("Unable to upload performance traces to the OTLP server", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1747,4 +1747,12 @@ public class MavenUtil {
|
||||
public static MavenProjectModelReadHelper createModelReadHelper(Project project) {
|
||||
return new MavenProjectModelServerModelReadHelper(project);
|
||||
}
|
||||
|
||||
public static Collection<File> collectClasspath(Collection<Class<?>> classes) {
|
||||
var result = new ArrayList<File>();
|
||||
for (Class<?> c : classes) {
|
||||
result.add(new File(PathUtil.getJarPathForClass(c)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user