Code Monkey home page Code Monkey logo

dd-sdk-android's Introduction

Datadog SDK for Android and Android TV

A client-side Android and Android TV library to interact with Datadog.

Getting Started

Log Collection

See the dedicated Datadog Android Log Collection documentation to learn how to forward logs from your Android or Android TV application to Datadog.

Real User Monitoring

See the dedicated Datadog Android RUM Collection documentation to learn how to send RUM data from your Android or Android TV application to Datadog.

Log Integrations

Timber

If your existing codebase is using Timber, you can forward all those logs to Datadog automatically by using the dedicated library.

RUM Integrations

Coil

If you use Coil to load images in your application, see Datadog's dedicated library.

Fresco

If you use Fresco to load images in your application, see Datadog's dedicated library.

Glide

If you use Glide to load images in your application, see Datadog's dedicated library.

Jetpack Compose

If you use Jetpack Compose in your application, see Datadog's dedicated library.

SQLDelight

If you use SQLDelight in your application, see Datadog's dedicated library.

RxJava

If you use RxJava in your application, see Datadog's dedicated library.

Picasso

If you use Picasso, use it with the OkHttpClient that's been instrumented with the Datadog SDK for RUM and APM information about network requests made by Picasso.

        val picasso = Picasso.Builder(context)
                .downloader(OkHttp3Downloader(okHttpClient))
                //
                .build()
        Picasso.setSingletonInstance(picasso)

Retrofit

If you use Retrofit, use it with the OkHttpClient that's been instrumented with the Datadog SDK for RUM and APM information about network requests made with Retrofit.

        val retrofitClient = Retrofit.Builder()
                .client(okHttpClient)
                //
                .build()

Apollo (GraphQL)

If you use Apollo, use it with the OkHttpClient that's been instrumented with the Datadog SDK for RUM and APM information about all the queries performed through Apollo client.

        val apolloClient =  ApolloClient.builder()
                 .okHttpClient(okHttpClient)
                 .serverUrl(<APOLLO_SERVER_URL>)
                 .build()

Kotlin Coroutines

If you use Kotlin Coroutines, see Datadog's dedicated library with extensions for RUM and with extensions for Trace

Looking up your logs

When you open your console in Datadog, navigate to the Log Explorer. In the search bar, type source:android. This filters your logs to only show the ones coming from Android or Android TV applications.

Datadog Mobile Logs

Looking up your spans

When you open your console in Datadog, navigate to APM > Services. In the list of services, you can see all your Android and Android TV applications (by default, the service name matches your application's package name, for example: com.example.android). You can access all the traces started from your application.

Datadog Mobile Logs

Looking up your RUM events

When you open your console in Datadog, navigate to the RUM Explorer. In the side bar, you can select your application and explore Sessions, Views, Actions, Errors, Resources, and Long Tasks.

Datadog Mobile Logs

Troubleshooting

If you encounter any issue when using the Datadog SDK for Android and Android TV, please take a look at the troubleshooting checklist, common problems, or at the existing issues.

Datadog cannot guarantee the Android and Android TV SDK's performance on Roku devices running with Android OS. If you encounter any issues when using the SDK for these devices, contact Datadog Support or open an issue in our GitHub project.

Contributing

Pull requests are welcome. First, open an issue to discuss what you would like to change. For more information, read the Contributing Guide.

License

Apache License, v2.0

dd-sdk-android's People

Contributors

0xnm avatar alai97 avatar cswatt avatar daniel-m-dd avatar dd-mergequeue[bot] avatar desponda avatar fuzzybinary avatar ganeshkumarsv avatar gualt1995 avatar hugokash avatar igorwojda avatar jonathanmos avatar jtappa avatar katerina-kossler avatar kayayarai avatar l0k0ms avatar louiszawadzki avatar mariusc83 avatar maycmlee avatar ncreated avatar plousada avatar priyanshi-gupta avatar pyricau avatar rtrieu avatar ruthnaebeck avatar sarina-dd avatar simonpatarin avatar tasomaniac avatar tomaz avatar xgouchet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dd-sdk-android's Issues

ConcurrentModificationException crash on FileReader.sendBatches

Describe what happened

This is one of our top crashes w/ 50-100 crashes daily. From what I see there needs to be some concurrency handling around sentBatches.

Fatal Exception: java.util.ConcurrentModificationException
java.util.LinkedHashMap$LinkedHashIterator.nextEntry (LinkedHashMap.java:411)
java.util.LinkedHashSet.<init> (LinkedHashSet.java:169)
kotlin.collections.CollectionsKt___CollectionsKt.toMutableSet (_Collections.kt:1509)
kotlin.collections.CollectionsKt___CollectionsKt.union (_Collections.kt:1524)
com.datadog.android.core.internal.data.file.FileReader.readNextFile (FileReader.kt:70)
com.datadog.android.core.internal.data.file.FileReader.readNextBatch (FileReader.kt:29)
com.datadog.android.core.internal.data.upload.DataUploadRunnable.run (DataUploadRunnable.kt:36)
android.os.Handler.handleCallback (Handler.java:751)
android.os.HandlerThread.run (HandlerThread.java:61)

Steps to reproduce the issue:
Unknown

Describe what you expected:

Additional context

  • Android OS version: Wide spread
  • Device Model: Wide spread
  • Datadog SDK version: 1.2.0
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration: N/A
  • Gradle Plugins:

Some CUSTOM Actions not reported

Describe what happened
GlobalRum.get().addUserAction(RumActionType.CUSTOM, name, map) is used

  • When using FragmentViewTrackingStrategy some actions (like 5% off all actions) are not reported, there is really nothing special about that 5% missing actions, but those are always the same actions
  • When using ActivityViewTrackingStrategy the missing actions seem to be reported
  • The action is added immediately before a transition from one fragment to another

Describe what you expected:

  • all actions are always reported

Additional context

  • Android OS version: 7.1
  • Datadog SDK version: 1.7.1
  • There are no errors / warnings in the logs (at level Log.VERBOSE)

It's a big closed-source project so source code extracts cannot be provided.

Log class names with the Timber logger

When using the Timber logger via
Timber.plant(new DatadogTree(logger));
the classname doesn't propagate in the logs. All logs are tagged with /DatadogTree: ...... | at .log(DatadogTree.kt:32) instead of the actual tag(class).

If I use the DataDog logger directly it works. It also works if I plant the Timber.DebugTree with Timber.plant(new Timber.DebugTree());

This is happening on 1.7.1 (and prior).

Crash from crashlytics

v1.6.0 marks one of the crash fix, is this same?

Crash from firebase crqashlytics:

Unable to reproduce myself, or uncertain of exact steps

Device
Brand: Google
Model: Pixel 5
Orientation: Portrait
RAM free: 3.44 GB
Disk free: 82.11 GB
Operating System
Version: 11
Orientation: Portrait
Rooted: No

Stacktrace:
Fatal Exception: java.lang.RuntimeException
Unable to create application com.everlance.EverlanceApplication: java.lang.SecurityException: Package android does not belong to 10277
android.app.ActivityThread.handleBindApplication
Caused by java.lang.SecurityException
Package android does not belong to 10277
android.os.Parcel.createExceptionOrNull (Parcel.java:2373)
android.net.ConnectivityManager.registerDefaultNetworkCallback (ConnectivityManager.java:4158)
com.datadog.android.core.internal.net.info.CallbackNetworkInfoProvider.register (CallbackNetworkInfoProvider.kt:55)
com.datadog.android.core.internal.CoreFeature.setupInfoProviders (CoreFeature.kt:109)
com.datadog.android.core.internal.CoreFeature.initialize (CoreFeature.kt:60)
com.datadog.android.Datadog.initialize (Datadog.kt:88)
com.datadog.android.Datadog.initialize (Datadog.kt:158)
com.datadog.android.Datadog.initialize$default (Datadog.kt:152)
com.datadog.android.Datadog.initialize (Unknown Source:2)
com.everlance.EverlanceApplication.onCreate (EverlanceApplication.java:70)
android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1192)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:947)
Caused by android.os.RemoteException
Remote stack trace: at android.app.AppOpsManager.checkPackage(AppOpsManager.java:7631) at com.android.server.ConnectivityService.ensureSufficientPermissionsForRequest(ConnectivityService.java:5444) at com.android.server.ConnectivityService.requestNetwork(ConnectivityService.java:5539) at android.net.IConnectivityManager$Stub.onTransact(IConnectivityManager.java:1570) at android.os.Binder.execTransactInternal(Binder.java:1154)

