Skip to content

Commit

Permalink
JPERF-1408: Record PerformanceServerTiming
Browse files Browse the repository at this point in the history
  • Loading branch information
dagguh committed Oct 24, 2023
1 parent 958322c commit 1c0b4ad
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Dropping a requirement of a major version of a dependency is a new contract.
## [Unreleased]
[Unreleased]: https://github.com/atlassian/jira-actions/compare/release-3.23.1...master

### Added
- Add `PerformanceServerTiming`. Aid with [JPERF-1408].

[JPERF-1408]: https://ecosystem.atlassian.net/browse/JPERF-1408

## [3.23.1] - 2023-10-05
[3.23.1]: https://github.com/atlassian/jira-actions/compare/release-3.23.0...release-3.23.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,12 @@ class PerformanceResourceTiming internal constructor(
val responseEnd: Duration,
val transferSize: Long,
val encodedBodySize: Long,
val decodedBodySize: Long
val decodedBodySize: Long,
/**
* Represents the [serverTiming attribute](https://www.w3.org/TR/2023/WD-server-timing-20230411/#servertiming-attribute)
*
* @return Null if blocked, e.g. by same-origin policy.
* Empty if not blocked, but server didn't send any `Server-Timing` headers.
*/
val serverTiming: List<PerformanceServerTiming>?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.atlassian.performance.tools.jiraactions.api.w3c

import java.time.Duration

/**
* Represents the [PerformanceServerTiming](https://www.w3.org/TR/2023/WD-server-timing-20230411/#the-performanceservertiming-interface).
*/
class PerformanceServerTiming internal constructor(
val name: String,
val duration: Duration,
val description: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ internal class VerboseJsonFormat {
.add("transferSize", transferSize)
.add("encodedBodySize", encodedBodySize)
.add("decodedBodySize", decodedBodySize)
.apply {
if (serverTiming != null) {
add("serverTiming", serverTiming.map { serializeServerTiming(it) }.toJsonArray())
}
}
.build()
}

Expand All @@ -103,8 +108,10 @@ internal class VerboseJsonFormat {
responseEnd = getDuration("responseEnd"),
transferSize = getJsonNumber("transferSize").longValueExact(),
encodedBodySize = getJsonNumber("encodedBodySize").longValueExact(),
decodedBodySize = getJsonNumber("decodedBodySize").longValueExact()

decodedBodySize = getJsonNumber("decodedBodySize").longValueExact(),
serverTiming = getJsonArray("serverTiming")
?.map { it.asJsonObject() }
?.map { deserializeServerTiming(it) }
)
}

Expand Down Expand Up @@ -144,6 +151,26 @@ internal class VerboseJsonFormat {
)
}

private fun serializeServerTiming(
serverTiming: PerformanceServerTiming
): JsonObject = serverTiming.run {
Json.createObjectBuilder()
.add("name", serverTiming.name)
.add("duration", serverTiming.duration.toString())
.add("description", serverTiming.description)
.build()
}

private fun deserializeServerTiming(
json: JsonObject
): PerformanceServerTiming = json.run {
PerformanceServerTiming(
name = json.getString("name"),
duration = json.getDuration("duration"),
description = json.getString("description")
)
}

