Skip to content

Commit 9fa4f11

Browse files
committed
Feature/no data yet panel per span (#408)
1 parent 46b9dc3 commit 9fa4f11

File tree

4 files changed

+143
-48
lines changed

4 files changed

+143
-48
lines changed

ide-common/src/main/java/org/digma/intellij/plugin/insights/view/InsightsViewBuilder.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package org.digma.intellij.plugin.insights.view;
22

3+
import com.google.common.collect.Sets;
34
import com.intellij.openapi.project.Project;
45
import org.digma.intellij.plugin.model.discovery.MethodInfo;
6+
import org.digma.intellij.plugin.model.discovery.SpanInfo;
57
import org.digma.intellij.plugin.model.rest.insights.CodeObjectInsight;
68
import org.digma.intellij.plugin.model.rest.insights.EndpointInsight;
79
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema;
10+
import org.digma.intellij.plugin.model.rest.insights.SpanInsight;
11+
import org.digma.intellij.plugin.ui.model.insights.InsightGroupListViewItem;
12+
import org.digma.intellij.plugin.ui.model.insights.InsightGroupType;
13+
import org.digma.intellij.plugin.ui.model.insights.NoDataYet;
14+
import org.digma.intellij.plugin.ui.model.listview.GroupListViewItem;
815
import org.digma.intellij.plugin.ui.model.listview.ListViewItem;
916
import org.digma.intellij.plugin.view.ListViewBuilder;
1017
import org.digma.intellij.plugin.view.ListViewItemBuilder;
@@ -13,6 +20,8 @@
1320
import java.util.ArrayList;
1421
import java.util.List;
1522
import java.util.Objects;
23+
import java.util.Set;
24+
import java.util.stream.Collectors;
1625

1726
public class InsightsViewBuilder extends ListViewBuilder {
1827

@@ -32,15 +41,49 @@ public List<ListViewItem<?>> build(Project project, @NotNull MethodInfo methodIn
3241

3342
codeObjectInsights.forEach(insight -> {
3443
final ListViewItemBuilder<CodeObjectInsight> builder = (ListViewItemBuilder<CodeObjectInsight>) buildersHolder.getBuilder(insight.getType());
35-
final List<ListViewItem<?>> insightListItems = builder.build(project,methodInfo, insight, groupManager);
44+
final List<ListViewItem<?>> insightListItems = builder.build(project, methodInfo, insight, groupManager);
3645
allItems.addAll(insightListItems);
3746
});
3847

48+
Set<String> spansThatHaveNoInsight = findLocalSpansThatHaveNoInsights(methodInfo, codeObjectInsights);
49+
if (!spansThatHaveNoInsight.isEmpty()) {
50+
buildItemsForNoDataYet(spansThatHaveNoInsight);
51+
}
52+
3953
allItems.addAll(groupManager.getGroupItems());
4054

4155
return sortDistinct(allItems);
4256
}
4357

58+
protected static Set<String> findLocalSpansThatHaveNoInsights(@NotNull MethodInfo methodInfo, List<? extends CodeObjectInsight> codeObjectInsights) {
59+
60+
Set<String> spansOfMethod = methodInfo.getSpans().stream()
61+
.map(SpanInfo::getName)
62+
.collect(Collectors.toSet());
63+
64+
Set<String> spansThatHaveInsights = codeObjectInsights.stream()
65+
.filter(it -> it instanceof SpanInsight)
66+
.map(it -> (SpanInsight) it)
67+
.map(SpanInsight::spanName)// span name without instrumentation library
68+
.collect(Collectors.toSet());
69+
70+
// spansOfMethod minus spansThatHaveInsights
71+
Set<String> spansThatHaveNoInsights = Sets.difference(spansOfMethod, spansThatHaveInsights).immutableCopy();
72+
73+
return spansThatHaveNoInsights;
74+
}
75+
76+
protected void buildItemsForNoDataYet(Set<String> spansThatHaveNoInsight) {
77+
for (String currSpanName : spansThatHaveNoInsight) {
78+
String groupId = currSpanName;
79+
GroupListViewItem theGroup = groupManager.getOrCreateGroup(
80+
groupId, () -> new InsightGroupListViewItem(currSpanName, InsightGroupType.Span, ""));
81+
82+
ListViewItem<NoDataYet> itemOfNoDataYet = new ListViewItem<>(new NoDataYet(), 222);
83+
theGroup.addItem(itemOfNoDataYet);
84+
}
85+
}
86+
4487
protected void adjustToHttpIfNeeded(final List<? extends CodeObjectInsight> codeObjectInsights) {
4588
codeObjectInsights
4689
.stream()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package org.digma.intellij.plugin.ui.model.insights
2+
3+
class NoDataYet

src/main/kotlin/org/digma/intellij/plugin/ui/list/insights/InsightsCommon.kt

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,22 @@ import java.awt.event.MouseEvent
2727
import java.time.Duration
2828
import java.time.LocalDateTime
2929
import java.time.ZoneId
30-
import java.util.*
31-
import javax.swing.*
30+
import java.util.Date
31+
import javax.swing.Box
32+
import javax.swing.Icon
33+
import javax.swing.JButton
34+
import javax.swing.JComponent
35+
import javax.swing.JLabel
36+
import javax.swing.JPanel
37+
import javax.swing.SwingConstants
3238
import kotlin.math.max
3339

3440
private const val RECALCULATE = "Recalculate"
3541
private const val REFRESH = "Refresh"
3642

3743
fun insightTitlePanel(panel: JPanel): JPanel {
3844
panel.isOpaque = false
39-
panel.border = empty( 0, 5)
45+
panel.border = empty(0, 5)
4046
return panel
4147
}
4248

@@ -141,22 +147,22 @@ private fun rebuildPanel(
141147
insightPanel as DigmaResettablePanel
142148
), BorderLayout.EAST)
143149

144-
if(bodyPanel != null || buttons != null){
150+
if (bodyPanel != null || buttons != null) {
145151
val bodyWrapper = createDefaultBoxLayoutYAxisPanel()
146152
bodyWrapper.isOpaque = false
147153

148-
if(insight.customStartTime != null || isRecalculateButtonPressed)
154+
if (insight.customStartTime != null || isRecalculateButtonPressed)
149155
bodyWrapper.add(getTimeInfoMessagePanel(
150156
customStartTime = insight.customStartTime,
151157
actualStartTime = insight.actualStartTime,
152158
isRecalculateButtonPressed = isRecalculateButtonPressed,
153159
project = project
154160
))
155161

156-
if(bodyPanel != null)
162+
if (bodyPanel != null)
157163
bodyWrapper.add(bodyPanel)
158164

159-
if(buttons != null){
165+
if (buttons != null) {
160166
val buttonsListPanel = getBasicEmptyListPanel()
161167
buttonsListPanel.border = JBUI.Borders.emptyTop(5)
162168
buttons.filterNotNull().forEach {
@@ -166,11 +172,11 @@ private fun rebuildPanel(
166172
bodyWrapper.add(buttonsListPanel)
167173
}
168174

169-
if(paginationComponent != null){
175+
if (paginationComponent != null) {
170176
bodyWrapper.add(getPaginationPanel(paginationComponent))
171177
}
172178

173-
insightPanel.add(bodyWrapper,BorderLayout.SOUTH)
179+
insightPanel.add(bodyWrapper, BorderLayout.SOUTH)
174180
}
175181
return insightPanel
176182
}
@@ -224,15 +230,16 @@ private fun getFormattedTimeDifference(diff: Duration): String {
224230
}
225231
return builder.toString()
226232
}
233+
227234
private fun getBasicEmptyListPanel(): JPanel {
228-
val listPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 0 ,0))
235+
val listPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 0, 0))
229236
listPanel.isOpaque = false
230237
listPanel.border = empty()
231238
return listPanel
232239
}
233240

234241
private fun getPaginationPanel(paginationComponent: JComponent?): JPanel {
235-
val paginationPanel = JPanel(FlowLayout(FlowLayout.LEFT, 0 ,0))
242+
val paginationPanel = JPanel(FlowLayout(FlowLayout.LEFT, 0, 0))
236243
paginationPanel.isOpaque = false
237244
paginationPanel.border = empty()
238245

@@ -242,7 +249,7 @@ private fun getPaginationPanel(paginationComponent: JComponent?): JPanel {
242249
}
243250

244251
private fun getMessageLabel(title: String, description: String): JLabel {
245-
val messageLabel = JLabel(buildBoldTitleGrayedComment(title,description), SwingConstants.LEFT)
252+
val messageLabel = JLabel(buildBoldTitleGrayedComment(title, description), SwingConstants.LEFT)
246253
messageLabel.isOpaque = false
247254
messageLabel.verticalAlignment = SwingConstants.TOP
248255
return messageLabel
@@ -258,7 +265,7 @@ private fun getIconsListPanel(
258265
if (iconsList != null) {
259266
icons.addAll(iconsList)
260267
}
261-
if(insight.prefixedCodeObjectId != null) {
268+
if (insight.prefixedCodeObjectId != null) {
262269
icons.add(Laf.Icons.Insight.THREE_DOTS)
263270
}
264271

@@ -269,9 +276,9 @@ private fun getIconsListPanel(
269276
iconLabel.horizontalAlignment = SwingConstants.RIGHT
270277
iconLabel.verticalAlignment = SwingConstants.TOP
271278
iconLabel.isOpaque = false
272-
iconLabel.border = empty(2,2,2, 4)
279+
iconLabel.border = empty(2, 2, 2, 4)
273280

274-
if(it.instanceOf(ThreeDotsIcon::class)) {
281+
if (it.instanceOf(ThreeDotsIcon::class)) {
275282
iconLabel.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
276283
iconLabel.addMouseListener(object : MouseAdapter() {
277284
override fun mouseClicked(e: MouseEvent?) {
@@ -283,6 +290,7 @@ private fun getIconsListPanel(
283290
project = project
284291
)
285292
}
293+
286294
override fun mouseEntered(e: MouseEvent?) {
287295
showHintMessage(
288296
threeDotsIcon = iconLabel,
@@ -292,6 +300,7 @@ private fun getIconsListPanel(
292300
project = project
293301
)
294302
}
303+
295304
override fun mouseExited(e: MouseEvent?) {}
296305
override fun mousePressed(e: MouseEvent?) {}
297306
})
@@ -352,38 +361,54 @@ fun genericPanelForSingleInsight(project: Project, modelObject: Any?): JPanel {
352361
}
353362

354363

355-
internal fun getInsightIconPanelRightBorderSize():Int{
364+
internal fun getInsightIconPanelRightBorderSize(): Int {
356365
return 5
357366
}
358-
internal fun getCurrentLargestWidthIconPanel(layoutHelper: PanelsLayoutHelper, width: Int):Int{
367+
368+
internal fun getCurrentLargestWidthIconPanel(layoutHelper: PanelsLayoutHelper, width: Int): Int {
359369
//this method should never return null and never throw NPE
360370
val currentLargest: Int =
361-
(layoutHelper.getObjectAttribute("insightsIconPanelBorder","largestWidth")?: 0) as Int
362-
return max(width,currentLargest)
371+
(layoutHelper.getObjectAttribute("insightsIconPanelBorder", "largestWidth") ?: 0) as Int
372+
return max(width, currentLargest)
363373
}
364-
internal fun addCurrentLargestWidthIconPanel(layoutHelper: PanelsLayoutHelper,width: Int){
374+
375+
internal fun addCurrentLargestWidthIconPanel(layoutHelper: PanelsLayoutHelper, width: Int) {
365376
//this method should never throw NPE
366377
val currentLargest: Int =
367-
(layoutHelper.getObjectAttribute("insightsIconPanelBorder","largestWidth")?: 0) as Int
368-
layoutHelper.addObjectAttribute("insightsIconPanelBorder","largestWidth",
369-
max(currentLargest,width))
378+
(layoutHelper.getObjectAttribute("insightsIconPanelBorder", "largestWidth") ?: 0) as Int
379+
layoutHelper.addObjectAttribute("insightsIconPanelBorder", "largestWidth",
380+
max(currentLargest, width))
370381
}
371382

383+
const val NoDataYetDescription = "No data received yet for this span, please trigger some actions using this code to see more insights."
384+
385+
fun noDataYetInsightPanel(): JPanel {
372386

387+
val thePanel = object : DigmaResettablePanel() {
388+
override fun reset() {
389+
}
390+
}
391+
thePanel.layout = BorderLayout()
392+
thePanel.add(getMessageLabel("No Data Yet", ""), BorderLayout.WEST)
393+
thePanel.add(JLabel(asHtml(NoDataYetDescription)), BorderLayout.SOUTH)
373394

374-
class InsightAlignedPanel(private val layoutHelper: PanelsLayoutHelper): JPanel(){
395+
return insightItemPanel(thePanel as DigmaResettablePanel)
396+
}
397+
398+
class InsightAlignedPanel(private val layoutHelper: PanelsLayoutHelper) : JPanel() {
375399

376400
init {
377401
border = JBUI.Borders.emptyRight(getInsightIconPanelRightBorderSize())
378402
}
403+
379404
override fun getPreferredSize(): Dimension {
380405
val ps = super.getPreferredSize()
381-
if (ps == null){
406+
if (ps == null) {
382407
return ps
383408
}
384409
val h = ps.height
385410
val w = ps.width
386-
addCurrentLargestWidthIconPanel(layoutHelper,w)
387-
return Dimension(getCurrentLargestWidthIconPanel(layoutHelper,w), h)
411+
addCurrentLargestWidthIconPanel(layoutHelper, w)
412+
return Dimension(getCurrentLargestWidthIconPanel(layoutHelper, w), h)
388413
}
389414
}

src/main/kotlin/org/digma/intellij/plugin/ui/list/insights/InsightsListCellRenderer.kt

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,38 @@ import com.intellij.openapi.project.Project
44
import com.intellij.ui.dsl.builder.RightGap
55
import com.intellij.ui.dsl.builder.panel
66
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
7-
import org.digma.intellij.plugin.model.rest.insights.*
7+
import org.digma.intellij.plugin.model.rest.insights.EPNPlusSpansInsight
8+
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema
89
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema.Companion.CONSUMER_SCHEMA
910
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema.Companion.HTTP_SCHEMA
1011
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema.Companion.RPC_SCHEMA
1112
import org.digma.intellij.plugin.model.rest.insights.EndpointSchema.Companion.SPAN_SCHEMA
12-
13-
import org.digma.intellij.plugin.ui.common.*
13+
import org.digma.intellij.plugin.model.rest.insights.ErrorInsight
14+
import org.digma.intellij.plugin.model.rest.insights.GroupViewModel
15+
import org.digma.intellij.plugin.model.rest.insights.HighUsageInsight
16+
import org.digma.intellij.plugin.model.rest.insights.HotspotInsight
17+
import org.digma.intellij.plugin.model.rest.insights.LowUsageInsight
18+
import org.digma.intellij.plugin.model.rest.insights.NormalUsageInsight
19+
import org.digma.intellij.plugin.model.rest.insights.SlowEndpointInsight
20+
import org.digma.intellij.plugin.model.rest.insights.SlowestSpansInsight
21+
import org.digma.intellij.plugin.model.rest.insights.SpanDurationBreakdownInsight
22+
import org.digma.intellij.plugin.model.rest.insights.SpanDurationsInsight
23+
import org.digma.intellij.plugin.model.rest.insights.SpanNPlusOneInsight
24+
import org.digma.intellij.plugin.model.rest.insights.SpanScalingInsight
25+
import org.digma.intellij.plugin.model.rest.insights.SpanScalingRootCauseInsight
26+
import org.digma.intellij.plugin.model.rest.insights.SpanSlowEndpointsInsight
27+
import org.digma.intellij.plugin.model.rest.insights.SpanUsagesInsight
28+
import org.digma.intellij.plugin.model.rest.insights.UnmappedInsight
29+
import org.digma.intellij.plugin.ui.common.CopyableLabelHtml
30+
import org.digma.intellij.plugin.ui.common.Laf
31+
import org.digma.intellij.plugin.ui.common.asHtml
32+
import org.digma.intellij.plugin.ui.common.span
33+
import org.digma.intellij.plugin.ui.common.spanBold
1434
import org.digma.intellij.plugin.ui.list.AbstractPanelListCellRenderer
1535
import org.digma.intellij.plugin.ui.list.PanelsLayoutHelper
1636
import org.digma.intellij.plugin.ui.model.insights.InsightGroupType.HttpEndpoint
1737
import org.digma.intellij.plugin.ui.model.insights.InsightGroupType.Span
38+
import org.digma.intellij.plugin.ui.model.insights.NoDataYet
1839
import org.digma.intellij.plugin.ui.model.listview.ListViewItem
1940
import javax.swing.Icon
2041
import javax.swing.JPanel
@@ -44,16 +65,15 @@ class InsightsListCellRenderer : AbstractPanelListCellRenderer() {
4465
is EPNPlusSpansInsight -> ePNPlusSpansPanel(project, value.modelObject as EPNPlusSpansInsight, value.moreData)
4566
is SpanNPlusOneInsight -> spanNPlusOneInsightPanel(project, value.modelObject as SpanNPlusOneInsight)
4667
is SlowEndpointInsight -> slowEndpointPanel(project, value.modelObject as SlowEndpointInsight)
47-
is SlowestSpansInsight -> slowestSpansPanel(project,
48-
value.modelObject as SlowestSpansInsight, value.moreData)
68+
is SlowestSpansInsight -> slowestSpansPanel(project, value.modelObject as SlowestSpansInsight, value.moreData)
4969
is SpanUsagesInsight -> spanUsagesPanel(project, value.modelObject as SpanUsagesInsight, value.moreData)
5070
is SpanDurationsInsight -> spanDurationPanel(project, value.modelObject as SpanDurationsInsight, panelsLayoutHelper)
51-
is SpanDurationBreakdownInsight -> spanDurationBreakdownPanel(project,
52-
value.modelObject as SpanDurationBreakdownInsight, value.moreData)
71+
is SpanDurationBreakdownInsight -> spanDurationBreakdownPanel(project, value.modelObject as SpanDurationBreakdownInsight, value.moreData)
5372
is SpanSlowEndpointsInsight -> spanSlowEndpointsPanel(project, value.modelObject as SpanSlowEndpointsInsight, value.moreData)
5473
is SpanScalingInsight -> spanScalingListViewItemsPanel(project, value.modelObject as SpanScalingInsight, value.moreData)
5574
is SpanScalingRootCauseInsight -> spanScalingRootCauseItemsPanel(project, value.modelObject as SpanScalingRootCauseInsight, value.moreData)
5675
is UnmappedInsight -> unmappedInsightPanel(project, value.modelObject as UnmappedInsight)
76+
is NoDataYet -> noDataYetInsightPanel()
5777
else -> genericPanelForSingleInsight(project, value.modelObject)
5878
}
5979

@@ -102,25 +122,29 @@ class InsightsListCellRenderer : AbstractPanelListCellRenderer() {
102122
}
103123
}
104124

105-
private fun createEndpointGroupViewModel(fullRouteName: String): GroupViewModel{
125+
private fun createEndpointGroupViewModel(fullRouteName: String): GroupViewModel {
106126
val routeInfo = EndpointSchema.getRouteInfo(fullRouteName)
107-
val endpoint = routeInfo.shortName
108-
if(routeInfo.schema == HTTP_SCHEMA){
109-
val split =endpoint.split(' ')
127+
val endpoint = routeInfo.shortName
128+
if (routeInfo.schema == HTTP_SCHEMA) {
129+
val split = endpoint.split(' ')
110130
val lastElementIndex = split.size - 1
111-
val schemaName = if (split.size < 3) { "HTTP" } else { split[lastElementIndex - 2].uppercase()}
112-
return GroupViewModel(asHtml("${spanBold(schemaName)} ${span("${split[lastElementIndex - 1].uppercase()} ${split[lastElementIndex]}")}"), Laf.Icons.Insight.INTERFACE)
131+
val schemaName = if (split.size < 3) {
132+
"HTTP"
133+
} else {
134+
split[lastElementIndex - 2].uppercase()
135+
}
136+
return GroupViewModel(asHtml("${spanBold(schemaName)} ${span("${split[lastElementIndex - 1].uppercase()} ${split[lastElementIndex]}")}"), Laf.Icons.Insight.INTERFACE)
113137
}
114-
if(routeInfo.schema == RPC_SCHEMA){
115-
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.INTERFACE)
138+
if (routeInfo.schema == RPC_SCHEMA) {
139+
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.INTERFACE)
116140
}
117-
if(routeInfo.schema == CONSUMER_SCHEMA){
118-
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.MESSAGE)
141+
if (routeInfo.schema == CONSUMER_SCHEMA) {
142+
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.MESSAGE)
119143
}
120-
if(routeInfo.schema == SPAN_SCHEMA){
121-
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.TELESCOPE)
144+
if (routeInfo.schema == SPAN_SCHEMA) {
145+
return GroupViewModel(asHtml(span(endpoint)), Laf.Icons.Insight.TELESCOPE)
122146
}
123-
return GroupViewModel(asHtml(""), Laf.Icons.Insight.INTERFACE)
147+
return GroupViewModel(asHtml(""), Laf.Icons.Insight.INTERFACE)
124148
}
125149

126150
private fun unmappedInsightPanel(project: Project, modelObject: UnmappedInsight): JPanel {

0 commit comments

Comments
 (0)