Multiple services found in the RUM explorer, despite setting serviceName explicitly

Describe what happened
I setup the ServiceName in the androidSDK manually as follow:

 val datadogConfig = DatadogConfig.Builder(
      BuildConfig.DATADOG_CLIENT_TOKEN,
      BuildConfig.BUILD_TYPE,
      BuildConfig.DATADOG_APPLICATION_ID
    )
      .setServiceName("Android: $packageName")
      .useViewTrackingStrategy(FragmentViewTrackingStrategy(true))
      .setRumEnabled(true)
      .trackInteractions()
      .build()

However, in the RUM Explorer I notice two services:

  1. One with Android: <MY PACKAGE NAME>.
  2. One with android:_<MY PACKAGE NAME>.

screenshot

Where is this android:_<MY PACKAGE NAME> coming from?

Steps to reproduce the issue:

  1. Initialize datadog SDK in main application's class onCreate().
  2. Go to RUM Explorer, and track the services there.

Describe what you expected:
I expected to find only Android: <MY PACKAGE NAME> service. However, I found another service android:_<MY PACKAGE NAME> there.

Additional context

  • Android OS version: 10
  • Device Model: Galaxy S10
  • Datadog SDK version: 1.7.9
  • Versions of any other relevant dependencies (OkHttp, …): Retrofit 2.8.1
  • Proguard configuration: Default
  • Gradle Plugins:
 const val buildToolsVersion = "4.0.0"
  const val androidJunit5Plugin = "1.6.0.0"
  const val navigationSafeArgsPlugin = "2.1.0"
  const val googleServicesPlugin = "4.3.3"
  const val firebaseCrashlyticsPlugin = "2.3.0"

Support custom EventListener in DatadogEventListener.Factory

Is your feature request related to a problem? Please describe.
Currently, I have custom EventListener which tracks some important stuff, but OkHttp supports only one. So I am needed to choose to use Datadog's or custom.

Describe the solution you'd like

A one way to solve problem is by using delegates:

internal constructor(val delegate: EventListener, val key: String) : EventListener() by delegate {

    class Factory(delegate: EventListener = NoOpEventListener) : EventListener.Factory {
        override fun create(call: Call): EventListener {
            val key = identifyRequest(call.request())
            return DatadogEventListener(delegate, key)
        }
    }
}

Describe alternatives you've considered

The alternative is to implement delegate support in the custom EventListener. However, I believe many other projects have some custom EventListener already, so maybe it is a good decision to support delegates in the library.

Runtime crash

Describe what happened
Library was crashing shortly after app started twice. In my application class, after initializing Datadog and the loggers, I was logging two lines to each of my 3 Datadog loggers
Repeatable 100%.

        DatadogLoggerManagerKt.getPaymentDatadogLogger().i(
                DatadogLoggerManagerKt.getPaymentDatadogLogger().successMessage());

        DatadogLoggerManagerKt.getPaymentDatadogLogger().e(
                DatadogLoggerManagerKt.getPaymentDatadogLogger().failureWithErrorCodeMessage());
        DatadogLoggerManagerKt.getEnrollmentDatadogLogger().e(
                DatadogLoggerManagerKt.getEnrollmentDatadogLogger().failureMessage());
        DatadogLoggerManagerKt.getEnrollmentDatadogLogger().i(
                DatadogLoggerManagerKt.getEnrollmentDatadogLogger().successMessage());
2020-02-20 15:22:03.203 E/AndroidRuntime: FATAL EXCEPTION: ddog
    Process: com.udemy.android, PID: 17968
    java.lang.IllegalArgumentException: Input byte array has incorrect ending byte at 312
        at java.util.Base64$Decoder.decode0(Base64.java:742)
        at java.util.Base64$Decoder.decode(Base64.java:526)
        at com.datadog.android.log.internal.file.LogFileReader.deobfuscateApi26(LogFileReader.kt:84)
        at com.datadog.android.log.internal.file.LogFileReader.deobfuscate(LogFileReader.kt:73)
        at com.datadog.android.log.internal.file.LogFileReader.readNextBatch(LogFileReader.kt:50)
        at com.datadog.android.log.internal.LogUploadRunnable.run(LogUploadRunnable.kt:33)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.os.HandlerThread.run(HandlerThread.java:65)

My app has 3 Datadog loggers to allow for different service names.

Main code to create loggers

import com.datadog.android.log.Logger

interface LoggerMessages {
    fun successMessage(): String = "success"
    fun failureMessage(): String = "failure"
    fun failureWithErrorCodeMessage(): String = "failure: "
}

abstract class AbstractDatadogLogger(serviceName: String): LoggerMessages {

    private val datadogLogger = Logger.Builder()
            .setNetworkInfoEnabled(true)
            .setDatadogLogsEnabled(!BuildConfig.DEBUG)
            .setServiceName(serviceName)
            .build()

    // -- Below is copy of Datadog log API; forwards all logs to Datadog's logger

    /**
     * Sends a VERBOSE log message.
     * @param message the message to be logged
     * @param throwable a (nullable) throwable to be logged with the message
     * @param attributes a map of attributes to include only for this message. If an attribute with
     * the same key already exist in this logger, it will be overriden (just for this message)
     */
    @Suppress("FunctionMinLength")
    @JvmOverloads
    fun v(
            message: String,
            throwable: Throwable? = null,
            attributes: Map<String, Any?> = emptyMap()
    ) {
        datadogLogger.v(message, throwable, attributes)
    }

    /**
     * Sends a Debug log message.
     * @param message the message to be logged
     * @param throwable a (nullable) throwable to be logged with the message
     * @param attributes a map of attributes to include only for this message. If an attribute with
     * the same key already exist in this logger, it will be overriden (just for this message)
     */
    @Suppress("FunctionMinLength")
    @JvmOverloads
    fun d(
            message: String,
            throwable: Throwable? = null,
            attributes: Map<String, Any?> = emptyMap()
    ) {
        datadogLogger.d(message, throwable, attributes)
    }

    /**
     * Sends an Info log message.
     * @param message the message to be logged
     * @param throwable a (nullable) throwable to be logged with the message
     * @param attributes a map of attributes to include only for this message. If an attribute with
     * the same key already exist in this logger, it will be overriden (just for this message)
     */
    @Suppress("FunctionMinLength")
    @JvmOverloads
    fun i(
            message: String,
            throwable: Throwable? = null,
            attributes: Map<String, Any?> = emptyMap()
    ) {
        datadogLogger.i(message, throwable, attributes)
    }

    /**
     * Sends a Warning log message.
     * @param message the message to be logged
     * @param throwable a (nullable) throwable to be logged with the message
     * @param attributes a map of attributes to include only for this message. If an attribute with
     * the same key already exist in this logger, it will be overriden (just for this message)
     */
    @Suppress("FunctionMinLength")
    @JvmOverloads
    fun w(
            message: String,
            throwable: Throwable? = null,
            attributes: Map<String, Any?> = emptyMap()
    ) {
        datadogLogger.w(message, throwable, attributes)
    }

    /**
     * Sends an Error log message.
     * @param message the message to be logged
     * @param throwable a (nullable) throwable to be logged with the message
     * @param attributes a map of attributes to include only for this message. If an attribute with
     * the same key already exist in this logger, it will be overriden (just for this message)
     */
    @Suppress("FunctionMinLength")
    @JvmOverloads
    fun e(
            message: String,
            throwable: Throwable? = null,
            attributes: Map<String, Any?> = emptyMap()
    ) {
        datadogLogger.e(message, throwable, attributes)
    }

}

Concrete implementations are tiny. They only add to the interface with additional messages. sample usage is logger.e(logger.errorMessage())
see below for one of them

class EmailDatadogLogger : AbstractDatadogLogger("android.login.email"), EmailMessages

interface EmailMessages : LoggerMessages {
    override fun successMessage(): String = "email sign in success"
    override fun failureMessage(): String = "email sign in failure: "
    fun failureWithoutErrorCodeMessage(): String = "email sign in failure: generic, "
}

Steps to reproduce the issue:
Crashed on app start after the second app open (Application.onCreate() called again)
I can fix the issue by removing the lines above and reinstalling the app.

Describe what you expected:
lib to not crash

Additional context

  • Android OS version:8.1.0
  • Device Model:Mi Phone MI 8M1803E1A
  • Datadog SDK version:1.0.0
  • Versions of any other relevant dependencies (OkHttp, …): can provide if necessary
  • Proguard configuration: 6.2.0
  • Gradle Plugins:n/a

NavigationViewTrackingStrategy is not tracking child destinations