private fun List<JsonObject>.toJsonArray(): JsonArray {
val builder = Json.createArrayBuilder()
forEach { builder.add(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.jiraactions.w3c.harvesters

import com.atlassian.performance.tools.jiraactions.api.w3c.PerformanceEntry
import com.atlassian.performance.tools.jiraactions.api.w3c.PerformanceResourceTiming
import com.atlassian.performance.tools.jiraactions.api.w3c.PerformanceServerTiming
import org.openqa.selenium.JavascriptExecutor

internal fun getJsResourcesPerformance(javascript: JavascriptExecutor): List<PerformanceResourceTiming> {
Expand Down Expand Up @@ -42,7 +43,8 @@ internal fun parsePerformanceResourceTiming(
responseEnd = parseTimestamp(map["responseEnd"]),
transferSize = map["transferSize"] as Long,
encodedBodySize = map["encodedBodySize"] as Long,
decodedBodySize = map["decodedBodySize"] as Long
decodedBodySize = map["decodedBodySize"] as Long,
serverTiming = map["serverTiming"]?.let { parseServerTimings(it) }
)
}

Expand All @@ -59,3 +61,25 @@ private fun parsePerformanceEntry(
duration = parseTimestamp(map["duration"])
)
}

private fun parseServerTimings(
jsServerTimings: Any
): List<PerformanceServerTiming> {
if (jsServerTimings !is List<*>) {
throw Exception("Unexpected non-list JavaScript value: $jsServerTimings")
}
return jsServerTimings.map { parseServerTiming(it) }
}

private fun parseServerTiming(
map: Any?
): PerformanceServerTiming {
if (map !is Map<*, *>) {
throw Exception("Unexpected non-map JavaScript value: $map")
}
return PerformanceServerTiming(
name = map["name"] as String,
duration = parseTimestamp(map["duration"]),
description = map["description"] as String
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ class AppendableActionMetricOutputTest {
responseEnd = ofMillis(391),
transferSize = 12956,
encodedBodySize = 11818,
decodedBodySize = 59535
decodedBodySize = 59535,
serverTiming = listOf(
PerformanceServerTiming("userCache", ofMillis(13), "miss"),
PerformanceServerTiming("sqlTotal", ofMillis(40), "")
)
),
unloadEventStart = ofMillis(210),
unloadEventEnd = ofMillis(210),
Expand Down Expand Up @@ -161,7 +165,8 @@ class AppendableActionMetricOutputTest {
responseEnd = ofMillis(982),
transferSize = 3524,
encodedBodySize = 3032,
decodedBodySize = 24340
decodedBodySize = 24340,
serverTiming = null
)
),
elements = listOf(
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/action-metrics.jpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
{"label":"Create Issue","result":"OK","duration":"PT2M26.786S","start":"2017-12-12T10:38:36.275Z","virtualUser":"0e5ead7c-dc9c-4f48-854d-5200a1a71058"}
{"label":"View Board","result":"OK","duration":"PT26.786S","start":"2017-12-12T10:38:36.277Z","virtualUser":"0e5ead7c-dc9c-4f48-854d-5200a1a71058","observation":{"issues":5}}
{"label":"View Board","result":"OK","duration":"PT26.786S","start":"2017-12-12T10:38:36.277Z","virtualUser":"0e5ead7c-dc9c-4f48-854d-5200a1a71058","observation":{"issues":6}}
{"label":"Log In","result":"OK","duration":"PT3.86S","start":"2018-12-18T16:10:23.088Z","virtualUser":"0e5ead7c-dc9c-4f48-854d-5200a1a71058","drilldown":{"navigations":[{"resource":{"entry":{"name":"http://3.120.138.107:8080/","entryType":"navigation","startTime":"PT0S","duration":"PT1.74S"},"initiatorType":"navigation","nextHopProtocol":"http/1.1","workerStart":"PT0S","redirectStart":"PT0.016S","redirectEnd":"PT0.126S","fetchStart":"PT0.126S","domainLookupStart":"PT0.126S","domainLookupEnd":"PT0.126S","connectStart":"PT0.126S","connectEnd":"PT0.126S","secureConnectionStart":"PT0S","requestStart":"PT0.126S","responseStart":"PT0.208S","responseEnd":"PT0.391S","transferSize":12956,"encodedBodySize":11818,"decodedBodySize":59535},"unloadEventStart":"PT0.21S","unloadEventEnd":"PT0.21S","domInteractive":"PT0.805S","domContentLoadedEventStart":"PT0.805S","domContentLoadedEventEnd":"PT0.83S","domComplete":"PT1.73S","loadEventStart":"PT1.73S","loadEventEnd":"PT1.74S","type":"NAVIGATE","redirectCount":1}],"resources":[{"entry":{"name":"http://3.120.138.107:8080/rest/gadget/1.0/issueTable/jql?num=10&tableContext=jira.table.cols.dashboard&addDefault=true&enableSorting=true&paging=true&showActions=true&jql=assignee+%3D+currentUser()+AND+resolution+%3D+unresolved+ORDER+BY+priority+DESC%2C+created+ASC&sortBy=&startIndex=0&_=1545149426038","entryType":"resource","startTime":"PT0.903S","duration":"PT0.078S"},"initiatorType":"xmlhttprequest","nextHopProtocol":"http/1.1","workerStart":"PT0S","redirectStart":"PT0S","redirectEnd":"PT0S","fetchStart":"PT0.903S","domainLookupStart":"PT0.903S","domainLookupEnd":"PT0.903S","connectStart":"PT0.903S","connectEnd":"PT0.903S","secureConnectionStart":"PT0S","requestStart":"PT0.904S","responseStart":"PT0.981S","responseEnd":"PT0.982S","transferSize":3524,"encodedBodySize":3032,"decodedBodySize":24340}],"elements":[{"renderTime":"PT1.147S","loadTime":"PT0S","identifier":"app-header","naturalWidth":0,"naturalHeight":0,"id":"home_link","url":""}]}}
{"label":"Log In","result":"OK","duration":"PT3.86S","start":"2018-12-18T16:10:23.088Z","virtualUser":"0e5ead7c-dc9c-4f48-854d-5200a1a71058","drilldown":{"navigations":[{"resource":{"entry":{"name":"http://3.120.138.107:8080/","entryType":"navigation","startTime":"PT0S","duration":"PT1.74S"},"initiatorType":"navigation","nextHopProtocol":"http/1.1","workerStart":"PT0S","redirectStart":"PT0.016S","redirectEnd":"PT0.126S","fetchStart":"PT0.126S","domainLookupStart":"PT0.126S","domainLookupEnd":"PT0.126S","connectStart":"PT0.126S","connectEnd":"PT0.126S","secureConnectionStart":"PT0S","requestStart":"PT0.126S","responseStart":"PT0.208S","responseEnd":"PT0.391S","transferSize":12956,"encodedBodySize":11818,"decodedBodySize":59535,"serverTiming":[{"name":"userCache","duration":"PT0.013S","description":"miss"},{"name":"sqlTotal","duration":"PT0.04S","description":""}]},"unloadEventStart":"PT0.21S","unloadEventEnd":"PT0.21S","domInteractive":"PT0.805S","domContentLoadedEventStart":"PT0.805S","domContentLoadedEventEnd":"PT0.83S","domComplete":"PT1.73S","loadEventStart":"PT1.73S","loadEventEnd":"PT1.74S","type":"NAVIGATE","redirectCount":1}],"resources":[{"entry":{"name":"http://3.120.138.107:8080/rest/gadget/1.0/issueTable/jql?num=10&tableContext=jira.table.cols.dashboard&addDefault=true&enableSorting=true&paging=true&showActions=true&jql=assignee+%3D+currentUser()+AND+resolution+%3D+unresolved+ORDER+BY+priority+DESC%2C+created+ASC&sortBy=&startIndex=0&_=1545149426038","entryType":"resource","startTime":"PT0.903S","duration":"PT0.078S"},"initiatorType":"xmlhttprequest","nextHopProtocol":"http/1.1","workerStart":"PT0S","redirectStart":"PT0S","redirectEnd":"PT0S","fetchStart":"PT0.903S","domainLookupStart":"PT0.903S","domainLookupEnd":"PT0.903S","connectStart":"PT0.903S","connectEnd":"PT0.903S","secureConnectionStart":"PT0S","requestStart":"PT0.904S","responseStart":"PT0.981S","responseEnd":"PT0.982S","transferSize":3524,"encodedBodySize":3032,"decodedBodySize":24340}],"elements":[{"renderTime":"PT1.147S","loadTime":"PT0S","identifier":"app-header","naturalWidth":0,"naturalHeight":0,"id":"home_link","url":""}]}}

0 comments on commit 1c0b4ad

Please sign in to comment.