bucketeer-io / android-client-sdk Goto Github PK
View Code? Open in Web Editor NEWBucketeer Client-side SDK for Android
Home Page: https://docs.bucketeer.io/sdk/client-side/android
License: Apache License 2.0
Bucketeer Client-side SDK for Android
Home Page: https://docs.bucketeer.io/sdk/client-side/android
License: Apache License 2.0
Can't we update the Kotlinter?
Originally posted by @cre8ivejp in #135 (comment)
We want to add and remove deprecated metric events from the SDK to improve our monitoring system.
Basically, we will make changes in the current implementation to support the new metrics. Nothing in particular.
We use Okhttp and Moshi for the API requests.
For get_evaluations
, we will report all metrics events, Including the latency and size metrics events.
For register_events
, we will only report error metrics, such as timeout, network, server errors, etc.
We will remove the InternalErrorMetricsEvent
, and use InternalServerErrorMetricsEvent
for 500 internal server errors and InternalSdkErrorMetricsEvent
for SDK internal errors.
All the metrics events have a key/value map called labels
.
In the labels, we will set the same tag
that is used to initialize the SDK.
E.g
{
"tag": "android"
}
Metric list
https://github.com/bucketeer-io/bucketeer/blob/main/proto/event/client/event.proto#L119-L184
enum ApiId {
UNKNOWN_API = 0;
GET_EVALUATION = 1;
GET_EVALUATIONS = 2;
REGISTER_EVENTS = 3;
}
message LatencyMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
google.protobuf.Duration duration = 3;
}
message SizeMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
int32 size_byte = 3;
}
// HTTP Mapping: 400 Bad Request
message BadRequestErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 401 Unauthorized
message UnauthorizedErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 403 Forbidden
message ForbiddenErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 404 Not Found
message NotFoundErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 499 Client Closed Request
message ClientClosedRequestErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 500 Internal Server Error
message InternalServerErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
// HTTP Mapping: 503 Service Unavailable
message ServiceUnavailableErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
message TimeoutErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
message NetworkErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
message InternalSdkErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
message UnknownErrorMetricsEvent {
ApiId api_id = 1;
map<string, string> labels = 2;
}
response_code
via labelserror_message
and response_code
to the ErrorMetricsEvent labelsthe current metrics on the server are the following.
https://github.com/bucketeer-io/bucketeer/blob/main/proto/event/client/event.proto#L99-L187
We should add more data to the SDK requests for future data analysis and monitoring.
Note: Some data will be required, such as the app version, and it will be added in the BKTConfig.
Besides the sdk_version
, all other additional data will be delivered using a map.
Note: For metrics events, we don't need the metadata.
@JsonClass(generateAdapter = true)
data class GoalEvent(
val timestamp: Long,
val goal_id: String,
val user_id: String,
val value: Double,
val user: User,
val tag: String,
val source_id: SourceID,
val sdk_version: String, // NEW
val metadata: Map<String, String> // NEW
) : EventData()
@JsonClass(generateAdapter = true)
data class EvaluationEvent(
val timestamp: Long,
val feature_id: String,
val feature_version: Int = 0,
val user_id: String,
val variation_id: String = "",
val user: User,
val reason: Reason,
val tag: String,
val source_id: SourceID,
val sdk_version: String, // NEW
val metadata: Map<String, String> // NEW
) : EventData()
// we can't use codegen here
// see MetricsEventAdapterFactory
data class MetricsEvent(
val timestamp: Long,
val event: MetricsEventData,
val type: MetricsEventType,
val sdk_version: String, // NEW
) : EventData()
Because the developer can manually configure the timeout in the initialize interface, the server doesn't know if the request got the timeout error using the default 30 seconds or user setting. To detect it on the server, we need to pass the current setting used in the failed request.
E.g.
labels = mapOf("tag" to "android", "timeout" to "5"),
expected instance of: io.bucketeer.sdk.android.BKTException$NetworkException
but was instance of : io.bucketeer.sdk.android.BKTException$TimeoutException
with value : io.bucketeer.sdk.android.BKTException$TimeoutException: Request timeout error: Connect timed out
expected instance of: io.bucketeer.sdk.android.BKTException$NetworkException
but was instance of : io.bucketeer.sdk.android.BKTException$TimeoutException
with value : io.bucketeer.sdk.android.BKTException$TimeoutException: Request timeout error: Connect timed out
at app//io.bucketeer.sdk.android.internal.remote.ApiClientImplTest.registerEvents - network error(ApiClientImplTest.kt:344)
Caused by: io.bucketeer.sdk.android.BKTException$TimeoutException: Request timeout error: Connect timed out
at app//io.bucketeer.sdk.android.internal.remote.ApiClientExtKt.toBKTException(ApiClientExt.kt:93)
at app//io.bucketeer.sdk.android.internal.remote.ApiClientImpl.registerEvents(ApiClientImpl.kt:152)
at app//io.bucketeer.sdk.android.internal.remote.ApiClientImplTest.registerEvents - network error(ApiClientImplTest.kt:339)
Caused by: java.net.SocketTimeoutException: Connect timed out
at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(Unknown Source)
at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source)
at java.base/java.net.SocksSocketImpl.connect(Unknown Source)
at java.base/java.net.Socket.connect(Unknown Source)
at okhttp3.internal.platform.Platform.connectSocket(Platform.kt:128)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at io.bucketeer.sdk.android.internal.remote.ApiClientImpl.registerEvents(ApiClientImpl.kt:131)
... 1 more
This test fails randomly due to slow CI.
io.bucketeer.sdk.android.internal.remote.ApiClientImplTest > getEvaluations - custom timeout FAILED
com.google.common.truth.AssertionErrorWithFacts at ApiClientImplTest.kt:194
https://github.com/bucketeer-io/android-client-sdk/actions/runs/8261127634/job/22597824194
I mean we should rename EventDao to EventSQLDao.
Also, we might want to add EventStorage just for consistency.
Originally posted by @yshrsmz in #89 (comment)
When the client SDK is being destroyed and there are ongoing requests to the server, it will continue running and may try to write to the closed database.
Currently, the DAO will simply ignore this.
We aim to implement request cancellation, similar to the iOS SDK, to enhance overall safety.
reason
type from int to string (reference)In the new endpoint's response, there is no data
object.
Before:
{
data: {
...
},
}
After:
{
...
}
E.g.
https:/api.example.com/get_evaluations
https:/api.example.com/register_events
PR Reference:
ca-dp/bucketeer-ios-sdk#91
We are improving the evaluation process on the server to evaluate only the flags that have been changed.
This will improve the load on the server and the response time since it will only return the flags that have been changed.
Currently, when a flag changes on the server, it evaluates all flags again and sends the latest evaluations to the client SDK.
The SDK checks the response, and it does nothing if the response is empty. Otherwise, it deletes all the data in the DB and saves the latest evaluations.
1- Change the featureTag
setting to be optional in the BKTConfig
2- Save the featureTag
in the SharedPreferences
if it is configured in the BKTConfig
3- Clear the userEvaluationsID
in the SharedPreferences
if the featureTag
changes
The following new fields will be added to get_evaluations
request.
UserEvaluations.CreatedAt
), and it must be saved in the clientcustomAttributes
interface, the userAttributesUpdated field must be set to true in the next request.The server will return the new following fields in the response.
1- Delete all the evaluations from DB, and save the latest evaluations from the response into the DB
2- Save the UserEvaluations.CreatedAt
in the response as evaluatedAt
in the SharedPreferences
1- Check the evaluation list in the response and upsert them in the DB if the list is not empty
2- Check the list of the feature flags that were archived on the console and delete them from the DB
3- Save the UserEvaluations.CreatedAt
in the response as evaluatedAt
in the SharedPreferences
To help monitor the APIs by sdkVersion
, we need to add it to the GetEvaluations
and RegisterEvents
APIs.
sdkVersion
in the API request.This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
benc-uk/workflow-dispatch
, com.google.devtools.ksp
, com.google.android.material:material
, org.jetbrains.kotlinx:kotlinx-coroutines-android
, androidx.lifecycle:lifecycle-process
, androidx.lifecycle:lifecycle-runtime
, org.jetbrains.kotlin.kapt
, org.jetbrains.kotlin.android
, com.android.application
, com.android.library
)com.google.testparameterinjector:test-parameter-injector
, org.robolectric:robolectric
)actions/setup-java
, actions/upload-artifact
, google-github-actions/release-please-action
, gradle/gradle-build-action
, macos
).github/workflows/build.yml
actions/checkout v4
actions/setup-java v3.13.0
gradle/gradle-build-action v2
actions/upload-artifact v3
.github/workflows/e2e.yml
actions/checkout v4
actions/setup-java v4.2.1@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9
actions/cache v4
reactivecircus/android-emulator-runner v2.30.1@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2
reactivecircus/android-emulator-runner v2.30.1@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2
actions/upload-artifact v4
macos 13-large
.github/workflows/pr-title-validation.yml
amannn/action-semantic-pull-request v5
.github/workflows/publish-maven.yml
actions/checkout v4
actions/setup-java v3.13.0
.github/workflows/pullrequest.yml
actions/checkout v4
actions/setup-java v3.13.0
gradle/gradle-build-action v2
actions/upload-artifact v3
.github/workflows/release.yml
google-github-actions/release-please-action v3.7.13
.github/workflows/update-changelog-docs-page.yml
actions/checkout v4
actions/checkout v4
benc-uk/workflow-dispatch v1.2.2@798e70c97009500150087d30d9f11c5444830385
gradle.properties
settings.gradle
build.gradle
bucketeer/gradle.properties
bucketeer/build.gradle
gradle/libs.versions.toml
com.squareup.okhttp3:okhttp 4.12.0
com.squareup.okhttp3:mockwebserver 4.12.0
androidx.sqlite:sqlite-framework 2.4.0
com.google.android.gms:play-services-basement 18.3.0
com.squareup.moshi:moshi-kotlin 1.15.1
com.squareup.moshi:moshi-kotlin-codegen 1.15.1
com.squareup.moshi:moshi-adapters 1.15.1
junit:junit 4.13.2
org.robolectric:robolectric 4.11.1
com.google.truth:truth 1.4.2
com.google.testparameterinjector:test-parameter-injector 1.15
androidx.test:core 1.5.0
androidx.test:rules 1.5.0
androidx.test.ext:junit 1.1.5
androidx.test:orchestrator 1.4.2
androidx.appcompat:appcompat 1.6.1
androidx.lifecycle:lifecycle-runtime 2.7.0
androidx.lifecycle:lifecycle-process 2.7.0
com.google.android.material:material 1.11.0
com.facebook.stetho:stetho 1.6.0
org.jetbrains.kotlinx:kotlinx-coroutines-android 1.8.0
com.android.library 8.3.2
com.android.application 8.3.2
org.jetbrains.kotlin.android 1.9.23
org.jetbrains.kotlin.kapt 1.9.23
org.jetbrains.dokka 1.9.20
com.vanniktech.maven.publish 0.28.0
com.google.devtools.ksp 1.9.23-1.0.20
org.jmailen.kotlinter 4.3.0
mocks/build.gradle
sample/build.gradle
gradle/wrapper/gradle-wrapper.properties
gradle 8.7
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.