Describe what happened
NavigationViewTrackingStrategy doesn't track child destinations. The structure looks sth like that:
-- MainActivity
\_____ RootHomeFragment (this could be a fragment with bottom nav)
\________ Child fragments (e.g. the ones selected via the bottom nav)
In the above scenario we have two navControllers: one in MainActivity and the seconds one in RootHomeFragment.

Not sure if that is the problem but could be

Steps to reproduce the issue:
Building a sample repo with the above structure ;) I will attach it if I find time to build it.

Describe what you expected:
Child destination are tracked

Additional context

  • Android OS version: not relevant
  • Device Model: not relevant
  • Datadog SDK version: 1.5.0-alpha2
  • Versions of any other relevant dependencies (OkHttp, …): not relevant
  • Proguard configuration: disabled
  • Gradle Plugins: not relevant

RUM View name is not shown completely when the obfuscation is enabled (Proguard/R8 enabled)

Describe what happened
The obfuscated views are shown with the shrunk names:
Here is an example of what I see in RUM explorer -> attributes -> view:
image

But all logs are not like this. Some Fragment and Activity names are shown correctly.

Steps to reproduce the issue:

        Datadog.initialize(
            this, DatadogConfig.Builder(
                DATADOG_CLIENT_TOKEN,
                envName = BuildConfig.BUILD_TYPE,
                applicationId = DATADOG_APPLICATION_ID
            )
                .useViewTrackingStrategy(MixedViewTrackingStrategy(trackExtras = true))
                .trackInteractions()
                .setRumEnabled(true)
                .configureDatadogFlavor()
                .build()
        )
        val monitor = RumMonitor.Builder()
            .build()
        GlobalRum.registerIfAbsent(monitor)

Describe what you expected:
The name of the obfuscated views are shown completely.

Additional context

  • Android OS version: 10
  • Device Model: Samsung SM-G985F
  • Datadog SDK version: 1.5.1
  • Versions of any other relevant dependencies (OkHttp, …): 'com.squareup.okhttp3:okhttp:4.4.1'
  • Proguard configuration:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


# Fabric
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception
#-printmapping mapping.txt

-keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.**

#Disable logging
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}

### https://gist.github.com/jemshit/767ab25a9670eb0083bafa65f8d786bb

### Glide, Glide Okttp Module, Glide Transformations
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
# -keepresourcexmlelements manifest/application/meta-data@value=GlideModule 3 For dexguard

### Viewpager indicator
-dontwarn com.viewpagerindicator.**

### Support v7, Design
# http://stackoverflow.com/questions/29679177/cardview-shadow-not-appearing-in-lollipop-after-obfuscate-with-proguard/29698051
-keep class android.support.v7.widget.RoundRectDrawable { *; }

-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }

-keep public class * extends android.support.v4.view.ActionProvider {
    public <init>(android.content.Context);
}

-dontwarn android.support.**
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }

# https://github.com/Gericop/Android-Support-Preference-V7-Fix/blob/master/preference-v7/proguard-rules.pro
-keepclassmembers class android.support.v7.preference.PreferenceGroupAdapter {
    private ** mPreferenceLayouts;
}
-keepclassmembers class android.support.v7.preference.PreferenceGroupAdapter$PreferenceLayout {
    private int resId;
    private int widgetResId;
}

# https://github.com/dandar3/android-support-animated-vector-drawable/blob/master/proguard-project.txt
#-keepclassmembers class android.support.graphics.drawable.VectorDrawableCompat$* {
#   void set*(***);
#   *** get*();
#}

# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
# -keep class com.google.gson.examples.android.model.** { *; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

### Retrofit 2
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions

-dontwarn retrofit2.adapter.rxjava.CompletableHelper$** # https://github.com/square/retrofit/issues/2034
#To use Single instead of Observable in Retrofit interface
-keepnames class rx.Single
#Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.-KotlinExtensions

### OkHttp3
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase


### Kotlin
#https://stackoverflow.com/questions/33547643/how-to-use-kotlin-with-proguard
#https://medium.com/@AthorNZ/kotlin-metadata-jackson-and-proguard-f64f51e5ed32
-keepclassmembers class **$WhenMappings {
    <fields>;
}
-keep class kotlin.Metadata { *; }
-keepclassmembers class kotlin.Metadata {
    public <methods>;
}

### Other
-dontwarn com.google.errorprone.annotations.*

### Android Architecture Components
# Ref: https://issuetracker.google.com/issues/62113696
# LifecycleObserver's empty constructor is considered to be unused by proguard
#-keepclassmembers class * implements android.arch.lifecycle.LifecycleObserver {
#    <init>(...);
#}
-keep class * implements android.arch.lifecycle.LifecycleObserver {
    <init>(...);
}

# ViewModel's empty constructor is considered to be unused by proguard
-keepclassmembers class * extends android.arch.lifecycle.ViewModel {
    <init>(...);
}

# keep Lifecycle State and Event enums values
-keepclassmembers class android.arch.lifecycle.Lifecycle$State { *; }
-keepclassmembers class android.arch.lifecycle.Lifecycle$Event { *; }
# keep methods annotated with @OnLifecycleEvent even if they seem to be unused
# (Mostly for LiveData.LifecycleBoundObserver.onStateChange(), but who knows)
-keepclassmembers class * {
    @android.arch.lifecycle.OnLifecycleEvent *;
}

## Databinding or library depends on databinding
-dontwarn android.databinding.**
-keep class android.databinding.** { *; }

### Kotlin Coroutine
# https://github.com/Kotlin/kotlinx.coroutines/blob/master/README.md
# ServiceLoader support
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepnames class kotlinx.coroutines.android.AndroidExceptionPreHandler {}
-keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory {}
# Most of volatile fields are updated with AFU and should not be mangled
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}
# https://github.com/Kotlin/kotlinx.atomicfu/issues/57
-dontwarn kotlinx.atomicfu.**

### Kotlin
#https://stackoverflow.com/questions/33547643/how-to-use-kotlin-with-proguard
#https://medium.com/@AthorNZ/kotlin-metadata-jackson-and-proguard-f64f51e5ed32
-keepclassmembers class **$WhenMappings {
    <fields>;
}
-keep class kotlin.Metadata { *; }
-keepclassmembers class kotlin.Metadata {
    public <methods>;
}

### Google Play Billing
-keep class com.android.vending.billing.**

### Adjust SDK, android.installreferrer
-keep public class com.adjust.sdk.** { *; }
-keep class com.google.android.gms.common.ConnectionResult {
    int SUCCESS;
}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
    com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
    java.lang.String getId();
    boolean isLimitAdTrackingEnabled();
}
-keep public class com.android.installreferrer.** { *; }

  • Gradle Plugins:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.firebase-perf'

seldom crash

Thanks for taking the time for reporting an issue!

Describe what happened
crash

Session summary
 3.1.2.2 (1603311495)
 7.0
 LG Stylo 3 Plus
 Apr 21, 2020, 11:57:00 PM
Stack trace


Fatal Exception: java.util.ConcurrentModificationException
java.util.LinkedHashMap$LinkedHashIterator.nextEntry (LinkedHashMap.java:411)
java.util.LinkedHashSet.<init> (LinkedHashSet.java:169)
kotlin.collections.CollectionsKt___CollectionsKt.toMutableSet (_Collections.kt:1452)
kotlin.collections.CollectionsKt___CollectionsKt.union (_Collections.kt:1467)
com.datadog.android.core.internal.data.file.FileReader.readNextFile (FileReader.kt:72)
com.datadog.android.core.internal.data.file.FileReader.readNextBatch (FileReader.kt:31)
com.datadog.android.core.internal.data.upload.DataUploadRunnable.run (DataUploadRunnable.kt:36)
android.os.Handler.handleCallback (Handler.java:751)
android.os.HandlerThread.run (HandlerThread.java:61)

Steps to reproduce the issue:

Describe what you expected:

Additional context

  • Android OS version:
  • Device Model:
  • Datadog SDK version:
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
  • Gradle Plugins:

Update kronos-android to latest version & remove android support dependencies

Are you requesting automatic instrumentation for a framework or library? Please describe.
N/A

Is your feature request related to a problem? Please describe.
Dependency upgrade

Describe the solution you'd like
Upgrade kronos-android to the latest version, which will help consumers drop transitive com.android.support deps in favor of AndroidX versions & help migrate off of Jetifier. This lib is one of the last remaining usages of support libraries keeping the Jetifier around on our builds.

Describe alternatives you've considered
N/A

