diff --git a/app/build.gradle b/app/build.gradle index b74d955a05..ef55ea4c96 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -160,6 +160,7 @@ android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 + coreLibraryDesugaringEnabled true } packagingOptions { @@ -789,6 +790,15 @@ dependencies { // openwnn (bundled because it is not published outside of JCenter, which is deprecated) implementation fileTree(dir: "${project.rootDir}/libs/openwnn/", include: ['*.aar']) + + // OpenTelemetry + implementation libs.opentelemetry.android.core + implementation libs.opentelemetry.android.instrumentation.activity + implementation libs.opentelemetry.android.instrumentation.anr + implementation libs.opentelemetry.android.instrumentation.crash + implementation libs.opentelemetry.android.instrumentation.sessions + implementation libs.opentelemetry.exporter.logging + coreLibraryDesugaring libs.desugar.jdk.libs } if (findProject(':servo')) { diff --git a/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java b/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java index 96e0b5c4c0..2186429e30 100644 --- a/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java +++ b/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java @@ -65,6 +65,7 @@ import com.igalia.wolvic.search.SearchEngineWrapper; import com.igalia.wolvic.speech.SpeechRecognizer; import com.igalia.wolvic.speech.SpeechServices; +import com.igalia.wolvic.telemetry.OpenTelemetry; import com.igalia.wolvic.telemetry.TelemetryService; import com.igalia.wolvic.ui.OffscreenDisplay; import com.igalia.wolvic.ui.adapters.Language; @@ -284,6 +285,11 @@ protected void onCreate(Bundle savedInstanceState) { SettingsStore.getInstance(getBaseContext()).setPid(Process.myPid()); ((VRBrowserApplication)getApplication()).onActivityCreate(this); + + if (!DeviceType.isHVRBuild() && SettingsStore.getInstance(getBaseContext()).isTelemetryEnabled()) { + TelemetryService.setService(new OpenTelemetry(getApplication())); + } + // Fix for infinite restart on startup crashes. long count = SettingsStore.getInstance(getBaseContext()).getCrashRestartCount(); boolean cancelRestart = count > CrashReporterService.MAX_RESTART_COUNT; diff --git a/app/src/common/shared/com/igalia/wolvic/VRBrowserApplication.java b/app/src/common/shared/com/igalia/wolvic/VRBrowserApplication.java index c21a4d658a..623080ab3c 100644 --- a/app/src/common/shared/com/igalia/wolvic/VRBrowserApplication.java +++ b/app/src/common/shared/com/igalia/wolvic/VRBrowserApplication.java @@ -53,8 +53,8 @@ public class VRBrowserApplication extends Application implements AppServicesProv protected void onActivityCreate(@NonNull Context activityContext) { onConfigurationChanged(activityContext.getResources().getConfiguration()); - TelemetryService.init(activityContext); mAppExecutors = new AppExecutors(); + TelemetryService.init(activityContext); mConnectivityManager = new ConnectivityReceiver(activityContext); mConnectivityManager.init(); mPlaces = new Places(activityContext); diff --git a/app/src/common/shared/com/igalia/wolvic/telemetry/OpenTelemetry.java b/app/src/common/shared/com/igalia/wolvic/telemetry/OpenTelemetry.java new file mode 100644 index 0000000000..3b80f6837d --- /dev/null +++ b/app/src/common/shared/com/igalia/wolvic/telemetry/OpenTelemetry.java @@ -0,0 +1,91 @@ +package com.igalia.wolvic.telemetry; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; + +import android.app.Application; +import android.os.Bundle; + +import com.igalia.wolvic.BuildConfig; +import com.igalia.wolvic.VRBrowserApplication; + +import java.util.concurrent.Executor; + +import io.opentelemetry.android.OpenTelemetryRum; +import io.opentelemetry.android.OpenTelemetryRumBuilder; +import io.opentelemetry.android.config.OtelRumConfig; +import io.opentelemetry.android.features.diskbuffering.DiskBufferingConfiguration; +import io.opentelemetry.android.instrumentation.activity.ActivityLifecycleInstrumentation; +import io.opentelemetry.android.instrumentation.sessions.SessionInstrumentation; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.exporter.logging.LoggingSpanExporter; + +public class OpenTelemetry implements ITelemetry { + private final Application mApplication; + private OpenTelemetryRum mRUM; + private OpenTelemetryRumBuilder mRUMBuilder; + private final String INSTRUMENTATION_SCOPE_NAME = BuildConfig.APPLICATION_ID; + private final String INSTRUMENTATION_SCOPE_VERSION = "1.0.0"; + private final Executor mDiskIOExecutor; + + public OpenTelemetry(Application app) { + mApplication = app; + mDiskIOExecutor = ((VRBrowserApplication) mApplication).getExecutors().diskIO(); + } + + private void initializeOpenTelemetryAndroid() { + DiskBufferingConfiguration diskBufferingConfiguration = DiskBufferingConfiguration.builder() + .setEnabled(true) + .setMaxCacheSize(10 * 1024 * 1024) + .setMaxFileAgeForWriteMillis(1000 * 5) + .build(); + OtelRumConfig config = new OtelRumConfig() + .setDiskBufferingConfiguration(diskBufferingConfiguration); + mRUMBuilder = OpenTelemetryRum.builder(mApplication, config) + .addSpanExporterCustomizer(exporter -> LoggingSpanExporter.create()) + .addInstrumentation(new SessionInstrumentation()) + .addInstrumentation(new ActivityLifecycleInstrumentation()); + try { + mRUM = mRUMBuilder.build(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void runOnDiskIO(Runnable runnable) { mDiskIOExecutor.execute(runnable); } + + @Override + public void start() { + assert mRUM == null; + initializeOpenTelemetryAndroid(); + } + + @Override + public void stop() { + mRUM = null; + mRUMBuilder = null; + } + + @Override + public void customEvent(String name) { + assert mRUM != null; + runOnDiskIO(() -> { + mRUM.getOpenTelemetry().getTracer(INSTRUMENTATION_SCOPE_NAME, INSTRUMENTATION_SCOPE_VERSION) + .spanBuilder(name) + .startSpan() + .end(); + }); + } + + @Override + public void customEvent(String name, Bundle bundle) { + assert mRUM != null; + runOnDiskIO(() -> { + SpanBuilder spanBuilder = mRUM.getOpenTelemetry().getTracer(INSTRUMENTATION_SCOPE_NAME, INSTRUMENTATION_SCOPE_VERSION) + .spanBuilder(name); + for (String key : bundle.keySet()) { + spanBuilder.setAttribute(key, bundle.get(key).toString()); + } + spanBuilder.startSpan().end(); + }); + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000000..abfef0549b --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,13 @@ +[versions] +desugar_jdk_libs = "2.1.4" +opentelemetryApi = "1.46.0" +opentelemetryAndroid = "0.9.1-alpha" + +[libraries] +desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" } +opentelemetry-exporter-logging = { module = "io.opentelemetry:opentelemetry-exporter-logging", version.ref = "opentelemetryApi" } +opentelemetry-android-core = { module = "io.opentelemetry.android:core", version.ref = "opentelemetryAndroid" } +opentelemetry-android-instrumentation-activity = { module = "io.opentelemetry.android:instrumentation-activity", version.ref = "opentelemetryAndroid" } +opentelemetry-android-instrumentation-anr = { module = "io.opentelemetry.android:instrumentation-anr", version.ref = "opentelemetryAndroid" } +opentelemetry-android-instrumentation-crash = { module = "io.opentelemetry.android:instrumentation-crash", version.ref = "opentelemetryAndroid" } +opentelemetry-android-instrumentation-sessions = { module = "io.opentelemetry.android:instrumentation-sessions", version.ref = "opentelemetryAndroid" } diff --git a/versions.gradle b/versions.gradle index 7d9f33a913..3b8a02d11f 100644 --- a/versions.gradle +++ b/versions.gradle @@ -46,7 +46,7 @@ versions.atsl_rules = "1.5.0" versions.atsl_junit = "1.1.5" versions.espresso = "3.5.1" versions.android_gradle_plugin = '8.7.2' -versions.kotlin = "1.9.21" +versions.kotlin = "2.1.0" versions.kotlin_coroutines = "1.7.3" versions.snakeyaml = "2.0" versions.gson = "2.10.1" @@ -191,8 +191,8 @@ build_versions.target_sdk_wave = 31 build_versions.target_sdk_aosp = 29 build_versions.target_sdk_spaces = 29 build_versions.target_sdk_visionglass = 33 -build_versions.compile_sdk = 34 -build_versions.build_tools = "34.0.0" +build_versions.compile_sdk = 35 +build_versions.build_tools = "35.0.0" ext.build_versions = build_versions ext.deps = deps