Skip to content

CallerSdkType added #6298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion firebase-dataconnect/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Unreleased
* [feature] Add ability to specify SerializersModule when serializing.
* [feature] initial beta release.
* [feature] Add ability to specify SerializersModule when serializing.
* [feature] CallerSdkType added, to enable tracking generated SDK usage.
21 changes: 15 additions & 6 deletions firebase-dataconnect/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,30 +66,37 @@ package com.google.firebase.dataconnect {
field @NonNull public static final com.google.firebase.dataconnect.FirebaseDataConnect.Companion Companion;
}

public enum FirebaseDataConnect.CallerSdkType {
method @NonNull public static com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType valueOf(@NonNull String name) throws java.lang.IllegalArgumentException;
method @NonNull public static com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType[] values();
enum_constant public static final com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType Base;
enum_constant public static final com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType Generated;
}

public static final class FirebaseDataConnect.Companion {
}

public static interface FirebaseDataConnect.MutationRefOptionsBuilder<Data, Variables> {
method @Nullable public com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType getCallerSdkType();
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
method @Nullable public com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables> getGeneratedMutation();
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
method public void setCallerSdkType(@Nullable com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType);
method public void setDataSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
method public void setGeneratedMutation(@Nullable com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables>);
method public void setVariablesSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
property @Nullable public abstract com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType callerSdkType;
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
property @Nullable public abstract com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables> generatedMutation;
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule variablesSerializersModule;
}

public static interface FirebaseDataConnect.QueryRefOptionsBuilder<Data, Variables> {
method @Nullable public com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType getCallerSdkType();
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
method @Nullable public com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables> getGeneratedQuery();
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
method public void setCallerSdkType(@Nullable com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType);
method public void setDataSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
method public void setGeneratedQuery(@Nullable com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables>);
method public void setVariablesSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
property @Nullable public abstract com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType callerSdkType;
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
property @Nullable public abstract com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables> generatedQuery;
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule variablesSerializersModule;
}