Additional context
N/A

Support for minSdkVersion 17?

I need to be able to support older devices with sdk version 17. Is it a nonstarter, or is it worth trying?

Using implementation "com.datadoghq:dd-sdk-android:1.3.1"

	Suggestion: use a compatible library with a minSdk of at most 17,
		or increase this project's minSdk version to at least 19,
		or use tools:overrideLibrary="com.datadog.android" to force usage (may lead to runtime failures)

Add stop functionality for datadog

Are you requesting automatic instrumentation for a framework or library? Please describe.
No

Is your feature request related to a problem? Please describe.
I'd like to have a hook to stop datadog from sending logs to its server when I've already set up my logger / datadog config. Currently, if I use the same logger object, I have to create a new one in order to control not sending datadog info up. I'd rather keep using the same Logger object as a singleton and have some stop / control functionality on it.

Describe the solution you'd like
Make the DataDog.stop method public instead of private.

Describe alternatives you've considered
Give more functions on the DataDog logger so I can adjust it's functionality on the fly.

Additional context
Because DataDog as a service charges per amount of logging, I want the ability to easily turn it off as needed.

RUM doesn't send anything

I don't receive any data in the RUM dashboard. When I run the application I see this warning in logcat.
A RUM event was detected, but no view is active. To track views automatically, try calling the DatadogConfig.Builder.useViewTrackingStrategy() method.

My datadog config:

Datadog.initialize(
            this, DatadogConfig.Builder(
                DATADOG_CLIENT_TOKEN,
                envName = BuildConfig.BUILD_TYPE,
                applicationId = DATADOG_APPLICATION_ID
            )
                .useViewTrackingStrategy(MixedViewTrackingStrategy(trackExtras = true))
                .trackInteractions()
                .setRumEnabled(true)
                .build()
        )
  • Android OS version:10
  • Device Model:Redmi Note7
  • Datadog SDK version:1.6.1-1.7.1

[Question] How to modify RUM Resource metadata

Are you requesting automatic instrumentation for a framework or library? Please describe.
No

Is your feature request related to a problem? Please describe.
We're using DatadogInterceptor to enable both APM tracing and RUM integration in our Android app.
We have an internal tool that obfuscates URL paths so that HTTP request data in DD/other systems removes PII:

  • GET /orders/1.0/{orderId} would become GET /orders/1.0/[ORDERID]
  • POST /users/CustomerId-1234/profile would become POST /users/[USERID]/profile

Currently, we're using a custom TracedRequestListener on the interceptor to modify the Span and update the URL path, and its working great 👍 However, the automatic tracking of HTTP calls as RUM Resources doesn't use that same listener like I though it would, so RUM Resources aren't obfuscated and PII is showing up in our HTTP URLs in the RUM Resource records.

Describe the solution you'd like
Is there a way to translate/modify RUM Resource data before its sent up to the server? I'm not sure if RUM Resources are built/tracked using Spans, or some other mechanism... so re-using the existing TracedRequestListener may not make sense.

Describe alternatives you've considered
It seems like the RUM integration may have internal mechanisms to accomplish this (e.g. EventMapper ?), but I'm not sure of the best way to take advantage of them.

Additional context
N/A

Fatal Exception: java.io.FileNotFoundException /data/user/0/com.activehours/files/dd-logs-v1/1600303496930 (Permission denied) com.datadog.android.core.internal.data.file.FileExtensionsKt.readBytes

We are seeing a huge spike in crashes happening due to DataDog. Please see the following details:

Describe what happened
Include any error message or stack trace if available.
Stacktrace:

Fatal Exception: java.io.FileNotFoundException: /data/user/0/com.activehours/files/dd-logs-v1/1600303496930 (Permission denied)
       at java.io.FileInputStream.open0(FileInputStream.java)
       at java.io.FileInputStream.open(FileInputStream.java:200)
       at java.io.FileInputStream.<init>(FileInputStream.java:150)
       at com.datadog.android.core.internal.data.file.FileExtensionsKt.readBytes(FileExtensions.kt:7)
       at com.datadog.android.core.internal.data.file.FileReader.readNextFile(FileReader.kt:74)
       at com.datadog.android.core.internal.data.file.FileReader.readNextBatch(FileReader.kt:29)
       at com.datadog.android.core.internal.data.upload.DataUploadRunnable.run(DataUploadRunnable.kt:36)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.os.HandlerThread.run(HandlerThread.java:65)

It has happened 385 times in last 30 days.

Steps to reproduce the issue:
Not able to reproduce.

Describe what you expected:

Additional context

  • Android OS version: Android 9 (74% of times)
  • Device Model: Motorola devices (100% of times)
  • Datadog SDK version: 1.4.3
  • Device state: Background (95% times)

Callback when SDK is fully initialized?

Are you requesting automatic instrumentation for a framework or library? Please describe.
N/A

Is your feature request related to a problem? Please describe.
I'm seeing a warning when trying to configure global SDK functionality immediately after calling Datadog.initialize(...).
Our setup looks like this:

class DatadogWrapper {

    fun init() {
        Datadog.initialize(/* Details omitted*/)

        Datadog.setVerbosity(if (BuildConfig.DEBUG) Log.DEBUG else Log.INFO)

        GlobalRum.registerIfAbsent(RumMonitor.Builder().build())
        GlobalTracer.registerIfAbsent(createTracer(...))
    }
}

Error log looks like this:

Datadog  E  Datadog has not been initialized.
         E  Please add the following code in your application's onCreate() method: 
         ...

Adding an artificial Thread.sleep() gives the SDK time to fully initialize so the secondary configuration calls don't trigger the error log (but that's obviously not ideal)

Describe the solution you'd like
A callback that's triggered when the SDK is initialized:

Datadog.initialize(some, params, here, listener)

where listener type is something like this:

interface SDKListener {
    fun onSDKInitialized()
}

Describe alternatives you've considered
Polling and constantly checking Datadog.isInitialized() (not ideal)

Additional context
N/A

Add additional attributes on network interceptor

Are you requesting automatic instrumentation for a framework or library? Please describe.
I'm requesting for the DatadogInterceptor

Is your feature request related to a problem? Please describe.
Need additional information from the network traces.

Describe the solution you'd like
I would like to add additional attributes to the network interceptor.
Specifically: deviceId, userId, build number, build name, build type

Describe alternatives you've considered
I can manually log the calls outside the interceptor.

Additional context
Will probably be looking at flutter in the near future - do you have a direct flutter plugin?

Dependency clash while trying to implement datadog sdk v1.7.0

Describe what happened
After including datadog SDK in the project, there are dependency clashes that exist for androidx namespace, namely for the following dependencies:

cv: Compile version, rv: Runtime version

androidx.fragment:fragment (cv:1.1.0, rv:1.2.4)
androidx.activity:activity (cv:1.0.0, rv:1.1.0)
androidx.core:core (cv:1.1.0, rv:1.3.1)
androidx.lifecycle:lifecycle-service (cv:2.0.0, rv:2.1.0)

To resolve this, manual gradle dependency resolution was done as follow:

subprojects {
        project.configurations.all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'androidx.activity'
                  && details.requested.name.contains('activity') ) {
                    details.useVersion "1.0.0"
                }
            }
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'androidx.fragment'
                  && details.requested.name.contains('fragment') ) {
                    details.useVersion "1.1.0"
                }
            }
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'androidx.lifecycle'
                  && details.requested.name.contains('lifecycle-service') ) {
                    details.useVersion "2.0.0"
                }
            }
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'androidx.core'
                  && details.requested.name.contains('core') ) {
                    details.useVersion "1.1.0"
                }
            }
        }
    }

Running .gradlew :app:installDebug --scan leads to a crash with the following crashlog:

> Task :app:transformClassesWithDexBuilderForDebug
com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process <PACKAGE_NAME>/app/build/intermediates/transforms/FirebasePerformancePlugin/debug/145
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
	at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
	at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
	at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.transform(DexArchiveBuilderTransform.java:405)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:239)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:235)
	at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
	at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)
	at sun.reflect.GeneratedMethodAccessor992.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
	at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
	at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:273)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:258)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process <PACKAGE_NAME>/app/build/intermediates/transforms/FirebasePerformancePlugin/debug/145
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.launchProcessing(DexArchiveBuilderTransform.java:900)
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.lambda$convertToDexArchive$6(DexArchiveBuilderTransform.java:825)
	at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: com.android.builder.dexing.DexArchiveBuilderException: Error while dexing.
	at com.android.builder.dexing.D8DexArchiveBuilder.getExceptionToRethrow(D8DexArchiveBuilder.java:124)
	at com.android.builder.dexing.D8DexArchiveBuilder.convert(D8DexArchiveBuilder.java:101)
	at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.launchProcessing(DexArchiveBuilderTransform.java:895)
	... 6 more
Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete
	at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:65)
	at com.android.tools.r8.utils.ExceptionUtils.withD8CompilationHandler(ExceptionUtils.java:43)
	at com.android.tools.r8.D8.run(D8.java:90)
	at com.android.builder.dexing.D8DexArchiveBuilder.convert(D8DexArchiveBuilder.java:99)
	... 7 more
