Skip to content

Commit

Permalink
JPERF-1454 Add timeOrigin
Browse files Browse the repository at this point in the history
  • Loading branch information
mgrzaslewicz authored and dagguh committed Jan 12, 2024
1 parent c58d3a2 commit 49467ee
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 8 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.26.0...master

### Added
- Add `RecordedPerformanceEntries.timeOrigin`. Help with [JPERF-1454].

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

## [3.26.0] - 2023-11-30
[3.26.0]: https://github.com/atlassian/jira-actions/compare/release-3.25.0...release-3.26.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.atlassian.performance.tools.jiraactions.api.w3c
import com.atlassian.performance.tools.jiraactions.w3c.harvesters.getJsElementsPerformance
import com.atlassian.performance.tools.jiraactions.w3c.harvesters.getJsNavigationsPerformance
import com.atlassian.performance.tools.jiraactions.w3c.harvesters.getJsResourcesPerformance
import com.atlassian.performance.tools.jiraactions.w3c.harvesters.parseInstantMilli
import org.openqa.selenium.JavascriptExecutor
import java.time.Instant

/**
* Obtains entries from [javascript].
Expand All @@ -24,10 +26,15 @@ class JavascriptW3cPerformanceTimeline private constructor(
return RecordedPerformanceEntries(
navigations = if (recordNavigation) getJsNavigationsPerformance(javascript) else emptyList(),
resources = if (recordResources) getJsResourcesPerformance(javascript) else emptyList(),
elements = if (recordElements) getJsElementsPerformance(javascript) else emptyList()
elements = if (recordElements) getJsElementsPerformance(javascript) else emptyList(),
timeOrigin = getTimeOrigin(javascript)
)
}

private fun getTimeOrigin(javascript: JavascriptExecutor): Instant {
return parseInstantMilli(javascript.executeScript("return window.performance.timeOrigin;"))
}

class Builder(
private var javascript: JavascriptExecutor
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package com.atlassian.performance.tools.jiraactions.api.w3c

import java.time.Instant

/**
* Holds interesting recorded performance entries.
* They share the same timeline and can be cross-examined.
*/
class RecordedPerformanceEntries internal constructor(
val navigations: List<PerformanceNavigationTiming>,
val resources: List<PerformanceResourceTiming>,
val elements: List<PerformanceElementTiming>
val elements: List<PerformanceElementTiming>,
val timeOrigin: Instant?
) {

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.atlassian.performance.tools.jiraactions.w3c
import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.w3c.*
import java.time.Duration
import javax.json.Json
import java.time.Instant
import javax.json.JsonArray
import javax.json.JsonObject

Expand All @@ -16,6 +16,11 @@ internal class VerboseJsonFormat {
.add("navigations", navigations.map { serializeNavigationTiming(it) }.toJsonArray())
.add("resources", resources.map { serializeResourceTiming(it) }.toJsonArray())
.add("elements", (elements.map { serializeElementTiming(it) }).toJsonArray())
.apply {
if (timeOrigin != null) {
add("timeOrigin", timeOrigin.toString())
}
}
.build()
}

Expand All @@ -32,7 +37,8 @@ internal class VerboseJsonFormat {
elements = getJsonArray("elements")
?.map { it.asJsonObject() }
?.map { deserializeElementTiming(it) }
?: emptyList()
?: emptyList(),
timeOrigin = getJsonString("timeOrigin")?.let { Instant.parse(it.string) }
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.atlassian.performance.tools.jiraactions.w3c.harvesters

import java.time.Duration
import java.time.Instant
import kotlin.math.floor

internal fun parseTimestamp(
timestamp: Any?
Expand All @@ -9,3 +11,17 @@ internal fun parseTimestamp(
is Double -> Duration.ofMillis(timestamp.toLong())
else -> throw Exception("Cannot parse timestamp from $timestamp")
}

internal fun parseInstantMilli(
milli: Any?
): Instant = when (milli) {
is Long -> Instant.ofEpochMilli(milli)
is Double -> {
val wholeMilli: Long = floor(milli).toLong()
val remainderMilli: Double = milli - wholeMilli
val remainderNanos: Long = (remainderMilli * 1_000_000).toLong()
Instant.ofEpochMilli(wholeMilli).plusNanos(remainderNanos)
}

else -> throw Exception("Cannot parse instant from $milli")
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class ActionMeterTest {
result: ActionResult,
duration: Duration,
start: Instant,
entries: RecordedPerformanceEntries? = RecordedPerformanceEntries(emptyList(), emptyList(), emptyList())
entries: RecordedPerformanceEntries? = RecordedPerformanceEntries(emptyList(), emptyList(), emptyList(), null)
): ActionMetric = ActionMetric.Builder(
label = actionType.label,
result = result,
Expand All @@ -83,7 +83,7 @@ class ActionMeterTest {
@Test
fun shouldMeasureErrors() {
val output = CollectionActionMetricOutput(mutableListOf())
val entries = RecordedPerformanceEntries(emptyList(), emptyList(), emptyList())
val entries = RecordedPerformanceEntries(emptyList(), emptyList(), emptyList(), null)
val actionMeter = ActionMeter.Builder(
output = output
)
Expand Down Expand Up @@ -112,7 +112,7 @@ class ActionMeterTest {
val clock = TickingClock(start, tick)
val output = CollectionActionMetricOutput(mutableListOf())
val w3cPerformanceTimelineMock =
HardcodedTimeline(RecordedPerformanceEntries(emptyList(), emptyList(), emptyList()))
HardcodedTimeline(RecordedPerformanceEntries(emptyList(), emptyList(), emptyList(), null))
val actionMeter = ActionMeter.Builder(
output = output
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class AppendableActionMetricOutputTest {
id = "home_link",
url = ""
)
)
),
timeOrigin = null
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import org.openqa.selenium.By
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.OutputType
import org.openqa.selenium.remote.RemoteWebDriver
import java.time.LocalDate
import java.time.ZoneId
import java.time.ZonedDateTime

abstract class AbstractJiraCoreScenario {
private val logger: Logger = LogManager.getLogger(this::class.java)
Expand Down Expand Up @@ -98,6 +101,10 @@ abstract class AbstractJiraCoreScenario {
private fun assertDrilldown(metrics: List<ActionMetric>) {
val navigationsPerMetric = metrics.map { it.drilldown?.navigations ?: emptyList() }
assertThat(navigationsPerMetric).`as`("all results contain timings in drilldown").hasSize(metrics.size)
val timeOrigin = metrics[0].drilldown?.timeOrigin
assertThat(timeOrigin).isNotNull()
val dateTimeOrigin = ZonedDateTime.ofInstant(timeOrigin, ZoneId.of("UTC"))
assertThat(dateTimeOrigin.year).isBetween(2024, 2060)
}

private fun goToServices(driver: RemoteWebDriver, jira: Jira) {
Expand Down

0 comments on commit 49467ee

Please sign in to comment.