Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import com.onesignal.core.internal.http.OneSignalService
import com.onesignal.debug.internal.logging.Logging
import com.onesignal.otel.IOtelPlatformProvider

// Use this to enable/disable the Otel exporter logging in debug builds.
internal const val OTEL_EXPORTER_LOGGING_ENABLED = false

/**
* Configuration for AndroidOtelPlatformProvider.
*/
Expand All @@ -18,6 +21,7 @@ internal data class OtelPlatformProviderConfig(
val appVersion: String,
val context: Context? = null,
val getIsInForeground: (() -> Boolean?)? = null,
val isOtelExporterLoggingEnabled: Boolean,
)

/**
Expand Down Expand Up @@ -135,6 +139,8 @@ internal class OtelPlatformProvider(
}
}

override val isOtelExporterLoggingEnabled: Boolean = OTEL_EXPORTER_LOGGING_ENABLED
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does isOtelExporterLoggingEnabled get set to true?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we set it manually whenever we want to debug in our local test env.


override val appIdForHeaders: String
get() = appId ?: ""

Expand All @@ -159,6 +165,7 @@ internal fun createAndroidOtelPlatformProvider(
appPackageId = context.packageName,
appVersion = com.onesignal.common.AndroidUtils.getAppVersion(context) ?: "unknown",
context = context,
isOtelExporterLoggingEnabled = OTEL_EXPORTER_LOGGING_ENABLED,
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ interface IOtelPlatformProvider {
* Valid values: "NONE", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"
*/
val remoteLogLevel: String?

/**
* Debug-only toggle for local exporter diagnostics.
* When true, Otel exporter request/response success/failure logs are emitted to logcat.
*/
val isOtelExporterLoggingEnabled: Boolean

val appIdForHeaders: String

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,19 @@ internal class OneSignalOpenTelemetryRemote(

val extraHttpHeaders: Map<String, String> by lazy {
mapOf(
"X-OneSignal-App-Id" to appId,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need app_id in header anymore because it's already captured elsewhere right

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats right

"X-OneSignal-SDK-Version" to platformProvider.sdkBaseVersion,
"SDK-Version" to "onesignal/${platformProvider.sdkBase}/${platformProvider.sdkBaseVersion}",
)
}

private val apiBaseUrl: String get() = platformProvider.apiBaseUrl

override val logExporter by lazy {
OtelConfigRemoteOneSignal.HttpRecordBatchExporter.create(extraHttpHeaders, appId, apiBaseUrl)
OtelConfigRemoteOneSignal.HttpRecordBatchExporter.create(
extraHttpHeaders,
appId,
apiBaseUrl,
platformProvider.isOtelExporterLoggingEnabled,
)
}

override fun getSdkInstance(attributes: Map<String, String>): OpenTelemetrySdk =
Expand All @@ -123,6 +127,7 @@ internal class OneSignalOpenTelemetryRemote(
extraHttpHeaders,
appId,
apiBaseUrl,
platformProvider.isOtelExporterLoggingEnabled,
)
).build()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.onesignal.otel.config

import android.util.Log
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter
import io.opentelemetry.sdk.common.CompletableResultCode
import io.opentelemetry.sdk.logs.SdkLoggerProvider
import io.opentelemetry.sdk.logs.data.LogRecordData
import io.opentelemetry.sdk.logs.export.LogRecordExporter
import java.time.Duration

Expand Down Expand Up @@ -35,23 +38,74 @@ internal class OtelConfigRemoteOneSignal {
extraHttpHeaders: Map<String, String>,
appId: String,
apiBaseUrl: String,
enableExporterLogging: Boolean
): SdkLoggerProvider =
SdkLoggerProvider
.builder()
.setResource(resource)
.addLogRecordProcessor(
OtelConfigShared.LogRecordProcessorConfig.batchLogRecordProcessor(
HttpRecordBatchExporter.create(extraHttpHeaders, appId, apiBaseUrl)
HttpRecordBatchExporter.create(
extraHttpHeaders,
appId,
apiBaseUrl,
enableExporterLogging,
)
)
).setLogLimits(OtelConfigShared.LogLimitsConfig::logLimits)
.build()
}

object HttpRecordBatchExporter {
fun create(extraHttpHeaders: Map<String, String>, appId: String, apiBaseUrl: String) =
LogRecordExporterConfig.otlpHttpLogRecordExporter(
extraHttpHeaders,
buildEndpoint(apiBaseUrl, appId)
)
fun create(
extraHttpHeaders: Map<String, String>,
appId: String,
apiBaseUrl: String,
enableExporterLogging: Boolean,
): LogRecordExporter {
val exporter =
LogRecordExporterConfig.otlpHttpLogRecordExporter(
extraHttpHeaders,
buildEndpoint(apiBaseUrl, appId)
)

return if (enableExporterLogging) {
ExporterLoggingConfig.loggingExporter(exporter)
} else {
exporter
}
}
}

object ExporterLoggingConfig {
private const val TAG = "OneSignalOtel"

fun loggingExporter(delegate: LogRecordExporter): LogRecordExporter = LoggingLogRecordExporter(delegate)

private class LoggingLogRecordExporter(
private val delegate: LogRecordExporter
) : LogRecordExporter {
override fun export(logs: Collection<LogRecordData>): CompletableResultCode {
Log.d(TAG, "OTEL export request sent to backend. count=${logs.size}")
val result = delegate.export(logs)
result.whenComplete {
if (result.isSuccess) {
Log.d(TAG, "OTEL export response received: success")
} else {
val throwable = result.failureThrowable
Log.e(
TAG,
"OTEL export response received: failed${throwable?.let { " - ${it.message}" } ?: ""}",
throwable
)
}
}
return result
}

override fun flush(): CompletableResultCode = delegate.flush()

override fun shutdown(): CompletableResultCode = delegate.shutdown()
}
}
}
Loading