You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by jo...@apache.org on 2022/03/27 19:28:14 UTC
[isis] 03/03: ISIS-2957 ResponseHandler chain based on stats
This is an automated email from the ASF dual-hosted git repository.
joergrade pushed a commit to branch ISIS-2957
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 5c906d647d520b20ff03fd10fd169a79e5785dbb
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Sun Mar 27 21:27:27 2022 +0200
ISIS-2957 ResponseHandler chain based on stats
---
.../kroviz/core/aggregator/ActionDispatcher.kt | 2 +-
.../isis/client/kroviz/handler/BaseHandler.kt | 2 +
.../isis/client/kroviz/handler/PlainHandlers.kt | 7 -
.../isis/client/kroviz/handler/ResponseHandler.kt | 81 ++++---
.../isis/client/kroviz/handler/TObjectHandler.kt | 41 ++++
.../apache/isis/client/kroviz/ui/core/RoMenuBar.kt | 20 +-
.../isis/client/kroviz/ui/core/SessionManager.kt | 12 ++
.../client/kroviz/ui/panel/DynamicMenuBuilder.kt | 6 -
.../isis/client/kroviz/ui/panel/EventPieChart.kt | 237 ---------------------
.../apache/isis/client/kroviz/utils/IconManager.kt | 1 -
10 files changed, 114 insertions(+), 295 deletions(-)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ActionDispatcher.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ActionDispatcher.kt
index 4ed1d7c..91ab86e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ActionDispatcher.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ActionDispatcher.kt
@@ -51,7 +51,7 @@ class ActionDispatcher(private val at: Point = Point(100, 100)) : BaseAggregator
to is Restful -> {}
else -> {
console.log(to)
- throw Throwable("[ActionDispatcher.update] ${to!!::class.simpleName}")
+// throw Throwable("[ActionDispatcher.update] ${to!!::class.simpleName}")
}
}
}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
index dd57b46..83d1b2a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
@@ -21,6 +21,7 @@ package org.apache.isis.client.kroviz.handler
import org.apache.isis.client.kroviz.core.event.LogEntry
import org.apache.isis.client.kroviz.to.TransferObject
import org.apache.isis.client.kroviz.ui.core.Constants
+ import org.apache.isis.client.kroviz.ui.core.SessionManager
/**
* Handle responses to XmlHttpRequests asynchronously,
@@ -76,6 +77,7 @@ abstract class BaseHandler {
}
open fun update() {
+ SessionManager.logInvocation(this)
logEntry.getAggregator()?.update(logEntry, Constants.subTypeJson)
}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/PlainHandlers.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/PlainHandlers.kt
index 234db7a..069bce9 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/PlainHandlers.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/PlainHandlers.kt
@@ -63,13 +63,6 @@ class ServiceHandler : BaseHandler() {
}
}
-class TObjectHandler : BaseHandler() {
-
- override fun parse(response: String): TransferObject {
- return Json.decodeFromString<TObject>(response)
- }
-}
-
class UserHandler : BaseHandler() {
override fun parse(response: String): TransferObject {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
index f777f2d..b4ae3f5 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResponseHandler.kt
@@ -27,56 +27,55 @@ import org.apache.isis.client.kroviz.core.event.LogEntry
object ResponseHandler {
private var delegate: BaseHandler
- //IMPROVE sequence of handlers should follow frequency of invocation in order to minimize the time taken by unneeded calls to 'canHandle()'
- private var _0 = RestfulHandler()
- private var _0a = VersionHandler()
- private var _0b = DomainTypesHandler()
- private var _1 = MenuBarsHandler()
- private var _2 = ActionHandler()
- private var _3 = ServiceHandler()
- private var _4 = ResultListHandler()
- private var _4a = ResultObjectHandler()
- private var _4b = ResultValueHandler()
- private var _6 = LayoutHandler()
- private var _6a = LayoutXmlHandler()
- private var _7 = CollectionHandler()
- private var _7a = PropertyHandler()
- private var _7b = TObjectHandler()
- private var _8 = MemberHandler()
- private var _9 = HttpErrorHandler()
- private var _9a = Http401ErrorHandler()
- private var _10 = UserHandler()
- private var _13 = DomainTypeHandler()
- private var _14 = DiagramHandler()
- private var _15 = IconHandler()
+ //sequence of handlers follows frequency of invocation (demo execute all menu actions)
+ //IMPROVE by dynamic lookup at runtime?
+ private var _1 = TObjectHandler()
+ private var _2 = LayoutXmlHandler()
+ private var _3 = CollectionHandler()
+ private var _4 = ActionHandler()
+ private var _5 = HttpErrorHandler()
+ private var _6 = RestfulHandler()
+ private var _7 = VersionHandler()
+ private var _8 = MenuBarsHandler()
+
+ private var _9 = DomainTypesHandler()
+ private var _10 = ServiceHandler()
+ private var _11 = ResultListHandler()
+ private var _12 = ResultObjectHandler()
+ private var _13 = ResultValueHandler()
+ private var _14 = LayoutHandler()
+ private var _15 = PropertyHandler()
+ private var _16 = MemberHandler()
+ private var _17 = Http401ErrorHandler()
+ private var _18 = UserHandler()
+ private var _19 = DomainTypeHandler()
+ private var _20 = DiagramHandler()
+ private var _21 = IconHandler()
private var last = DefaultHandler()
init {
- delegate = _0
- _0.successor = _0a
- _0a.successor = _0b
- _0b.successor = _1
+ delegate = _1
_1.successor = _2
_2.successor = _3
_3.successor = _4
- _4.successor = _4a
- _4a.successor = _4b
- _4b.successor = _6
-// _5.successor = _6
- _6.successor = _6a
- _6a.successor = _7
- _7.successor = _7a
- _7a.successor = _7b
- _7b.successor = _8
+ _4.successor = _5
+ _5.successor = _6
+ _6.successor = _7
+ _7.successor = _8
_8.successor = _9
- _9.successor = _9a
- _9a.successor = _10
- _10.successor = _13
-// _11.successor = _12
-// _12.successor = _13
+ _9.successor = _10
+ _10.successor = _11
+ _11.successor = _12
+ _12.successor = _13
_13.successor = _14
_14.successor = _15
- _15.successor = last
+ _15.successor = _16
+ _16.successor = _17
+ _17.successor = _18
+ _18.successor = _19
+ _19.successor = _20
+ _20.successor = _21
+ _21.successor = last
}
fun handle(logEntry: LogEntry) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/TObjectHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/TObjectHandler.kt
new file mode 100644
index 0000000..36806fd
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/TObjectHandler.kt
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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 org.apache.isis.client.kroviz.handler
+
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import org.apache.isis.client.kroviz.to.TObject
+import org.apache.isis.client.kroviz.to.TransferObject
+
+class TObjectHandler : BaseHandler() {
+
+ override fun canHandle(response: String): Boolean {
+ val urlPath = logEntry.url.split("restful")
+ val path = urlPath[1]
+ if (path != null && path.length > 1) {
+ return super.canHandle(response)
+ }
+ return false
+ }
+
+ override fun parse(response: String): TransferObject {
+ return Json.decodeFromString<TObject>(response)
+ }
+
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoMenuBar.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoMenuBar.kt
index 534f8a0..7e91a47 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoMenuBar.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoMenuBar.kt
@@ -33,8 +33,13 @@ import io.kvision.utils.px
import org.apache.isis.client.kroviz.core.Session
import org.apache.isis.client.kroviz.core.event.ResourceProxy
import org.apache.isis.client.kroviz.to.mb.Menubars
-import org.apache.isis.client.kroviz.ui.dialog.*
-import org.apache.isis.client.kroviz.ui.panel.*
+import org.apache.isis.client.kroviz.ui.dialog.About
+import org.apache.isis.client.kroviz.ui.dialog.EventDialog
+import org.apache.isis.client.kroviz.ui.dialog.LoginPrompt
+import org.apache.isis.client.kroviz.ui.dialog.SvgInline
+import org.apache.isis.client.kroviz.ui.panel.GeoMap
+import org.apache.isis.client.kroviz.ui.panel.ImageSample
+import org.apache.isis.client.kroviz.ui.panel.SvgMap
import org.apache.isis.client.kroviz.utils.IconManager
import org.apache.isis.client.kroviz.utils.Point
@@ -186,6 +191,11 @@ class RoMenuBar : SimplePanel() {
buildMenuEntry(testTitle, "Test", { this.executeAllMenuBarActions() })
)
+ val stats = "Log Handler Stats"
+ mainMenu.add(
+ buildMenuEntry(stats, "Console", { this.logStats() })
+ )
+
/*
val testTitle = "Test"
mainMenu.add(
@@ -234,4 +244,10 @@ class RoMenuBar : SimplePanel() {
}
}
+ fun logStats() {
+ SessionManager.responseHandlerStatistics.forEach {
+ console.log("${it.key} -> ${it.value}")
+ }
+ }
+
}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/SessionManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/SessionManager.kt
index 98496dc..173177c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/SessionManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/SessionManager.kt
@@ -20,6 +20,7 @@ package org.apache.isis.client.kroviz.ui.core
import org.apache.isis.client.kroviz.core.Session
import org.apache.isis.client.kroviz.core.event.EventStore
+import org.apache.isis.client.kroviz.handler.BaseHandler
/**
* Handle multiple Sessions
@@ -29,6 +30,7 @@ object SessionManager {
private val sessions = mutableSetOf<Session>()
private val eventStore = EventStore()
private var activeSession: Session? = null
+ val responseHandlerStatistics = mutableMapOf<String, Int>()
fun getBaseUrl(): String? {
return activeSession?.baseUrl
@@ -69,4 +71,14 @@ object SessionManager {
menuBar.updateIcon(activeSession!!)
}
+ fun logInvocation(responseHandler: BaseHandler) {
+ val className = responseHandler::class.simpleName!!
+ val value = responseHandlerStatistics.get(className)
+ if (value == null) {
+ responseHandlerStatistics.put(className, 1)
+ } else {
+ responseHandlerStatistics.put(className, value + 1)
+ }
+ }
+
}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/DynamicMenuBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/DynamicMenuBuilder.kt
index 87ce81e..f193d73 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/DynamicMenuBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/DynamicMenuBuilder.kt
@@ -62,12 +62,6 @@ class DynamicMenuBuilder {
})
menu.add(bubble)
- val pieTitle = "Pie Chart"
- val pie = buildMenuEntry(pieTitle, pieTitle, {
- ViewManager.add(pieTitle, EventPieChart())
- })
- menu.add(pie)
-
return menu.toTypedArray().asDynamic()
}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventPieChart.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventPieChart.kt
deleted file mode 100644
index 87ae40a..0000000
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/panel/EventPieChart.kt
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * http://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 org.apache.isis.client.kroviz.ui.panel
-
-import io.kvision.chart.*
-import io.kvision.chart.js.LegendItem
-import io.kvision.core.Col
-import io.kvision.core.Color
-import io.kvision.core.CssSize
-import io.kvision.core.UNIT
-import io.kvision.panel.SimplePanel
-import io.kvision.utils.obj
-import org.apache.isis.client.kroviz.core.event.LogEntry
-import org.apache.isis.client.kroviz.ui.core.SessionManager
-import org.apache.isis.client.kroviz.utils.StringUtils
-import kotlin.math.pow
-
-/*
-new Chart(document.getElementById("doughnut-chart"), {
- type: 'doughnut',
- data: {
- labels: ["Africa", "Asia", "Europe", "Latin America", "North America"],
- datasets: [
- {
- label: "Population (millions)",
- backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
- data: [2478,5267,734,784,433]
- }
- ]
- },
- options: {
- title: {
- display: true,
- text: 'Predicted world population (millions) in 2050'
- }
- }
-});
- */
-
-class EventPieChart : SimplePanel() {
- private val model = SessionManager.getEventStore()
- private var chart: Chart
-
- init {
- width = CssSize(90, UNIT.vw)
- chart = chart(
- configuration = buildConfiguration()
- )
- }
-
- private fun buildConfiguration(): Configuration {
- fun buildToolTipList(): List<String> {
- val labelList = mutableListOf<String>()
- model.log.forEachIndexed { i, it ->
- val l = it.buildToolTip(i)
- labelList.add(l)
- }
- return labelList
- }
-
- val dataSetsList = listOf(buildDataSets())
- return Configuration(
- type = ChartType.DOUGHNUT,
- dataSets = dataSetsList,
- labels = buildToolTipList(),
- options = buildChartOptions(),
- )
- }
-
- private fun buildChartOptions(): ChartOptions {
- fun buildLegend(): LegendOptions {
- fun buildLegendLabelList(): Array<LegendItem> {
- val legendLabelList = mutableListOf<LegendItem>()
- label2color.forEach {
- val li = obj {
- text = it.key
- fillStyle = it.value
- }
- legendLabelList.add(li as LegendItem)
- }
- val error = obj {
- text = "error"
- fillStyle = TRANSPARENT
- strokeStyle = ERROR_COLOR
- }
- legendLabelList.add(error as LegendItem)
- val size = obj {
- text = "bubble size ^= response size"
- fillStyle = TRANSPARENT
- strokeStyle = TRANSPARENT
- }
- legendLabelList.add(size as LegendItem)
- return legendLabelList.toTypedArray()
- }
-
- return LegendOptions(
- display = true,
- position = Position.RIGHT,
- labels = LegendLabelOptions(generateLabels = {
- buildLegendLabelList()
- }),
- title = LegendTitleOptions(text = "Parallel Requests", display = true),
- )
- }
-
- return ChartOptions(
- plugins = PluginsOptions(
- title = TitleOptions(
- text = listOf("Request Duration over Time by Request Parallelism and Response Size"),
- display = true
- ),
- legend = buildLegend(),
- ),
- showLine = true,
- scales = mapOf(
- "x" to ChartScales(
- title = ScaleTitleOptions(
- text = "Time since Connect(ms)", display = true
- )
- ),
- "y" to ChartScales(
- title = ScaleTitleOptions(text = "duration in ms (log)", display = true),
- type = ScalesType.LOGARITHMIC
- )
- )
- )
- }
-
- private fun buildDataSets(): DataSets {
- fun buildBgColorList(): List<Color> {
- val bgColorList = mutableListOf<Color>()
- model.log.forEach {
- val c = it.determineBubbleColor()
- bgColorList.add(c)
- }
- return bgColorList
- }
-
- fun buildBorderColorList(): List<Color> {
- val borderColorList = mutableListOf<Color>()
- model.log.forEach {
- when {
- it.isError() -> borderColorList.add(ERROR_COLOR)
- else -> borderColorList.add(Color.name(Col.LIGHTGRAY))
- }
- }
- return borderColorList
- }
-
- /**
- * The term DataSets is severely miss leading:
- * 1. a plural form is used (where actually a singular would be more appropriate) -> "a DataSets"
- * 2. datasets are used inside datasets, data inside data
- */
- fun buildDataSetsList(): List<DataSets> {
- val dataSetsList = mutableListOf<DataSets>()
- model.log.forEach {
- // val d = it //.buildData()
- // dataSetsList.add(d)
- }
- return dataSetsList
- }
-
- return DataSets(
- backgroundColor = buildBgColorList(),
- borderColor = buildBorderColorList(),
- data = buildDataSetsList(),
- )
- }
-
- private fun LogEntry.buildToolTip(index: Int): String {
- val size = StringUtils.format(this.responseLength)
- val title = StringUtils.shortTitle(this.title)
- return title +
- "\nseq.no.: $index" +
- "\nparallel runs: ${this.runningAtStart}" +
- "\nrsp.len.: $size" +
- "\ntype: ${this.type}"
- }
-
- private fun LogEntry.calculateBubbleSize(): Int {
- val i = responseLength
- return i.toDouble().pow(1 / 3.toDouble()).toInt()
- }
-
- private fun LogEntry.determineBubbleColor(): Color {
- val i = runningAtStart
- return when {
- (i >= 0) && (i <= 4) -> LIGHT_BLUE
- (i > 4) && (i <= 8) -> DARK_BLUE
- (i > 8) && (i <= 16) -> GREEN
- (i > 16) && (i <= 32) -> YELLOW
- (i > 32) && (i <= 64) -> RED
- (i > 64) && (i <= 128) -> RED_VIOLET
- else -> VIOLET
- }
- }
-
- companion object {
- val TRANSPARENT = Color.rgba(0xFF, 0xFF, 0xFF, 0x00)
- val ERROR_COLOR = Color.rgba(0xFF, 0x00, 0x00, 0xFF)
- val LIGHT_BLUE = Color.rgba(0x4B, 0xAC, 0xC6, 0x80)
- val DARK_BLUE = Color.rgba(0x4F, 0x81, 0xBD, 0x80)
- val GREEN = Color.rgba(0x9B, 0xBB, 0x59, 0x80)
- val YELLOW = Color.rgba(0xF7, 0x96, 0x46, 0x80)
- val RED = Color.rgba(0xC0, 0x50, 0x4D, 0x80)
- val RED_VIOLET = Color.rgba(0xA0, 0x5A, 0x78, 0x80)
- val VIOLET = Color.rgba(0x80, 0x64, 0xA2, 0x80)
-
- val label2color = mapOf(
- "0 .. 4" to LIGHT_BLUE,
- "5 .. 8" to DARK_BLUE,
- "9 .. 16" to GREEN,
- "17 .. 32" to YELLOW,
- "33 .. 64" to RED,
- "65 .. 128" to RED_VIOLET,
- ">= 129" to VIOLET
- )
- }
-
-}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/IconManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/IconManager.kt
index 3e56d72..b48b67e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/IconManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/utils/IconManager.kt
@@ -88,7 +88,6 @@ object IconManager {
"OK" to "check",
"Open" to "book",
"Other" to "asterisk",
- "Pie" to "pie-chart",
"Pin" to "map-pin",
"Primitives" to "hashtag",
"Properties" to "indent",