Skip to content

Commit 1b6c400

Browse files
authored
feat(jetbrains): Add global metadata fields into all metrics for jetbrains telemetry generator (#817)
1 parent c8b91f4 commit 1b6c400

File tree

6 files changed

+428
-2
lines changed

6 files changed

+428
-2
lines changed

telemetry/jetbrains/src/main/kotlin/software/aws/toolkits/telemetry/generator/TelemetryGenerator.kt

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,39 @@ fun generateTelemetryFromFiles(
4040
outputFolder: File
4141
) {
4242
val telemetry = TelemetryParser.parseFiles(defaultDefinitions, inputFiles)
43+
val commonMetadataTypes = setOf(
44+
"duration",
45+
"httpStatusCode",
46+
"reason",
47+
"reasonDesc",
48+
"requestId",
49+
"requestServiceType",
50+
"result",
51+
)
52+
53+
val metricsWithCommonMetadata = telemetry.metrics.map { metric ->
54+
// compute [MetadataSchema] for any common types not already declared in the schema
55+
val commonMetadata = commonMetadataTypes.mapNotNull { commonMetadataType ->
56+
val type = telemetry.types.firstOrNull { it.name == commonMetadataType }
57+
58+
if (type != null && metric.metadata.none { it.type.name == commonMetadataType }) {
59+
MetadataSchema(type, false)
60+
} else {
61+
null
62+
}
63+
}
64+
65+
// metadata will be sorted during generation
66+
metric.copy(metadata = metric.metadata + commonMetadata)
67+
}
68+
4369
// make sure the output directory exists before writing to it
4470
outputFolder.mkdirs()
4571
FileSpec.builder(PACKAGE_NAME, "TelemetryDefinitions")
4672
.indent(" ".repeat(4))
4773
.generateHeader()
4874
.generateTelemetryEnumTypes(telemetry.types)
49-
.generateTelemetryObjects(telemetry.metrics)
75+
.generateTelemetryObjects(metricsWithCommonMetadata)
5076
.build()
5177
.writeTo(outputFolder)
5278
}
@@ -129,7 +155,9 @@ private fun FileSpec.Builder.generateTelemetryObjects(schema: List<MetricSchema>
129155
private fun FileSpec.Builder.generateNamespaces(namespace: String, metrics: List<MetricSchema>): FileSpec.Builder {
130156
val telemetryObject = TypeSpec.objectBuilder("${namespace.toTypeFormat()}Telemetry")
131157

132-
metrics.sortedBy { it.name }.forEach { telemetryObject.generateRecordFunctions(it) }
158+
metrics.sortedBy { it.name }.forEach {
159+
telemetryObject.generateRecordFunctions(it)
160+
}
133161

134162
addType(telemetryObject.build())
135163

telemetry/jetbrains/src/test/kotlin/software/aws/toolkits/telemetry/generator/GeneratorTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ class GeneratorTest {
2424
}.hasMessageContaining("required key [metrics] not found")
2525
}
2626

27+
@Test
28+
fun generateWithGlobalMetadata() {
29+
testGenerator(defaultDefinitionsFile = "/testGlobalMetadataInput.json", expectedOutputFile = "/testGlobalMetadataOutput")
30+
}
31+
2732
@Test
2833
fun generatesWithNormalInput() {
2934
testGenerator(defaultDefinitionsFile = "/testGeneratorInput.json", expectedOutputFile = "/testGeneratorOutput")

telemetry/jetbrains/src/test/resources/testGeneratorOutput

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public object LambdaTelemetry {
4444
project: Project?,
4545
lambdaRuntime: LambdaRuntime,
4646
arbitraryString: String,
47+
duration: Double? = null,
4748
passive: Boolean = false,
4849
`value`: Double = 1.0,
4950
createTime: Instant = Instant.now(),
@@ -56,6 +57,9 @@ public object LambdaTelemetry {
5657
passive(passive)
5758
metadata("lambdaRuntime", lambdaRuntime.toString())
5859
metadata("arbitraryString", arbitraryString)
60+
if(duration != null) {
61+
metadata("duration", duration.toString())
62+
}
5963
}
6064
}
6165
}
@@ -67,6 +71,7 @@ public object LambdaTelemetry {
6771
connectionSettings: ConnectionSettings? = null,
6872
lambdaRuntime: LambdaRuntime,
6973
arbitraryString: String,
74+
duration: Double? = null,
7075
passive: Boolean = false,
7176
`value`: Double = 1.0,
7277
createTime: Instant = Instant.now(),
@@ -79,6 +84,9 @@ public object LambdaTelemetry {
7984
passive(passive)
8085
metadata("lambdaRuntime", lambdaRuntime.toString())
8186
metadata("arbitraryString", arbitraryString)
87+
if(duration != null) {
88+
metadata("duration", duration.toString())
89+
}
8290
}
8391
}
8492
}
@@ -90,6 +98,7 @@ public object LambdaTelemetry {
9098
metadata: MetricEventMetadata,
9199
lambdaRuntime: LambdaRuntime,
92100
arbitraryString: String,
101+
duration: Double? = null,
93102
passive: Boolean = false,
94103
`value`: Double = 1.0,
95104
createTime: Instant = Instant.now(),
@@ -102,6 +111,9 @@ public object LambdaTelemetry {
102111
passive(passive)
103112
metadata("lambdaRuntime", lambdaRuntime.toString())
104113
metadata("arbitraryString", arbitraryString)
114+
if(duration != null) {
115+
metadata("duration", duration.toString())
116+
}
105117
}
106118
}
107119
}
@@ -182,6 +194,7 @@ public object LambdaTelemetry {
182194
project: Project?,
183195
lambdaRuntime: LambdaRuntime? = null,
184196
inttype: Int,
197+
duration: Double? = null,
185198
passive: Boolean = false,
186199
`value`: Double = 1.0,
187200
createTime: Instant = Instant.now(),
@@ -196,6 +209,9 @@ public object LambdaTelemetry {
196209
metadata("lambdaRuntime", lambdaRuntime.toString())
197210
}
198211
metadata("inttype", inttype.toString())
212+
if(duration != null) {
213+
metadata("duration", duration.toString())
214+
}
199215
}
200216
}
201217
}
@@ -207,6 +223,7 @@ public object LambdaTelemetry {
207223
connectionSettings: ConnectionSettings? = null,
208224
lambdaRuntime: LambdaRuntime? = null,
209225
inttype: Int,
226+
duration: Double? = null,
210227
passive: Boolean = false,
211228
`value`: Double = 1.0,
212229
createTime: Instant = Instant.now(),
@@ -221,6 +238,9 @@ public object LambdaTelemetry {
221238
metadata("lambdaRuntime", lambdaRuntime.toString())
222239
}
223240
metadata("inttype", inttype.toString())
241+
if(duration != null) {
242+
metadata("duration", duration.toString())
243+
}
224244
}
225245
}
226246
}
@@ -232,6 +252,7 @@ public object LambdaTelemetry {
232252
metadata: MetricEventMetadata,
233253
lambdaRuntime: LambdaRuntime? = null,
234254
inttype: Int,
255+
duration: Double? = null,
235256
passive: Boolean = false,
236257
`value`: Double = 1.0,
237258
createTime: Instant = Instant.now(),
@@ -246,6 +267,9 @@ public object LambdaTelemetry {
246267
metadata("lambdaRuntime", lambdaRuntime.toString())
247268
}
248269
metadata("inttype", inttype.toString())
270+
if(duration != null) {
271+
metadata("duration", duration.toString())
272+
}
249273
}
250274
}
251275
}
@@ -257,6 +281,7 @@ public object NoTelemetry {
257281
*/
258282
public fun metadata(
259283
project: Project?,
284+
duration: Double? = null,
260285
passive: Boolean = false,
261286
`value`: Double = 1.0,
262287
createTime: Instant = Instant.now(),
@@ -267,6 +292,9 @@ public object NoTelemetry {
267292
unit(Unit.NONE)
268293
value(value)
269294
passive(passive)
295+
if(duration != null) {
296+
metadata("duration", duration.toString())
297+
}
270298
}
271299
}
272300
}
@@ -276,6 +304,7 @@ public object NoTelemetry {
276304
*/
277305
public fun metadata(
278306
connectionSettings: ConnectionSettings? = null,
307+
duration: Double? = null,
279308
passive: Boolean = false,
280309
`value`: Double = 1.0,
281310
createTime: Instant = Instant.now(),
@@ -286,6 +315,9 @@ public object NoTelemetry {
286315
unit(Unit.NONE)
287316
value(value)
288317
passive(passive)
318+
if(duration != null) {
319+
metadata("duration", duration.toString())
320+
}
289321
}
290322
}
291323
}
@@ -295,6 +327,7 @@ public object NoTelemetry {
295327
*/
296328
public fun metadata(
297329
metadata: MetricEventMetadata,
330+
duration: Double? = null,
298331
passive: Boolean = false,
299332
`value`: Double = 1.0,
300333
createTime: Instant = Instant.now(),
@@ -305,6 +338,9 @@ public object NoTelemetry {
305338
unit(Unit.NONE)
306339
value(value)
307340
passive(passive)
341+
if(duration != null) {
342+
metadata("duration", duration.toString())
343+
}
308344
}
309345
}
310346
}
@@ -316,6 +352,7 @@ public object PassiveTelemetry {
316352
*/
317353
public fun passive(
318354
project: Project?,
355+
duration: Double? = null,
319356
passive: Boolean = true,
320357
`value`: Double = 1.0,
321358
createTime: Instant = Instant.now(),
@@ -326,6 +363,9 @@ public object PassiveTelemetry {
326363
unit(Unit.NONE)
327364
value(value)
328365
passive(passive)
366+
if(duration != null) {
367+
metadata("duration", duration.toString())
368+
}
329369
}
330370
}
331371
}
@@ -335,6 +375,7 @@ public object PassiveTelemetry {
335375
*/
336376
public fun passive(
337377
connectionSettings: ConnectionSettings? = null,
378+
duration: Double? = null,
338379
passive: Boolean = true,
339380
`value`: Double = 1.0,
340381
createTime: Instant = Instant.now(),
@@ -345,6 +386,9 @@ public object PassiveTelemetry {
345386
unit(Unit.NONE)
346387
value(value)
347388
passive(passive)
389+
if(duration != null) {
390+
metadata("duration", duration.toString())
391+
}
348392
}
349393
}
350394
}
@@ -354,6 +398,7 @@ public object PassiveTelemetry {
354398
*/
355399
public fun passive(
356400
metadata: MetricEventMetadata,
401+
duration: Double? = null,
357402
passive: Boolean = true,
358403
`value`: Double = 1.0,
359404
createTime: Instant = Instant.now(),
@@ -364,6 +409,9 @@ public object PassiveTelemetry {
364409
unit(Unit.NONE)
365410
value(value)
366411
passive(passive)
412+
if(duration != null) {
413+
metadata("duration", duration.toString())
414+
}
367415
}
368416
}
369417
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"types": [
3+
{
4+
"name": "duration",
5+
"type": "double",
6+
"description": "The duration of the operation in milliseconds"
7+
},
8+
{
9+
"name": "httpStatusCode",
10+
"type": "string",
11+
"description": "HTTP status code for the request (if any) associated with a metric."
12+
},
13+
{
14+
"name": "reason",
15+
"type": "string",
16+
"description": "Reason code or name for an event (when result=Succeeded) or error (when result=Failed). Unlike the `reasonDesc` field, this should be a stable/predictable name for a class of events or errors (typically the exception name, e.g. FileIOException)."
17+
},
18+
{
19+
"name": "reasonDesc",
20+
"type": "string",
21+
"description": "Error message detail. May contain arbitrary message details (unlike the `reason` field), but should be truncated (recommendation: 200 chars)."
22+
},
23+
{
24+
"name": "requestId",
25+
"type": "string",
26+
"description": "Request ID (if any) associated with a metric. For example, an event with `requestServiceType: s3` means that the request ID is associated with an S3 API call. Events that cover multiple API calls should use the request ID of the most recent call."
27+
},
28+
{
29+
"name": "requestServiceType",
30+
"type": "string",
31+
"description": "Per-request service identifier. Unlike `serviceType` (which describes the originator of the request), this describes the request itself."
32+
},
33+
{
34+
"name": "result",
35+
"allowedValues": [
36+
"Succeeded",
37+
"Failed",
38+
"Cancelled"
39+
],
40+
"description": "The result of the operation"
41+
}
42+
],
43+
"metrics": [
44+
{
45+
"name": "test_metric",
46+
"description": "Testing metric with global metadata fields",
47+
"metadata": []
48+
}
49+
]
50+
}

0 commit comments

Comments
 (0)