Skip to content
5 changes: 4 additions & 1 deletion telemetry/jetbrains/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ dependencies {

tasks {
withType<KotlinCompile> {
compilerOptions.jvmTarget = JvmTarget.JVM_17
compilerOptions {
jvmTarget = JvmTarget.JVM_17
freeCompilerArgs.add("-Xcontext-receivers")
}
}

val validatePackagedSchema by registering {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import com.squareup.kotlinpoet.DOUBLE
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.STRING
import com.squareup.kotlinpoet.TypeAliasSpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.TypeVariableName
import java.io.File
import java.time.Instant

Expand All @@ -28,6 +29,7 @@ val CONNECTION_SETTINGS = ClassName("software.aws.toolkits.core", "ConnectionSet

const val RESULT = "result"
const val SUCCESS = "success"
const val SANITIZED_RESULT_TYPE_FORMAT = "MetricResult"

fun String.filterInvalidCharacters() = this.replace(".", "")
fun String.toTypeFormat() = this.filterInvalidCharacters().split("_", "-").joinToString(separator = "") { it.capitalize() }
Expand Down Expand Up @@ -73,7 +75,16 @@ private fun FileSpec.Builder.generateTelemetryEnumTypes(items: List<TelemetryMet
}

private fun FileSpec.Builder.generateTelemetryEnumType(item: TelemetryMetricType): FileSpec.Builder {
val enum = TypeSpec.enumBuilder(item.name.toTypeFormat())
val clazz = item.name.toTypeFormat()
val existsInKotlinStdlib = try {
Class.forName("kotlin.$clazz")
true
} catch (_: ClassNotFoundException) {
false
}

val typeName = if (existsInKotlinStdlib) "Metric$clazz" else clazz
val enum = TypeSpec.enumBuilder(typeName)
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("value", String::class)
Expand Down Expand Up @@ -104,7 +115,7 @@ private fun FileSpec.Builder.generateTelemetryEnumType(item: TelemetryMetricType
val companion = TypeSpec.companionObjectBuilder()
.addFunction(
FunSpec.builder("from")
.returns(ClassName("", item.name.toTypeFormat()))
.returns(ClassName("", typeName))
.addParameter("type", String::class)
.addStatement("return values().firstOrNull·{·it.value·==·type·} ?:·$unknownType")
.build()
Expand All @@ -118,6 +129,24 @@ private fun FileSpec.Builder.generateTelemetryEnumType(item: TelemetryMetricType
return this
}

private fun FileSpec.Builder.generateDeprecatedOverloads(name: String): FileSpec.Builder {
val oldName = name.toTypeFormat()
val replacementType = TypeVariableName("Metric$oldName")
val replacementFqn = TypeVariableName("$PACKAGE_NAME.$replacementType")
val alias = TypeAliasSpec.builder(oldName, replacementType)
.addAnnotation(
AnnotationSpec.builder(Deprecated::class)
.addMember("message = %S", "Name conflicts with the Kotlin standard library")
.addMember("replaceWith = ReplaceWith(%S, %S)", replacementType, replacementFqn)
.build()
)
.build()

addTypeAlias(alias)

return this
}

private fun FileSpec.Builder.generateTelemetryObjects(schema: List<MetricSchema>): FileSpec.Builder {
schema.groupBy { it.namespace() }
.toSortedMap()
Expand All @@ -136,6 +165,7 @@ private fun FileSpec.Builder.generateNamespaces(namespace: String, metrics: List
return this
}

context(FileSpec.Builder)
private fun TypeSpec.Builder.generateRecordFunctions(metric: MetricSchema) {
// metric.name.split("_")[1] is guaranteed to work at this point because the schema requires the metric name to have at least 1 underscore
val functionName = metric.name.split("_")[1]
Expand All @@ -148,6 +178,7 @@ private fun TypeSpec.Builder.generateRecordFunctions(metric: MetricSchema) {
if (metric.metadata.none { it.type.name == RESULT }) {
return
}
generateDeprecatedOverloads(RESULT)

addFunction(buildProjectOverloadFunction(functionName, metric))
addFunction(buildConnectionSettingsOverloadFunction(functionName, metric))
Expand Down Expand Up @@ -198,7 +229,7 @@ private fun buildMetricParameters(metric: MetricSchema): List<ParameterSpec> {
private fun MetadataSchema.metadataToParameter(): ParameterSpec {
// Allowed values indicates an enum
val typeName = if (type.allowedValues != null) {
ClassName(PACKAGE_NAME, type.name.toTypeFormat())
ClassName(PACKAGE_NAME, type.name.toTypeFormat().replace("Result", SANITIZED_RESULT_TYPE_FORMAT))
} else {
type.type.kotlinType()
}.copy(nullable = required == false)
Expand All @@ -211,11 +242,11 @@ private fun MetadataSchema.metadataToParameter(): ParameterSpec {
}

private fun FunSpec.Builder.generateFunctionBody(metadataParameter: ParameterSpec, metric: MetricSchema): FunSpec.Builder {
val metricUnit = MemberName("software.amazon.awssdk.services.toolkittelemetry.model", "Unit")
val metricUnit = ClassName("software.amazon.awssdk.services.toolkittelemetry.model", "Unit")
beginControlFlow("%T.getInstance().record(${metadataParameter.name})", TELEMETRY_SERVICE)
beginControlFlow("datum(%S)", metric.name)
addStatement("createTime(createTime)")
addStatement("unit(%M.${(metric.unit ?: MetricUnit.NONE).name})", metricUnit)
addStatement("unit(%T.${(metric.unit ?: MetricUnit.NONE).name})", metricUnit)
addStatement("value(value)")
addStatement("passive(passive)")
metric.metadata.forEach {
Expand Down Expand Up @@ -269,7 +300,7 @@ private fun FunSpec.Builder.generateResultOverloadFunctionBody(functionName: Str
if (it.name != SUCCESS) {
it.name
} else {
"if($SUCCESS) Result.Succeeded else Result.Failed"
"if($SUCCESS) $SANITIZED_RESULT_TYPE_FORMAT.Succeeded else $SANITIZED_RESULT_TYPE_FORMAT.Failed"
}
})

Expand Down
5 changes: 3 additions & 2 deletions telemetry/jetbrains/src/test/resources/testOverrideOutput
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import software.aws.toolkits.jetbrains.services.telemetry.TelemetryService
/**
* The result of the operation
*/
public enum class Result(
public enum class MetricResult(
private val `value`: String,
) {
Succeeded("Succeeded"),
Expand All @@ -29,7 +29,8 @@ public enum class Result(
override fun toString(): String = value

public companion object {
public fun from(type: String): Result = values().firstOrNull { it.value == type } ?: Unknown
public fun from(type: String): MetricResult = values().firstOrNull { it.value == type }
?: Unknown
}
}

Expand Down
30 changes: 19 additions & 11 deletions telemetry/jetbrains/src/test/resources/testResultOutput
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package software.aws.toolkits.telemetry
import com.intellij.openapi.project.Project
import java.time.Instant
import kotlin.Boolean
import kotlin.Deprecated
import kotlin.Double
import kotlin.String
import kotlin.Suppress
Expand All @@ -19,7 +20,7 @@ import software.aws.toolkits.jetbrains.services.telemetry.TelemetryService
/**
* The result of the operation
*/
public enum class Result(
public enum class MetricResult(
private val `value`: String,
) {
Succeeded("Succeeded"),
Expand All @@ -34,17 +35,24 @@ public enum class Result(
override fun toString(): String = value

public companion object {
public fun from(type: String): Result = values().firstOrNull { it.value == type } ?: Unknown
public fun from(type: String): MetricResult = values().firstOrNull { it.value == type }
?: Unknown
}
}

@Deprecated(
message = "Name conflicts with the Kotlin standard library",
replaceWith = ReplaceWith("MetricResult", "software.aws.toolkits.telemetry.MetricResult"),
)
public typealias Result = MetricResult

public object MetadataTelemetry {
/**
* It has a result
*/
public fun hasResult(
project: Project?,
result: Result,
result: MetricResult,
passive: Boolean = false,
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
Expand All @@ -65,7 +73,7 @@ public object MetadataTelemetry {
*/
public fun hasResult(
connectionSettings: ConnectionSettings? = null,
result: Result,
result: MetricResult,
passive: Boolean = false,
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
Expand All @@ -86,7 +94,7 @@ public object MetadataTelemetry {
*/
public fun hasResult(
metadata: MetricEventMetadata,
result: Result,
result: MetricResult,
passive: Boolean = false,
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
Expand All @@ -112,8 +120,8 @@ public object MetadataTelemetry {
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
) {
hasResult(project, if(success) Result.Succeeded else Result.Failed, passive, value,
createTime)
hasResult(project, if(success) MetricResult.Succeeded else MetricResult.Failed, passive,
value, createTime)
}

/**
Expand All @@ -126,8 +134,8 @@ public object MetadataTelemetry {
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
) {
hasResult(connectionSettings, if(success) Result.Succeeded else Result.Failed, passive,
value, createTime)
hasResult(connectionSettings, if(success) MetricResult.Succeeded else MetricResult.Failed,
passive, value, createTime)
}

/**
Expand All @@ -140,7 +148,7 @@ public object MetadataTelemetry {
`value`: Double = 1.0,
createTime: Instant = Instant.now(),
) {
hasResult(metadata, if(success) Result.Succeeded else Result.Failed, passive, value,
createTime)
hasResult(metadata, if(success) MetricResult.Succeeded else MetricResult.Failed, passive,
value, createTime)
}
}