Caused by: com.android.tools.r8.utils.AbortException: Error: <PACKAGE_NAME>/app/build/intermediates/transforms/FirebasePerformancePlugin/debug/145/META-INF/versions/9/module-info.class, Illegal class file: Class module-info is missing a super type. Class file version 53.
	at com.android.tools.r8.utils.Reporter.failIfPendingErrors(Reporter.java:116)
	at com.android.tools.r8.utils.Reporter.fatalError(Reporter.java:74)
	at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:59)
	... 10 more


> Task :app:transformClassesWithDexBuilderForDebug FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> com.android.build.api.transform.TransformException: com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process <PACKAGE_NAME>/app/build/intermediates/transforms/FirebasePerformancePlugin/debug/145

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 28s
289 actionable tasks: 9 executed, 280 up-to-date

Could this be an issue between FirebasePerformacePlugin and datadog SDK?

Steps to reproduce the issue:

  1. Added datadog SDK maven repo in project's build.gradle.kts.
  2. Added datadog dependency implementation "com.datadoghq:dd-sdk-android:1.7.0" to app's build.gradle.kts.
  3. Setup datadog in Application Class onCreate() as follow:

CLIENT_TOKEN, ENV_NAME, and APP_ID redacted.

DatadogConfig datadogConfig = new DatadogConfig.Builder(
      "CLIENT_TOKEN",
      "<ENV_NAME>",
      "<APP_ID>"
    )
      .trackInteractions()
      .setTracesEnabled(true)
      .setRumEnabled(true)
      .useViewTrackingStrategy(new FragmentViewTrackingStrategy(true))
      .build();

    Datadog.initialize(this, TrackingConsent.GRANTED, datadogConfig);

    RumMonitor datadogRumMonitor = new RumMonitor.Builder()
      .sampleRumSessions(100.0f)
      .build();
    GlobalRum.registerIfAbsent(datadogRumMonitor);
  1. Build the project.

Describe what you expected:
Expected the project to build without any dependency conflicts.

Additional context

  • Android OS version: 10

  • Device Model: Samsung galaxy S10

  • Datadog SDK version: 1.7.0

  • retrofit: 2.7.1 (not using DatadogInterceptor())

  • Proguard configuration: default

  • Android Gradle plugin: 3.2.0

  • Kotlin Gradle plugin: 1.3.61

  • Google Services plugin: 3.1.1

  • Firebase Crashlytics plugin: 2.3.0

  • Firebase Performance plugin: 1.3.1

PS: I am trying to upgrade the dependencies to their latest versions, especially the ones with androidx and firebase. I will keep the issue posted with the findings.

1.3.0 Release: App build failed for devices with Android API less than 26

Describe what happened
With com.datadoghq:dd-sdk-android:1.3.0 app build failed with next error:

image

Error: C:\Users\Kirill\.gradle\caches\transforms-2\files-2.1\d6c780953302a96e24317c3588620170\jetified-disruptor-3.4.2.jar:com/lmax/disruptor/util/ThreadHints.class, void com.lmax.disruptor.util.ThreadHints.onSpinWait(), MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)

When I switched back to "com.datadoghq:dd-sdk-android:1.2.2" it works.

Steps to reproduce the issue:

  • Use implementation "com.datadoghq:dd-sdk-android:1.3.0" for your project
  • Create an emulator or connect a device with Android API less than 26
  • Try to "Run" the app

Describe what you expected:

  • The app should be worked

Additional context

  • Android OS version: Android 5.1.1
  • Device Model: Samsung SM-J320FN
  • Datadog SDK version: 1.3.0
  • Versions of any other relevant dependencies (OkHttp, …):
   implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
   implementation 'androidx.appcompat:appcompat:1.1.0'
   implementation 'androidx.core:core-ktx:1.3.0-alpha01'
   implementation 'com.google.android.material:material:1.1.0'
   implementation 'com.airbnb.android:lottie:3.0.0-beta1'
   implementation 'com.hbb20:ccp:2.2.4'
   implementation 'androidx.annotation:annotation:1.1.0'
   implementation 'com.yuyakaido.android:card-stack-view:2.3.4'
   implementation 'com.android.volley:volley:1.1.1'
   implementation 'com.squareup.moshi:moshi:1.9.2'
   implementation 'com.j256.ormlite:ormlite-android:4.46'
   implementation 'com.rvalerio:fgchecker:1.1.0'
   implementation 'com.google.code.gson:gson:2.8.6'
   implementation 'com.squareup.retrofit2:retrofit:2.5.0'
   implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
   implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
   implementation 'com.squareup.okhttp3:logging-interceptor:3.14.0'
   implementation 'com.squareup.okhttp3:okhttp:3.14.0'
   implementation 'io.reactivex.rxjava2:rxjava:2.2.11'
   implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
   implementation 'com.orhanobut:hawk:2.0.1'
   implementation 'com.scottyab:rootbeer-lib:0.0.7'
   implementation 'com.github.stfalcon:stfalcon-imageviewer:1.0.0'
   implementation 'com.squareup.picasso:picasso:2.71828'
   implementation 'com.facebook.android:facebook-login:5.1.1'
   implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
   implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
   implementation "com.datadoghq:dd-sdk-android:1.2.2"
   implementation "androidx.biometric:biometric:1.0.1"
   implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
   implementation "com.github.YarikSOffice:lingver:1.2.0"
   implementation 'com.google.firebase:firebase-analytics:17.2.2'
   implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta01'
   implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
  • Proguard configuration: empty

  • Gradle Plugins: 3.6.1

One notice: I didn't add this lines of code for build.gradle(:app):
{ exclude group: "com.google.guava", module: "listenablefuture" } as I am getting another error:
Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method com.datadoghq:dd-sdk-android:1.3.0() for arguments [build_51j9qrhttyw5g4zdn6hs7qdap$_run_closure3$_closure20@2bd02ded] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

So, my implementation of datadog looks next:
image

groupId for dd-sdk-android in dd-sdk-android-timber POM is wrong

Thanks for taking the time for reporting an issue!

Describe what happened
Include any error message or stack trace if available.

Surfacing this up here for visibility since #138 was closed. This is a follow-up to that issue (#138 (comment)).

Steps to reproduce the issue:

Describe what you expected:

Additional context

  • Android OS version:
  • Device Model:
  • Datadog SDK version:
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
  • Gradle Plugins:

Network Error: Error when dispatching Datadog logs

Describe what happened
Include any error message or stack trace if available.
We have been seeing an issue related to his network for about 3 weeks. When running the project, the android sdk is not logging properly to the dashboard. This is the error we're seeing:

3139/com.cfa.openpos.sppayment E/Datadog: Unable to send batch [80681 bytes] (LogsOkHttpUploader) because of a network error; we will retry later.

I've attached the full logs here:
DDLoggingDevTerm_2_5.txt

Steps to reproduce the issue:
Only one of our team members has been seeing this and can reproduce it on their network. A router reboot fixes the issue but after a few hours the sdk will stop reporting logs again.

Additional context

  • Android OS version: Running android sdk 29 on app, android version 6.0 on device
  • Device Model: Pax A60 & A77
  • Datadog SDK version: 1.7.1
  • Versions of any other relevant dependencies (OkHttp, …): okhttp 4.4.0
  • Proguard configuration:
  • Gradle Plugins:

Stacktrace deobfuscation

Do you support stack trace deobfuscation in the Datadog console? If yes, where should I upload the mapping file? If no, would you consider adding this(logging exceptions in the app that has R8 enabled is not very useful)?

Log class names in Logcat

When Logcat is enabled, every message is tagged with the service name. When using Timber's vanilla Timber.DebugTree, it tags every message with the class the log came from. This is more useful to tell where the log came from when debugging.

It could be helpful to make a subclass of Timber.DebugTree which could pass tags from Timber to the datadog logger.

dd-sdk-android-timber requires dd-sdk-android:1.2.1

