Skip to content

Commit

Permalink
CallerSdkType added (#6298)
Browse files Browse the repository at this point in the history
  • Loading branch information
dconeybe authored Sep 24, 2024
1 parent 9f3210a commit 0466055
Show file tree
Hide file tree
Showing 27 changed files with 302 additions and 260 deletions.
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

0 comments on commit 0466055

Please sign in to comment.