Expand Down Expand Up @@ -120,6 +127,7 @@ package com.google.firebase.dataconnect {
public interface OperationRef<Data, Variables> {
method public boolean equals(@Nullable Object other);
method @Nullable public suspend Object execute(@NonNull kotlin.coroutines.Continuation<? super com.google.firebase.dataconnect.OperationResult<Data,Variables>>);
method @NonNull public com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType getCallerSdkType();
method @NonNull public com.google.firebase.dataconnect.FirebaseDataConnect getDataConnect();
method @NonNull public kotlinx.serialization.DeserializationStrategy<Data> getDataDeserializer();
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
Expand All @@ -129,6 +137,7 @@ package com.google.firebase.dataconnect {
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
method public int hashCode();
method @NonNull public String toString();
property @NonNull public abstract com.google.firebase.dataconnect.FirebaseDataConnect.CallerSdkType callerSdkType;
property @NonNull public abstract com.google.firebase.dataconnect.FirebaseDataConnect dataConnect;
property @NonNull public abstract kotlinx.serialization.DeserializationStrategy<Data> dataDeserializer;
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import com.google.firebase.Firebase
import com.google.firebase.FirebaseApp
import com.google.firebase.app
import com.google.firebase.dataconnect.core.FirebaseDataConnectFactory
import com.google.firebase.dataconnect.generated.GeneratedMutation
import com.google.firebase.dataconnect.generated.GeneratedQuery
import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerializationStrategy
Expand Down Expand Up @@ -201,12 +199,11 @@ public interface FirebaseDataConnect : AutoCloseable {
public interface QueryRefOptionsBuilder<Data, Variables> {

/**
* The [GeneratedQuery] object that is creating the query; may be `null` if not being created
* from an SDK that was generated by the Data Connect toolkit. The value of this property does
* not affect the runtime behavior, but is used for runtime checks and gathering metrics on
* generated SDK usage.
* The calling SDK information to apply to all operations executed by the corresponding
* [QueryRef] object. May be `null` (the default) in which case [CallerSdkType.Base] will be
* used.
*/
public var generatedQuery: GeneratedQuery<*, Data, Variables>?
public var callerSdkType: CallerSdkType?

/**
* A [SerializersModule] to use when encoding the query's variables. May be `null` (the default)
Expand Down Expand Up @@ -242,12 +239,11 @@ public interface FirebaseDataConnect : AutoCloseable {
public interface MutationRefOptionsBuilder<Data, Variables> {

/**
* The [GeneratedMutation] object that is creating the mutation; may be `null` if not being
* created from an SDK that was generated by the Data Connect toolkit. The value of this
* property does not affect the runtime behavior, but is used for runtime checks and gathering
* metrics on generated SDK usage.
* The calling SDK information to apply to all operations executed by the corresponding
* [MutationRef] object. May be `null` (the default) in which case [CallerSdkType.Base] will be
* used.
*/
public var generatedMutation: GeneratedMutation<*, Data, Variables>?
public var callerSdkType: CallerSdkType?

/**
* A [SerializersModule] to use when encoding the mutation's variables. May be `null` (the
Expand All @@ -270,7 +266,7 @@ public interface FirebaseDataConnect : AutoCloseable {
* @param variablesSerializer The value for [MutationRef.variablesSerializer] of the returned
* object.
* @param optionsBuilder A method that will be called to provide optional information when
* creating the [MutationRef]; may be `null` (the default) to not perform any customization.
* creating the [QueryRef]; may be `null` (the default) to not perform any customization.
*/
public fun <Data, Variables> mutation(
operationName: String,
Expand Down Expand Up @@ -356,6 +352,26 @@ public interface FirebaseDataConnect : AutoCloseable {
*/
override fun toString(): String

/**
* Indicates where the usages of this object are coming from.
*
* This information is merely used for analytics and has no effects on the product's
* functionality.
*/
public enum class CallerSdkType {
/**
* The [FirebaseDataConnect] class is used directly in an application, rather than using the
* code generation done by the Firebase Data Connect toolkit.
*/
Base,

/**
* The [FirebaseDataConnect] class is used by code generated by the Firebase Data Connect
* toolkit.
*/
Generated,
}

/**
* The companion object for [FirebaseDataConnect], which provides extension methods and properties
* that may be accessed qualified by the class, rather than an instance of the class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ public interface OperationRef<Data, Variables> {
*/
public val variablesSerializer: SerializationStrategy<Variables>

/**
* The [FirebaseDataConnect.CallerSdkType] that will be associated with all operations performed
* by this object for analytics purposes.
*/
public val callerSdkType: FirebaseDataConnect.CallerSdkType

/**
* A [SerializersModule] to use when encoding the variables using [variablesSerializer]. May be
* `null`, to not use a [SerializersModule].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal class DataConnectGrpcClient(
requestId: String,
operationName: String,
variables: Struct,
isFromGeneratedSdk: Boolean,
callerSdkType: FirebaseDataConnect.CallerSdkType,
): OperationResult {
val request = executeQueryRequest {
this.name = requestName
Expand All @@ -67,7 +67,7 @@ internal class DataConnectGrpcClient(

val response =
grpcRPCs.retryOnGrpcUnauthenticatedError(requestId, "executeQuery") {
executeQuery(requestId, request, isFromGeneratedSdk)
executeQuery(requestId, request, callerSdkType)
}

return OperationResult(
Expand All @@ -80,7 +80,7 @@ internal class DataConnectGrpcClient(
requestId: String,
operationName: String,
variables: Struct,
isFromGeneratedSdk: Boolean,
callerSdkType: FirebaseDataConnect.CallerSdkType,
): OperationResult {
val request = executeMutationRequest {
this.name = requestName
Expand All @@ -90,7 +90,7 @@ internal class DataConnectGrpcClient(

val response =
grpcRPCs.retryOnGrpcUnauthenticatedError(requestId, "executeMutation") {
executeMutation(requestId, request, isFromGeneratedSdk = isFromGeneratedSdk)
executeMutation(requestId, request, callerSdkType)
}

return OperationResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.firebase.dataconnect.core
import android.os.Build
import com.google.firebase.FirebaseApp
import com.google.firebase.dataconnect.BuildConfig
import com.google.firebase.dataconnect.FirebaseDataConnect
import com.google.firebase.dataconnect.util.buildStructProto
import com.google.protobuf.Struct
import io.grpc.Metadata
Expand Down Expand Up @@ -53,25 +54,31 @@ internal class DataConnectGrpcMetadata(
@Suppress("SpellCheckingInspection")
private val googRequestParamsHeaderValue = "location=${connectorLocation}&frontend=data"

private fun googApiClientHeaderValue(isFromGeneratedSdk: Boolean): String {
private fun googApiClientHeaderValue(callerSdkType: FirebaseDataConnect.CallerSdkType): String {
val components = buildList {
add("gl-kotlin/$kotlinVersion")
add("gl-android/$androidVersion")
add("fire/$dataConnectSdkVersion")
add("grpc/$grpcVersion")
if (isFromGeneratedSdk) {
add("kotlin/gen")

when (callerSdkType) {
FirebaseDataConnect.CallerSdkType.Base -> {
/* nothing to add for Base */
}
FirebaseDataConnect.CallerSdkType.Generated -> {
add("kotlin/gen")
}
}
}
return components.joinToString(" ")
}

suspend fun get(requestId: String, isFromGeneratedSdk: Boolean): Metadata {
suspend fun get(requestId: String, callerSdkType: FirebaseDataConnect.CallerSdkType): Metadata {
val authToken = dataConnectAuth.getToken(requestId)
val appCheckToken = dataConnectAppCheck.getToken(requestId)
return Metadata().also {
it.put(googRequestParamsHeader, googRequestParamsHeaderValue)
it.put(googApiClientHeader, googApiClientHeaderValue(isFromGeneratedSdk))
it.put(googApiClientHeader, googApiClientHeaderValue(callerSdkType))
if (appId.isNotBlank()) {
it.put(gmpAppIdHeader, appId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.google.firebase.dataconnect.core

import android.content.Context
import com.google.android.gms.security.ProviderInstaller
import com.google.firebase.dataconnect.FirebaseDataConnect
import com.google.firebase.dataconnect.core.DataConnectGrpcMetadata.Companion.toStructProto
import com.google.firebase.dataconnect.util.SuspendingLazy
import com.google.firebase.dataconnect.util.buildStructProto
Expand Down Expand Up @@ -133,9 +134,9 @@ internal class DataConnectGrpcRPCs(
suspend fun executeMutation(
requestId: String,
request: ExecuteMutationRequest,
isFromGeneratedSdk: Boolean,
callerSdkType: FirebaseDataConnect.CallerSdkType,
): ExecuteMutationResponse {
val metadata = grpcMetadata.get(requestId, isFromGeneratedSdk)
val metadata = grpcMetadata.get(requestId, callerSdkType)
val kotlinMethodName = "executeMutation(${request.operationName})"

logger.logGrpcSending(
Expand Down Expand Up @@ -171,9 +172,9 @@ internal class DataConnectGrpcRPCs(
suspend fun executeQuery(
requestId: String,
request: ExecuteQueryRequest,
isFromGeneratedSdk: Boolean,
callerSdkType: FirebaseDataConnect.CallerSdkType,
): ExecuteQueryResponse {
val metadata = grpcMetadata.get(requestId, isFromGeneratedSdk)
val metadata = grpcMetadata.get(requestId, callerSdkType)
val kotlinMethodName = "executeQuery(${request.operationName})"

logger.logGrpcSending(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import com.google.firebase.dataconnect.DataConnectSettings
import com.google.firebase.dataconnect.FirebaseDataConnect
import com.google.firebase.dataconnect.FirebaseDataConnect.MutationRefOptionsBuilder
import com.google.firebase.dataconnect.FirebaseDataConnect.QueryRefOptionsBuilder
import com.google.firebase.dataconnect.generated.GeneratedMutation
import com.google.firebase.dataconnect.generated.GeneratedQuery
import com.google.firebase.dataconnect.isDefaultHost
import com.google.firebase.dataconnect.querymgr.LiveQueries
import com.google.firebase.dataconnect.querymgr.LiveQuery
Expand Down Expand Up @@ -327,7 +325,7 @@ internal class FirebaseDataConnectImpl(
): QueryRefImpl<Data, Variables> {
val options =
object : QueryRefOptionsBuilder<Data, Variables> {
override var generatedQuery: GeneratedQuery<*, Data, Variables>? = null
override var callerSdkType: FirebaseDataConnect.CallerSdkType? = null
override var variablesSerializersModule: SerializersModule? = null
override var dataSerializersModule: SerializersModule? = null
}
Expand All @@ -339,7 +337,7 @@ internal class FirebaseDataConnectImpl(
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
isFromGeneratedSdk = options.generatedQuery !== null,
callerSdkType = options.callerSdkType ?: FirebaseDataConnect.CallerSdkType.Base,
variablesSerializersModule = options.variablesSerializersModule,
dataSerializersModule = options.dataSerializersModule,
)
Expand All @@ -354,7 +352,7 @@ internal class FirebaseDataConnectImpl(
): MutationRefImpl<Data, Variables> {
val options =
object : MutationRefOptionsBuilder<Data, Variables> {
override var generatedMutation: GeneratedMutation<*, Data, Variables>? = null
override var callerSdkType: FirebaseDataConnect.CallerSdkType? = null
override var variablesSerializersModule: SerializersModule? = null
override var dataSerializersModule: SerializersModule? = null
}
Expand All @@ -366,7 +364,7 @@ internal class FirebaseDataConnectImpl(
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
isFromGeneratedSdk = options.generatedMutation !== null,
callerSdkType = options.callerSdkType ?: FirebaseDataConnect.CallerSdkType.Base,
variablesSerializersModule = options.variablesSerializersModule,
dataSerializersModule = options.dataSerializersModule,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class MutationRefImpl<Data, Variables>(
variables: Variables,
dataDeserializer: DeserializationStrategy<Data>,
variablesSerializer: SerializationStrategy<Variables>,
val isFromGeneratedSdk: Boolean,
callerSdkType: FirebaseDataConnect.CallerSdkType,
variablesSerializersModule: SerializersModule?,
dataSerializersModule: SerializersModule?,
) :
Expand All @@ -44,6 +44,7 @@ internal class MutationRefImpl<Data, Variables>(
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
callerSdkType = callerSdkType,
variablesSerializersModule = variablesSerializersModule,
dataSerializersModule = dataSerializersModule,
) {
Expand All @@ -65,7 +66,7 @@ internal class MutationRefImpl<Data, Variables>(
encodeToStruct(variables, variablesSerializer, variablesSerializersModule)
}
},
isFromGeneratedSdk,
callerSdkType,
)
.runCatching {
withContext(dataConnect.blockingDispatcher) {
Expand All @@ -90,6 +91,7 @@ internal class MutationRefImpl<Data, Variables>(
"variables=$variables, " +
"dataDeserializer=$dataDeserializer, " +
"variablesSerializer=$variablesSerializer, " +
"callerSdkType=$callerSdkType, " +
"variablesSerializersModule=$variablesSerializersModule, " +
"dataSerializersModule=$dataSerializersModule" +
")"
Expand All @@ -114,7 +116,7 @@ internal fun <Data, Variables> MutationRefImpl<Data, Variables>.copy(
variables: Variables = this.variables,
dataDeserializer: DeserializationStrategy<Data> = this.dataDeserializer,
variablesSerializer: SerializationStrategy<Variables> = this.variablesSerializer,
isFromGeneratedSdk: Boolean = this.isFromGeneratedSdk,
callerSdkType: FirebaseDataConnect.CallerSdkType = this.callerSdkType,
variablesSerializersModule: SerializersModule? = this.variablesSerializersModule,
dataSerializersModule: SerializersModule? = this.dataSerializersModule,
) =
Expand All @@ -124,7 +126,7 @@ internal fun <Data, Variables> MutationRefImpl<Data, Variables>.copy(
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
isFromGeneratedSdk = isFromGeneratedSdk,
callerSdkType = callerSdkType,
variablesSerializersModule = variablesSerializersModule,
dataSerializersModule = dataSerializersModule,
)
Expand All @@ -140,7 +142,7 @@ internal fun <Data, NewVariables> MutationRefImpl<Data, *>.withVariablesSerializ
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
isFromGeneratedSdk = isFromGeneratedSdk,
callerSdkType = callerSdkType,
variablesSerializersModule = variablesSerializersModule,
dataSerializersModule = dataSerializersModule,
)
Expand All @@ -155,7 +157,7 @@ internal fun <NewData, Variables> MutationRefImpl<*, Variables>.withDataDeserial
variables = variables,
dataDeserializer = dataDeserializer,
variablesSerializer = variablesSerializer,
isFromGeneratedSdk = isFromGeneratedSdk,
callerSdkType = callerSdkType,
variablesSerializersModule = variablesSerializersModule,
dataSerializersModule = dataSerializersModule,
)
Loading
Loading