Thanks for taking the time for reporting an issue!

Describe what happened
Include any error message or stack trace if available.

In trying to include dd-sdk-android-timber as a dependency, resolution fails because it cannot find dd-sdk-android:1.2.1. Looking at the POM file for dd-sdk-android-timber, it appears that it requires 1.2.1 as a dependency (https://dl.bintray.com/datadog/datadog-maven/com/datadoghq/dd-sdk-android-timber/), but that does not exist. I believe it should be 1.2.0.

Error message:

ERROR: Failed to resolve: dd-sdk-android:dd-sdk-android:1.2.1

Steps to reproduce the issue:
Add this to your build.gradle and perform a Gradle sync:

repositories {
    maven { url “https://dl.bintray.com/datadog/datadog-maven" }
}

dependencies {
    implementation "com.datadoghq:dd-sdk-android:1.2.0"
    implementation "com.datadoghq:dd-sdk-android-timber:1.2.0"
}

Describe what you expected:
Expected Gradle dependency resolution to complete successfully.

Additional context

  • Android OS version:
  • Device Model:
  • Datadog SDK version:
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
  • Gradle Plugins:

OpenTracing message field gets overridden by default "Span event" message in some cases

Describe what happened
In a log event that's attached to a span in a trace, when I set the OpenTracing message field Fields.MESSAGE and also set Fields.EVENT and Fields.ERROR_KIND, the Fields.MESSAGE value gets overridden with the default "Span event" message. When I only set Fields.MESSAGE and did not set Fields.EVENT and Fields.ERROR_KIND, the message was properly set.

Steps to reproduce the issue:

Message DOES NOT get set with the following:

HashMap propertiesWithOpenTracingInfo = properties.toHashMap();
propertiesWithOpenTracingInfo.put(Fields.EVENT, "error");
propertiesWithOpenTracingInfo.put(Fields.ERROR_KIND, errorKind);
propertiesWithOpenTracingInfo.put(Fields.MESSAGE, message);
span.log(propertiesWithOpenTracingInfo);

Message IS correctly set with the following:

HashMap propertiesWithOpenTracingInfo = properties.toHashMap();
propertiesWithOpenTracingInfo.put(Fields.MESSAGE, message);
span.log(propertiesWithOpenTracingInfo);

Describe what you expected:

On DataDog's website in Log Explorer, the message should be the message that I passed, i.e. network request error. But it is replaced with Span event, but only when I set other fields, i.e. in order to mark it as an error log.

Additional context

  • Android OS version: 11
  • Device Model: Samsung Galaxy S20
  • Datadog SDK version: 1.7.1
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
  • Gradle Plugins:

Support of newer okHttp versions

Describe what happened
If I use a newer SDK version than 1.1.1, it is not possible for me to use a current version of OkHttp. During the initialisation of Datadog the following error occurs:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.datadogtestapp, PID: 8047
    java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; in class Ljava/lang/invoke/LambdaMetafactory; or its super classes (declaration of 'java.lang.invoke.LambdaMetafactory' appears in /apex/com.android.art/javalib/core-oj.jar)
        at okhttp3.CipherSuite.<clinit>(CipherSuite.java:49)
        at okhttp3.ConnectionSpec.<clinit>(ConnectionSpec.java:51)
        at com.datadog.android.Datadog.buildOkHttpClient(Datadog.kt:267)
        at com.datadog.android.Datadog.setupLogsUploader(Datadog.kt:300)
        at com.datadog.android.Datadog.initialize(Datadog.kt:134)
        at com.example.datadogtestapp.ItemListActivity.onCreate(ItemListActivity.kt:27)
        at android.app.Activity.performCreate(Activity.java:7990)
        at android.app.Activity.performCreate(Activity.java:7979)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3477)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:216)
        at android.app.ActivityThread.main(ActivityThread.java:7464)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)

This behaviour might be caused by the downgrade of OkHttp in the DD SDK version 1.2.0

Steps to reproduce the issue:

  • Add the following dependencies:
    implementation 'com.squareup.okhttp3:okhttp:3.14.0' (newer version than 3.12.10)
    implementation 'com.datadoghq:dd-sdk-android:1.3.0' (newer version than 1.1.1)
  • Add "Datadog.initialize" statement to your code and try to run the app

Describe what you expected:
I expected to be able to use newer OkHttp versions than OkHttp 3.12.10. Is it possible to support those SDKs in future versions again or is there a secure way to work around this conflict?

Additional context

  • Android OS version: 8.1
  • Device Model: Nexus 5X
  • Datadog SDK version: 1.3.0
  • other dependencies:
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.0'
implementation 'com.datadoghq:dd-sdk-android:1.3.0'
  • Proguard configuration:
  • Gradle Plugins:

[Question] How to correctly identify users in RUM Sessions

The javascript docs are pretty clear about the correct way to set the user context, by calling the setUser function. What's the correct way to do this using the android sdk? Should I use those same properties (usr.id, usr.name, usr.email), and call GlobalRum.addAttribute(...)?

If so, it would be great to update the docs.

App crash on RUM

Fatal Exception: java.lang.IllegalArgumentException
Parameter specified as non-null is null: method z.i.a.o.f.c.c.g.onMenuOpened, parameter p1
com.datadog.android.rum.internal.instrumentation.gestures.WindowCallbackWrapper.onMenuOpened
com.datadog.android.rum.internal.instrumentation.gestures.WindowCallbackWrapper.onMenuOpened (WindowCallbackWrapper.java:2)
androidx.appcompat.view.WindowCallbackWrapper.onMenuOpened (WindowCallbackWrapper.java:104)
androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.onMenuOpened (AppCompatDelegateImpl.java:2868)
androidx.appcompat.view.WindowCallbackWrapper.onMenuOpened (WindowCallbackWrapper.java:104)
androidx.appcompat.app.ToolbarActionBar$ActionMenuPresenterCallback.onOpenSubMenu (ToolbarActionBar.java:560)
androidx.appcompat.view.menu.BaseMenuPresenter.onSubMenuSelected (BaseMenuPresenter.java:221)
androidx.appcompat.widget.ActionMenuPresenter.showOverflowMenu (ActionMenuPresenter.java:345)
androidx.appcompat.widget.ActionMenuPresenter$OverflowMenuButton.performClick (ActionMenuPresenter.java:681)
android.view.View.performClickInternal (View.java:8147)
android.view.View.access$3700 (View.java:888)
android.view.View$PerformClick.run (View.java:30233)
android.os.Handler.handleCallback (Handler.java:938)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:246)
android.app.ActivityThread.main (ActivityThread.java:8414)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:596)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1130)
  • Android OS version:11
  • Device Model:Galaxy S20+
  • Datadog SDK version:1.6.1

Crash

Describe what happened

From crashlytics there are multiple instances of crashes

Fatal Exception: java.lang.InternalError Thread starting during runtime shutdown 
  | java.lang.Thread.nativeCreate (Thread.java)
  | java.lang.Thread.start + 733 (Thread.java:733)
  | okio.AsyncTimeout.scheduleTimeout + 88 (AsyncTimeout.java:88)
  | okio.AsyncTimeout.enter + 80 (AsyncTimeout.java:80)
  | okhttp3.RealCall.execute + 88 (RealCall.java:88)
  | com.datadog.android.core.internal.net.DataOkHttpUploader.upload + 47 (DataOkHttpUploader.kt:47)
  | com.datadog.android.core.internal.data.upload.DataUploadRunnable.consumeBatch + 75 (DataUploadRunnable.kt:75)
  | com.datadog.android.core.internal.data.upload.DataUploadRunnable.run + 39 (DataUploadRunnable.kt:39)
  | android.os.Handler.handleCallback + 790 (Handler.java:790)
  | android.os.HandlerThread.run + 65 (HandlerThread.java:65)

Steps to reproduce the issue:
Hard to reproduce, I kept running my app doing what app does and it crashes at some point

Describe what you expected:
I have recently integrated this into my app, largely java based code. I followed the steps and I think I did not miss anything but please let me know if I did.

Additional context
Out of 115 crashes
Devices
samsung49%
LGE23%
motorola11%
ZTE10%
Other…7%
Operating Systems
7 57%
9 23%
10 12%
8 8%

  • Datadog SDK version: 1.2.1
  • okhttp:3.12.0
  • retrofit2:retrofit:2.2.0
  • Proguard configuration:
    implementation ('com.datadoghq:dd-sdk-android:1.2.1') {
    exclude group: 'com.google.guava', module: 'listenablefuture'
    }

