Skip to content

Commit

Permalink
remove unusefull setting. (#165)
Browse files Browse the repository at this point in the history
* remove unusefull setting.

* break lines.
separate class.

* add unit test for event validator
  • Loading branch information
wasnot authored Jan 13, 2022
1 parent fe9d834 commit 9d9d77e
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 87 deletions.
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[*.{kt, kts}]
disabled_rules = import-ordering
max_line_length = 1000
2 changes: 1 addition & 1 deletion .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 8 additions & 60 deletions core/src/main/java/io/karte/android/tracking/Event.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
package io.karte.android.tracking

import io.karte.android.utilities.format
import io.karte.android.utilities.toMap
import io.karte.android.utilities.toValues
import org.json.JSONObject
import java.util.regex.Pattern

/** イベントに追加できるカスタムオブジェクトの型を示すエイリアスです。 */
typealias Values = Map<String, Any>
Expand Down Expand Up @@ -72,9 +70,6 @@ open class Event {
internal var isRetry = false
val eventName: EventName
internal val isRetryable: Boolean
internal val isDeprecatedEventName: Boolean
internal val isDeprecatedEventFieldName: Boolean
internal val isInvalidEventFieldValue: Boolean

/** [JSONObject] による初期化 */
constructor(
Expand All @@ -85,9 +80,6 @@ open class Event {
this.eventName = eventName
this.values = jsonObject?.format() ?: JSONObject()
this.isRetryable = isRetryable ?: true
this.isDeprecatedEventName = validateEventName(eventName.value)
this.isDeprecatedEventFieldName = validateEventFieldName(values)
this.isInvalidEventFieldValue = validateEventFieldValue(eventName.value, values)
}

/** [Values] による初期化 */
Expand Down Expand Up @@ -119,58 +111,6 @@ open class Event {
}.getOrNull()
}
}

private val EVENT_NAME_REGEX = Pattern.compile("[^a-z0-9_]")

/** 非推奨なイベント名が含まれるかを返します。 */
private fun validateEventName(eventName: String): Boolean {
if (eventName.isEmpty()) {
return false
}
when (eventName) {
MessageEventName.MessageReady.value, MessageEventName.MessageSuppressed.value, "_fetch_variables" -> {
return false
}
}
val m = EVENT_NAME_REGEX.matcher(eventName)
return m.find() || eventName.startsWith("_")
}

internal val INVALID_FIELD_NAMES = listOf("_source", "_system", "any", "avg", "cache", "count", "count_sets", "date", "f_t", "first", "keys", "l_t", "last", "lrus", "max", "min", "o", "prev", "sets", "size", "span", "sum", "type", "v")

/** 非推奨なフィールド名が含まれるかを返します。 */
private fun validateEventFieldName(values: JSONObject): Boolean {
if (values.length() == 0) {
return false
}
val result = values.toMap().any {
it.key.startsWith("$") || it.key.contains(".") || INVALID_FIELD_NAMES.contains(it.key)
}
return result
}

/** 無効な値が含まれるかを返します。 */
private fun validateEventFieldValue(eventName: String, values: JSONObject): Boolean {
if (values.length() == 0) {
return false
}

when (eventName) {
BaseEventName.View.value -> {
val viewName = values.optString("view_name")
if (viewName.isEmpty()) {
return true
}
}
BaseEventName.Identify.value -> {
val userId = values.optString("user_id")
if (userId.isEmpty()) {
return true
}
}
}
return false
}
}

