Skip to content
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

optimize gson usage #34

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 1 addition & 3 deletions src/main/kotlin/com/statsig/sdk/DynamicConfig.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.statsig.sdk

import com.google.gson.Gson

/**
* A helper class for interfacing with Dynamic Configs defined in the Statsig console
*/
Expand Down Expand Up @@ -132,7 +130,7 @@ class DynamicConfig(
}

fun getExposureMetadata(): String {
return Gson().toJson(
return Utils.PLAIN_GSON.toJson(
mapOf(
"config" to this.name,
"ruleID" to this.ruleID,
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/com/statsig/sdk/ErrorBoundary.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.statsig.sdk

import com.google.gson.Gson
import kotlinx.coroutines.*
import okhttp3.Call
import okhttp3.Callback
Expand Down Expand Up @@ -93,7 +92,7 @@ internal class ErrorBoundary(private val apiKey: String, private val options: St
if (safeInfo.length > maxInfoLength) {
safeInfo = safeInfo.substring(0, maxInfoLength)
}
val optionsCopy = Gson().toJson(options.getLoggingCopy())
val optionsCopy = Utils.PLAIN_GSON.toJson(options.getLoggingCopy())
val body = """{
"tag": "$tag",
"exception": "${ex.javaClass.name}",
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/com/statsig/sdk/Evaluator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ internal class Evaluator(
private var configOverrides: MutableMap<String, Map<String, Any>> = HashMap()
private var layerOverrides: MutableMap<String, Map<String, Any>> = HashMap()
private var hashLookupTable: MutableMap<String, ULong> = HashMap()
private val gson = Utils.getGson()
private val logger = options.customLogger

private val calendarOne = Calendar.getInstance()
Expand Down
4 changes: 1 addition & 3 deletions src/main/kotlin/com/statsig/sdk/Hashing.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.statsig.sdk

import com.google.gson.Gson
import java.security.MessageDigest
import java.util.Base64

Expand All @@ -22,8 +21,7 @@ class Hashing {
}

fun djb2ForMap(map: Map<String, Any>): String {
val gson = Gson()
return djb2(gson.toJson(Utils.sortMap(map)))
return djb2(Utils.PLAIN_GSON.toJson(Utils.sortMap(map)))
}

fun sha256(input: String): String {
Expand Down
4 changes: 1 addition & 3 deletions src/main/kotlin/com/statsig/sdk/Layer.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.statsig.sdk

import com.google.gson.Gson

typealias OnLayerExposure = (layerExposureEventData: LayerExposureEventData) -> Unit
internal typealias OnLayerExposureInternal = (layer: Layer, parameterName: String) -> Unit

Expand Down Expand Up @@ -125,7 +123,7 @@ class Layer internal constructor(
* Legacy exposure data at the layer level. Should NOT be used in new code as this will cause over exposure.
*/
fun getLegacyExposureMetadata(): String {
return Gson().toJson(
return Utils.PLAIN_GSON.toJson(
mapOf(
"config" to this.name,
"ruleID" to this.ruleID,
Expand Down
14 changes: 6 additions & 8 deletions src/main/kotlin/com/statsig/sdk/SpecStore.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.statsig.sdk

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.statsig.sdk.datastore.IDataStore
import com.statsig.sdk.network.StatsigTransport
import kotlinx.coroutines.*
Expand All @@ -20,6 +18,10 @@ internal class SpecStore(
private val sdkConfigs: SDKConfigs,
private val serverSecret: String,
) {
companion object {
val PRETTY_PRINTING_GSON = GsonBuilder().setPrettyPrinting().create()
}

private var initTime: Long = 0
private var evalReason: EvaluationReason = EvaluationReason.UNINITIALIZED
private var downloadIDListCallCount: Long = 0
Expand All @@ -42,9 +44,6 @@ internal class SpecStore(
specUpdater.registerConfigSpecListener(::processDownloadedConfigs)
}

private val gson = Utils.getGson()
private inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object : TypeToken<T>() {}.type)

suspend fun initialize(): FailureDetails? {
if (!options.localMode) {
specUpdater.initialize()
Expand Down Expand Up @@ -203,7 +202,7 @@ internal class SpecStore(

var configString = ""
try {
configString = gson.toJson(configSpecs)
configString = Utils.GSON.toJson(configSpecs)
} catch (e: Exception) {
errorBoundary.logException("fireRulesUpdatedCallback", e)
options.customLogger.error("An exception was caught when fire callback: $e")
Expand Down Expand Up @@ -419,8 +418,7 @@ internal class SpecStore(
dataStore: IDataStore,
response: APIDownloadedConfigs,
): APIDownloadedConfigs {
val gson = GsonBuilder().setPrettyPrinting().create()
val specs: String = gson.toJson(response)
val specs: String = PRETTY_PRINTING_GSON.toJson(response)

val adapterKey = dataStore.dataStoreKey
dataStore.set(adapterKey, specs)
Expand Down
13 changes: 4 additions & 9 deletions src/main/kotlin/com/statsig/sdk/SpecUpdater.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.statsig.sdk

import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import com.statsig.sdk.network.StatsigTransport
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
Expand Down Expand Up @@ -31,9 +29,6 @@ internal class SpecUpdater(
private var backgroundDownloadIDLists: Job? = null
private val logger = options.customLogger

private val gson = Utils.getGson()
private inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object : TypeToken<T>() {}.type)

fun initialize() {
transport.setStreamingFallback(NetworkEndpoint.DOWNLOAD_CONFIG_SPECS) {
this.transport.downloadConfigSpecsFromStatsig(
Expand Down Expand Up @@ -133,7 +128,7 @@ internal class SpecUpdater(
suspend fun updateIDLists(): Map<String, IDList>? {
return try {
val response = transport.getIDLists() ?: return null
gson.fromJson<Map<String, IDList>>(response)
Utils.GSON.fromJson<Map<String, IDList>>(response)
} catch (e: JsonSyntaxException) {
null
}
Expand All @@ -147,7 +142,7 @@ internal class SpecUpdater(
return Pair(null, FailureDetails(FailureReason.EMPTY_SPEC))
}
try {
return Pair(gson.fromJson(specs, APIDownloadedConfigs::class.java), null)
return Pair(Utils.GSON.fromJson(specs, APIDownloadedConfigs::class.java), null)
} catch (e: JsonSyntaxException) {
errorBoundary.logException("parseConfigSpecs", e)
logger.error("An exception was caught when parsing config specs: $e")
Expand All @@ -160,7 +155,7 @@ internal class SpecUpdater(
return Pair(null, response.second)
}
try {
val configs = gson.fromJson(response.first, APIDownloadedConfigs::class.java)
val configs = Utils.GSON.fromJson(response.first, APIDownloadedConfigs::class.java)
if (configs.hashedSDKKeyUsed != null && configs.hashedSDKKeyUsed != Hashing.djb2(serverSecret)) {
return Pair(null, FailureDetails(FailureReason.PARSE_RESPONSE_ERROR))
}
Expand All @@ -177,7 +172,7 @@ internal class SpecUpdater(
return null
}
try {
return gson.fromJson<Map<String, IDList>>(lists)
return Utils.GSON.fromJson<Map<String, IDList>>(lists)
} catch (e: JsonSyntaxException) {
errorBoundary.logException("parseIDLists", e)
logger.warn("An exception was caught when parsing ID lists: $e")
Expand Down
7 changes: 3 additions & 4 deletions src/main/kotlin/com/statsig/sdk/StatsigLogger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ internal class StatsigLogger(
deduper.clear()
}
}
private val gson = Utils.getGson()
internal var diagnostics: Diagnostics? = null
private var eventQueueSize: Int? = null
private val logger = statsigOptions.customLogger
Expand Down Expand Up @@ -181,8 +180,8 @@ internal class StatsigLogger(
val event = StatsigEvent(DIAGNOSTICS_EVENT)
event.eventMetadata = mapOf(
"context" to context.toString().lowercase(),
"markers" to gson.toJson(markers),
"statsigOptions" to gson.toJson(statsigOptions.getLoggingCopy()),
"markers" to Utils.GSON.toJson(markers),
"statsigOptions" to Utils.GSON.toJson(statsigOptions.getLoggingCopy()),
)
log(event)
}
Expand All @@ -198,7 +197,7 @@ internal class StatsigLogger(
val event = StatsigEvent(DIAGNOSTICS_EVENT)
event.eventMetadata = mapOf(
"context" to context.name.lowercase(),
"markers" to gson.toJson(markers),
"markers" to Utils.GSON.toJson(markers),
)
if (statsigOptions.disableAllLogging) {
return
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/com/statsig/sdk/StatsigMetadata.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ internal data class StatsigMetadata(@SerializedName("sdkType") var sdkType: Stri
VERSION
}
fun asJson(): String {
val gson = Utils.getGson()
return gson.toJson(this)
return Utils.GSON.toJson(this)
}
}
4 changes: 1 addition & 3 deletions src/main/kotlin/com/statsig/sdk/StatsigServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,6 @@ sealed class StatsigServer {
private class StatsigServerImpl() :
StatsigServer() {

private val gson = Utils.getGson()

override lateinit var errorBoundary: ErrorBoundary
private lateinit var coroutineExceptionHandler: CoroutineExceptionHandler
private lateinit var statsigJob: CompletableJob
Expand Down Expand Up @@ -1228,7 +1226,7 @@ private class StatsigServerImpl() :
normalizedUser,
layer,
paramName,
gson.toJson(metadata),
Utils.GSON.toJson(metadata),
),
)
} else {
Expand Down
6 changes: 5 additions & 1 deletion src/main/kotlin/com/statsig/sdk/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package com.statsig.sdk
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.ToNumberPolicy
import com.google.gson.reflect.TypeToken
import java.util.*

inline fun <reified T> Gson.fromJson(json: String): T = fromJson(json, object : TypeToken<T>() {}.type)

internal class Utils {
companion object {
fun getTimeInMillis(): Long {
return System.currentTimeMillis()
}
fun getGson(): Gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create()
val GSON: Gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create()
val PLAIN_GSON = Gson()
fun toStringOrEmpty(value: Any?): String {
return value?.toString() ?: ""
}
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/com/statsig/sdk/network/HTTPHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ internal class HTTPHelper(
private var diagnostics: Diagnostics? = null
private val logger = options.customLogger

private val gson = Utils.getGson()
private val json: MediaType = "application/json; charset=utf-8".toMediaType()

fun setDiagnostics(diagnostics: Diagnostics) {
Expand All @@ -34,7 +33,7 @@ internal class HTTPHelper(
val request = Request.Builder()
.url(url)
if (body != null) {
val bodyJson = gson.toJson(body)
val bodyJson = Utils.GSON.toJson(body)
request.post(bodyJson.toRequestBody(json))
}
headers.forEach { (key, value) -> request.addHeader(key, value) }
Expand Down
7 changes: 1 addition & 6 deletions src/main/kotlin/com/statsig/sdk/network/HTTPWorker.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.statsig.sdk.network

import com.google.gson.Gson
import com.google.gson.JsonParseException
import com.google.gson.reflect.TypeToken
import com.statsig.sdk.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -55,16 +53,13 @@ internal class HTTPWorker(

private val json: MediaType = "application/json; charset=utf-8".toMediaType()
private val statsigHttpClient: OkHttpClient
private val gson = Utils.getGson()
private var diagnostics: Diagnostics? = null
private val logger = options.customLogger
val apiForDownloadConfigSpecs = options.endpointProxyConfigs[NetworkEndpoint.DOWNLOAD_CONFIG_SPECS]?.proxyAddress ?: options.apiForDownloadConfigSpecs ?: options.api ?: STATSIG_CDN_URL_BASE
val apiForGetIDLists = options.endpointProxyConfigs[NetworkEndpoint.GET_ID_LISTS]?.proxyAddress ?: options.apiForGetIdlists ?: options.api ?: STATSIG_API_URL_BASE
val apiForLogEvent = options.endpointProxyConfigs[NetworkEndpoint.LOG_EVENT]?.proxyAddress ?: options.api ?: STATSIG_API_URL_BASE
private var eventsCount: String = ""

private inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object : TypeToken<T>() {}.type)

init {
val clientBuilder = OkHttpClient.Builder()

Expand Down Expand Up @@ -281,7 +276,7 @@ internal class HTTPWorker(
return
}

val bodyJson = gson.toJson(mapOf("events" to events, "statsigMetadata" to statsigMetadata))
val bodyJson = Utils.GSON.toJson(mapOf("events" to events, "statsigMetadata" to statsigMetadata))
val requestBody: RequestBody = bodyJson.toRequestBody(json)
eventsCount = events.size.toString()

Expand Down