Out of memory crash

Describe what happened

Fatal Exception: java.lang.OutOfMemoryError
Failed to allocate a 32784 byte allocation with 23056 free bytes and 22KB until OOM, target footprint 268435456, growth limit 268435456

java.util.HashMap.resize + 703 (HashMap.java:703)
--
  | java.util.LinkedHashSet.<init> + 169 (LinkedHashSet.java:169)
  | kotlin.collections.CollectionsKt___CollectionsKt.toMutableSet + 1452 (_Collections.kt:1452)
  | kotlin.collections.CollectionsKt___CollectionsKt.union + 1467 (_Collections.kt:1467)
  | com.datadog.android.core.internal.data.file.FileReader.readNextFile + 70 (FileReader.kt:70)
  | com.datadog.android.core.internal.data.file.FileReader.readNextBatch + 29 (FileReader.kt:29)
  | com.datadog.android.core.internal.data.upload.DataUploadRunnable.run + 36 (DataUploadRunnable.kt:36)
  | android.os.Handler.handleCallback + 883 (Handler.java:883)
  | android.os.HandlerThread.run + 67 (HandlerThread.java:67)

Steps to reproduce the issue:
No known steps

Describe what you expected:
App would not crash at least

Additional context
13 instances of this so far and success rate is 99+% so this is hard to reproduce
samsung 100%

Operating Systems
10 54%
7 23%
9 23%

  • Datadog SDK version:1.2.1

Feature: Add support for sending metrics

Is your feature request related to a problem? Please describe.
Datadog has an HTTP API for posting metrics to Datadog, and I've noticed that this SDK only supports sending logs. Is there plans to add support for Metrics to be sent from mobile?

Describe alternatives you've considered
I guess Metrics could be replaced with Logs by adding the metric value as an attribute to the log message, but then it's a bit trickier to visualize the metric in the same way a standard metric can be visualized.

Remove dependency on navigation-ui-ktx from the SDK?

Describe what happened
After adding the Datadog SDK (com.datadoghq:dd-sdk-android) to my app, I noticed that the app size increased by more than I expected.

Steps to reproduce the issue:
Add the Datadog SDK to an app which doesn't depend on the navigation architecture component.

implementation 'com.datadoghq:dd-sdk-android:1.5.2'

Describe what you expected:
I expected fewer transitive dependencies to be brought in, so that the app size wouldn't increase as much.

These dependencies were brought in, even though they don't appear to be used by the Datadog SDK:

  • androidx.navigation:navigation-ui-ktx
  • androidx.navigation:navigation-ui

Additional context

  • Datadog SDK version: 1.5.2

R8 is being run on the app, so the increase in size in this case was more from the resources being brought in from androidx.navigation:navigation-ui.


Looking at the code in this repo, it seems like the navigation dependencies are being brought in from 1 and 2.

I'm guessing that AndroidXNavigation includes the navigation-ui-ktx since it might be used in the sample app, but it doesn't seem to be needed by the SDK that gets released.

On the other hand, removing this transitive dependency could be considered a breaking change if people were relying on the Datadog SDK to bring it in. But I hope that this isn't the case.

RUM dashboard is empty

Thanks for taking the time for reporting an issue!

Describe what happened
No data appears on RUM dashboard

Steps to reproduce the issue:

  1. Run app, click around
  2. Open RUM dashboard

Describe what you expected:
Events, logs and collected data

Additional context

  • Android OS version: 5.1.1, 10, 11
  • Device Model: Samsung J3, Xiaomi Mi3, Android Emulator
  • Datadog SDK version: 1.8.1
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
#models
-keep class **.models.** { *; }
-keepclassmembers enum * { *; }

# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp3.** { *; }
-keep interface com.squareup.okhttp3.** { *; }
-dontwarn com.squareup.okhttp3.**

#rxjava
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
    long producerIndex;
    long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
-dontwarn sun.misc.Unsafe

#start gson
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#end of gson

#jobqueue
-keep class com.birbit.android.jobqueue { *; }
-dontwarn com.birbit.android.jobqueue.**

#okio
-dontwarn okio.**

#retrofit2
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

-keepclasseswithmembers class * { @retrofit2.http.* <methods>; }

#greenrobot eventbus
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

#lombok
-dontwarn lombok.**

#jackson
-keepattributes *Annotation*,EnclosingMethod,Signature
-keepnames class com.fasterxml.jackson.** { *; }
-dontwarn com.fasterxml.jackson.databind.**
-keep class org.codehaus.** { *; }
-keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility {
public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; }

#pubnub
-keep class com.pubnub.api.models.** { *; }

#debug
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

#twilio
-keep class com.twilio.** { *; }
-keep class tvo.webrtc.** { *; }
-dontwarn tvo.webrtc.**
-keep class com.twilio.voice.** { *; }
-keepattributes InnerClasses

#see ProgressRequestBody
-keep class okio.RealBufferedSink

plus standard android proguard.

  • Gradle Plugins:

com.android.application
kotlin-android
kotlin-parcelize
kotlin-kapt
com.google.firebase.crashlytics
com.getkeepsafe.dexcount
de.mannodermaus.android-junit5
com.github.triplet.play
com.google.firebase.appdistribution

here's my initialization code:

  private fun initializeDatadog() {
        val configuration = Configuration.Builder(logsEnabled = true, tracesEnabled = true,
                crashReportsEnabled = true, rumEnabled = true)
                .setFirstPartyHosts(listOf("twiagemed.net"))
                .useViewTrackingStrategy(MixedViewTrackingStrategy(trackExtras = true))
                .trackInteractions()
                .build()

        val credentials = Credentials(
                clientToken = BuildConfig.DATADOG_CLIENT_TOKEN,
                envName = BuildConfig.FLAVOR,
                variant = BuildConfig.FLAVOR,
                rumApplicationId = BuildConfig.DATADOG_APP_ID
        )
        Datadog.initialize(this, credentials, configuration, TrackingConsent.GRANTED)
        GlobalTracer.registerIfAbsent(AndroidTracer.Builder().build())
        GlobalRum.registerIfAbsent(RumMonitor.Builder().build())
        Datadog.setVerbosity(Log.VERBOSE)
    }

RumMonitor.Builder.sampleRumSessions is missing

Describe what happened
The sampleRumSessions method from RumMonitor.Builder is missing

Steps to reproduce the issue:
try to create a RumMonitor object thru the builder:

val monitor = RumMonitor.Builder()
        .sampleRumSessions(75.0f)
        .build()

Describe what you expected:
The method should be available

Additional context

  • Datadog SDK version: 1.5.2

Failed to resolve: com.datadoghq:dd-sdk-android:1.6.1

Thanks for taking the time for reporting an issue!

Describe what happened
Gradle unnable to resolve dependency implementation on Android Java project:
Failed to resolve: com.datadoghq:dd-sdk-android:1.6.1

Steps to reproduce the issue:
Added maven { url 'https://dl.bintray.com/datadog/datadog-maven' } to my repositories in my gradle file and
implementation 'com.datadoghq:dd-sdk-android:1.6.1' to my dependencies

Describe what you expected:
Should have imported the dee

Additional context

  • Datadog SDK version:
    1.6.1
  • Gradle Plugins
    apply plugin: 'com.google.gms.google-services'
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.firebase.firebase-perf'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'com.google.firebase.crashlytics'

Dependency cannot be resolved

Thanks for taking the time for reporting an issue!

Describe what happened
ERROR: Failed to resolve: com.datadoghq:dd-sdk-android:1.2.0

Steps to reproduce the issue:
Include datadog android library as dependency

Describe what you expected:
Dependency should have worked

Additional context
Not there yet

Improve data usage by reusing Http connections

Is your feature request related to a problem? Please describe.
Network data usage is critical for our business and currently, Datadog library is using the biggest number of data from all the libs that we use and our own service as well (around ~10 times more)

Describe the solution you'd like
While inspecting the network requests I noticed that Datadog is not reusing HTTP connections (~30-40% are new). This means it needs to make a TLS handshake that takes a significant amount of data. Take a look at the screenshots below (this were two consecutive requests). Notice the total data used.

1 2
Zrzut ekranu 2020-10-1 o 10 19 32 Zrzut ekranu 2020-10-1 o 10 19 53

This profiling was done when the app was in the background and still, the DD was doing ~2 requests per minute. The app I'm working on is turned on 24/7 so if we count that 30% request created a new connection this gives us ~17MB extra data per day.

Possible solutions:

  1. Reuse the HTTP connections
  2. Improve the number of requests made in the background. Ideally, make it configurable by the app.