/** `identify` イベント */
Expand Down Expand Up @@ -247,12 +187,16 @@ internal enum class AutoEventName(override val value: String) : EventName {
enum class MessageEventName(override val value: String) : EventName {
/** _message_ready イベント*/
MessageReady("_message_ready"),

/** message_open イベント*/
MessageOpen("message_open"),

/** message_close イベント*/
MessageClose("message_close"),

/** message_click イベント*/
MessageClick("message_click"),

/** _message_suppressed イベント */
MessageSuppressed("_message_suppressed"),
}
Expand All @@ -267,12 +211,16 @@ class CustomEventName(override val value: String) : EventName
enum class MessageEventType(val eventName: EventName) {
/** _message_ready イベント*/
Ready(MessageEventName.MessageReady),

/** message_open イベント*/
Open(MessageEventName.MessageOpen),

/** message_close イベント*/
Close(MessageEventName.MessageClose),

/** message_click イベント*/
Click(MessageEventName.MessageClick),

/** _message_suppressed イベント */
Suppressed(MessageEventName.MessageSuppressed),
}
134 changes: 134 additions & 0 deletions core/src/main/java/io/karte/android/tracking/EventValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//
// Copyright 2021 PLAID, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package io.karte.android.tracking

import io.karte.android.utilities.isAscii
import io.karte.android.utilities.toMap
import org.json.JSONObject
import java.util.regex.Pattern

private val EVENT_NAME_REGEX = Pattern.compile("[^a-z0-9_]")
internal val INVALID_FIELD_NAMES = listOf(
"_source",
"_system",
"any",
"avg",
"cache",
"count",
"count_sets",
"date",
"f_t",
"first",
"keys",
"l_t",
"last",
"lrus",
"max",
"min",
"o",
"prev",
"sets",
"size",
"span",
"sum",
"type",
"v"
)

internal object EventValidator {

internal fun getDeprecatedMessages(event: Event): List<String> {
val eventName = event.eventName.value
val messages = mutableListOf<String>()

if (!eventName.isAscii())
messages.add("Multi-byte character in event name is deprecated: Event=$eventName")

if (validateEventName(eventName))
messages.add(
"[^a-z0-9_] or starting with _ in event name is deprecated:" +
" Event=$eventName"
)

if (validateEventFieldName(event.values))
messages.add(
"Contains dots(.) or stating with $ or $INVALID_FIELD_NAMES" +
" in event field name is deprecated:" +
" EventName=$eventName,FieldName=${event.values}"
)
return messages
}

internal fun getInvalidMessages(event: Event): List<String> {
val messages = mutableListOf<String>()
if (validateEventFieldValue(event.eventName.value, event.values))
messages.add(
"Failed to push Event to queue because view_name or user_id is empty:" +
" EventName=${event.eventName.value},FieldName=${event.values}"
)
return messages
}

/** 非推奨なイベント名が含まれるかを返します。 */
private fun validateEventName(eventName: String): Boolean {
if (eventName.isEmpty()) {
return false
}
when (eventName) {
MessageEventName.MessageReady.value,
MessageEventName.MessageSuppressed.value,
"_fetch_variables" -> {
return false
}
}
val m = EVENT_NAME_REGEX.matcher(eventName)
return m.find() || eventName.startsWith("_")
}

/** 非推奨なフィールド名が含まれるかを返します。 */
private fun validateEventFieldName(values: JSONObject): Boolean {
if (values.length() == 0) {
return false
}
return values.toMap().any {
it.key.startsWith("$") || it.key.contains(".") || INVALID_FIELD_NAMES.contains(it.key)
}
}

/** 無効な値が含まれるかを返します。 */
private fun validateEventFieldValue(eventName: String, values: JSONObject): Boolean {
if (values.length() == 0) {
return false
}

when (eventName) {
BaseEventName.View.value -> {
val viewName = values.optString("view_name")
if (viewName.isEmpty()) {
return true
}
}
BaseEventName.Identify.value -> {
val userId = values.optString("user_id")
if (userId.isEmpty()) {
return true
}
}
}
return false
}
}
20 changes: 2 additions & 18 deletions core/src/main/java/io/karte/android/tracking/TrackingService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import io.karte.android.KarteApp
import io.karte.android.core.logger.Logger
import io.karte.android.tracking.queue.Dispatcher
import io.karte.android.tracking.queue.EventRecord
import io.karte.android.utilities.isAscii
import io.karte.android.utilities.toValues
import org.json.JSONObject

Expand All @@ -39,23 +38,8 @@ internal class TrackingService internal constructor() {
completion: TrackCompletion? = null
) {
if (KarteApp.isOptOut) return
if (!inEvent.eventName.value.isAscii())
Logger.w(
LOG_TAG,
"Multi-byte character in event name is deprecated: Event=${inEvent.eventName.value}"
)

if (inEvent.isDeprecatedEventName)
Logger.w(
LOG_TAG,
"[^a-z0-9_] or starting with _ in event name is deprecated: Event=${inEvent.eventName.value}"
)

if (inEvent.isDeprecatedEventFieldName)
Logger.w(
LOG_TAG,
"Contains dots(.) or stating with $ or ${inEvent.INVALID_FIELD_NAMES} in event field name is deprecated: EventName=${inEvent.eventName.value},FieldName=${inEvent.values}"
)
EventValidator.getDeprecatedMessages(inEvent)
.forEach { Logger.w(LOG_TAG, it) }

Logger.d(LOG_TAG, "track")
val event = delegate?.intercept(inEvent) ?: inEvent
Expand Down
13 changes: 6 additions & 7 deletions core/src/main/java/io/karte/android/tracking/queue/Dispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.karte.android.KarteApp
import io.karte.android.core.library.ActionModule
import io.karte.android.core.library.TrackModule
import io.karte.android.core.logger.Logger
import io.karte.android.tracking.EventValidator
import io.karte.android.tracking.TrackCompletion
import io.karte.android.tracking.client.TrackResponse
import io.karte.android.tracking.client.requestOf
Expand Down Expand Up @@ -89,11 +90,9 @@ internal class Dispatcher {
completion?.onComplete(false)
return
}
if (record.event.isInvalidEventFieldValue) {
Logger.w(
LOG_TAG,
"Failed to push Event to queue because view_name or user_id is empty: EventName=${record.event.eventName.value},FieldName=${record.event.values}"
)
val eventInvalidMessages = EventValidator.getInvalidMessages(record.event)
if (eventInvalidMessages.isNotEmpty()) {
eventInvalidMessages.forEach { Logger.w(LOG_TAG, it) }
completion?.onComplete(false)
return
}
Expand Down Expand Up @@ -147,8 +146,8 @@ internal class Dispatcher {
records
.filter { retryCircuitBreaker.canRequest || it.retry == 0 }
.groupBy(
{ GroupingKey(it.visitorId, it.originalPvId, it.pvId, it.retry > 0) },
{ it })
{ GroupingKey(it.visitorId, it.originalPvId, it.pvId, it.retry > 0) },
{ it })
.forEach { (key, events) ->
Logger.d(LOG_TAG, "request events: ${events.size}")
// 10 events per request
Expand Down
Loading

0 comments on commit 9d9d77e

Please sign in to comment.