Describe alternatives you've considered
Bumping up LogLevel
Leaving only critical logs (but at some point we might just as well use crashlytics only)

Additional context
This request is also valid for tracing and RUM

OkHttp interceptor doesn't see "known hosts" list when OkHttp is initialized before the SDK

Thanks for taking the time for reporting an issue!

Describe what happened
When OkHttp is initialized before the DD SDK and one of the TracingInterceptors is used, any "known hosts" set in the SDK Configuration aren't picked up by the interceptor(s) and those requests ultimately aren't traced in APM. This happens with the newer, non-deprecated Interceptor constructors that don't take in a list of known hosts (e.g. here).

Steps to reproduce the issue:
I've modified the sample app in my own fork to reproduce this issue (commit here):

  • Create an OkHttpClient with a TracedRequestListener and no known hosts provided.
  • Set known hosts in the DD SDK Configuration
  • Initialize the OkHttpClient before the DD SDK
  • Add the expected hostname as a known host (e.g. "unsplash.com" in this case)
  • Run the sample, go to the image loader and choose Picasso as the load type
  • Load image; If you debug within TracingInterceptor you'll notice that tracing is not enabled and FirstPartyHostDetector.knownHosts is empty

This can be avoided by using the deprecated Interceptor constructor(s) that take in the list of known hosts when constructing the OkHttpClient, but I'd rather not rely on deprecated functionality if it will be removed in the future.
EDIT: This doesn't seem to work any more with v1.8.0 🤔 however, providing the known hosts into the Interceptor used to work in prior SDK versions.

Describe what you expected:

  • I expect to be able to construct my OkHttpClient earlier than the DD SDK and still have APM/RUM tracing work properly.
    • (we initialize OkHttp earlier than any of our dependencies since its used by almost everything).
  • If the DD SDK must be initialized first, I need an initialization callback to be notified when the SDK is finished initializing (see issue #511).
  • If neither of those are possible, should the old/deprecated Interceptor constructor become un-deprecated? What's the best path forward here?

Additional context

  • Android OS version: Android 11
  • Device Model: Galaxy S10
  • Datadog SDK version: 1.8.0
  • Versions of any other relevant dependencies (OkHttp, …): Whatever is set in the sample app
  • Proguard configuration: Whatever is set in the sample app
  • Gradle Plugins: Whatever is set in the sample app

App does not log when background service had been running

Thanks for taking the time for reporting an issue!

Describe what happened
When app is launched, logs are recorded. But if only background service had been running, logs are not recorded.

Steps to reproduce the issue:

  1. Initiate data dog in application (not activity) to make sure it should be initialized even when background service has started.
  2. Start background service with some intent, log few lines.
  3. Check data dog log explorer, do not launch app.
  4. If user launches app, logs are seen in log explorer on same build

Describe what you expected:
Logs were logged both the times

Please advise if

  1. I missed a setting (read through the document but could not find anything relevant).
  2. Perhaps initialization is missing setting up user id such that user can be uniquely identified, I am not sure there is mandatory call is missing

Additional context

  • Android OS version: tried on various OS
  • Device Model: Various device models
  • Datadog SDK version:1.2.1
  • Versions of any other relevant dependencies (OkHttp, …):
  • Proguard configuration:
  • Gradle Plugins:

Crash due to onClick event on an overflowMenu

Describe what happened
Application crashes on onOverflowMenu click event.

Crashlog:

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter p1
        at com.datadog.android.rum.internal.instrumentation.gestures.WindowCallbackWrapper.onMenuOpened(Unknown Source:2)
        at androidx.appcompat.view.WindowCallbackWrapper.onMenuOpened(WindowCallbackWrapper.java:104)
        at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.onMenuOpened(AppCompatDelegateImpl.java:2868)
        at com.uxcam.a.d.onMenuOpened(Unknown Source:2)
        at androidx.appcompat.app.AppCompatDelegateImpl$ActionMenuPresenterCallback.onOpenSubMenu(AppCompatDelegateImpl.java:2528)
        at androidx.appcompat.view.menu.BaseMenuPresenter.onSubMenuSelected(BaseMenuPresenter.java:221)
        at androidx.appcompat.widget.ActionMenuPresenter.showOverflowMenu(ActionMenuPresenter.java:345)
        at androidx.appcompat.widget.ActionMenuPresenter$OverflowMenuButton.performClick(ActionMenuPresenter.java:681)
        at android.view.View.performClickInternal(View.java:7831)
        at android.view.View.access$3600(View.java:879)
        at android.view.View$PerformClick.run(View.java:29359)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

Steps to reproduce the issue:
OnClick event on an overflow menu item.

Describe what you expected:
Datadog is this case is simply being used in the application to monitor app crashes and logging. Datadog reporting the view action event is not a concern in this case. However, it causing application to crash is alarming.

Additional context

  • Android OS version: 10
  • Device Model: galaxy S10
  • Datadog SDK version: 1.7.1
  • Proguard configuration: default config
  • Gradle Plugins:
        const val kotlinGradlePlugin = "1.3.61"
        const val androidGradlePlugin = "3.6.0"
        const val googleServicesPlugin = "3.1.1"
        const val realmPlugin = "4.3.2"
        const val firebaseCrashlyticsPlugin = "2.3.0"
        const val firebasePerformancePlugin = "1.3.1"

Can't force the tag "source" value

Describe what happened
Calling addTag("source", "android") on the Datadog logger doesn't override the default value used by the SDK.

On the iOS SDK, the default value is "ios" but on Android it's just "mobile".
It would be more appropriate to set it to "android" or to allow to override this value from the DatadogConfig or from the Logger.Builder

Steps to reproduce the issue:

Call addTag("source", "android") on a Datadog logger instance.

Describe what you expected:
The source tag can be overridden.

Additional context

  • Datadog SDK version: 1.4.1

Update documentation on EventMapper

Are you requesting automatic instrumentation for a framework or library? Please describe.
N/A

Is your feature request related to a problem? Please describe.
I'm on v1.8.0 using the new RUM EventMapper feature - it works great! However, my first implementation didn't work and RUM events were being dropped by the SDK, and it took me a little while to figure out why.

After debugging I noticed the behavior in RumEventMapper that automatically drops the event if its not the same object instance originally used. I assumed I could just freely copy the event object and return a new one, but it appears that the internal mapper expects the same object to be returned.

My EventMapper impl. looked something like this, with .copy() being used:

class MyEventMapper: EventMapper<ResourceEvent> {
    override fun map(event: ResourceEvent): ResourceEvent {
        event.copy(resource = event.resource.copy(url = myNewUrl(...)))
    }
}

Given that .copy() is commonly used on data classes like this, the behavior is a bit misleading.

Describe the solution you'd like
The docs mention that null is used to indicate a dropped event, but the "same instance" requirement isn't listed.
I'd recommend dropping the requirement that custom mappers return the same instance, but if that's not feasible then this seems like a good thing to call out explicitly in the docs.

Describe alternatives you've considered
N/A

Additional context
N/A

Clarification on RUM usage

When we plug in DataDog - RUM - we don't know what to put for trackingConsent.
Is this supposed to show a popup?
Does the sdk have a problem with debug builds?
Should we know NOT use this in production?
Do we have to plug in the OKHTTP3 interceptor for it to work?

fyi - @insubliminal

Prevent Multiple Calls To Initialize

I'm using Roboelectric for android unit tests. This calls Application#onCreate every test and has an unfortunate interaction with this library. It causes Datadog.initialize to be called multiple times. So every test in the suite fails.

I have a workaround by manually tracking whether it's initialized. However, it could be helpful to have a method like Datadog.isInitialized to tell whether Datadog.initialize can be called safely.

Or, a method like Datadog.setInTestMode. SoLoader (another library that I had issues with) uses this strategy and has SoLoader.setInTestMode. I think the idea with this is you can call it in the test runner instead of modifying the Application.

The error:

java.lang.IllegalStateException: Datadog has already been initialized.
	at com.datadog.android.Datadog.initialize(Datadog.kt:94)
	at com.datadog.android.Datadog.initialize$default(Datadog.kt:92)
	at com.datadog.android.Datadog.initialize(Datadog.kt)
	at com.aapmobileedb.MainApplication.onCreate(MainApplication.java:62)
	at org.robolectric.android.internal.AndroidTestEnvironment.lambda$installAndCreateApplication$0(AndroidTestEnvironment.java:276)
	at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:75)
	at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:276)
	at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:169)
	at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301)
	at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:243)
	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.