Skip to content

Commit c603e58

Browse files
authored
Feature/support insight of ChildrenSpanDurations (#192)
1 parent fd6e0b9 commit c603e58

File tree

4 files changed

+123
-6
lines changed

4 files changed

+123
-6
lines changed

src/services/codeObject.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export enum CodeObjectType
44
span = "span",
55
}
66

7-
export class CodeObjectId{
7+
export class CodeObjectId {
88

99
static readonly codeObjectSeparator: string = "$_$";
1010

@@ -24,5 +24,14 @@ export class CodeObjectId{
2424
var codeObjectType: string = parts[0];
2525
return (<any>CodeObjectType)[codeObjectType];
2626
}
27-
27+
28+
public static getSpanName(spanCodeObjectId: string): string {
29+
30+
const ix = spanCodeObjectId.lastIndexOf(this.codeObjectSeparator);
31+
if (ix < 0) {
32+
return spanCodeObjectId;
33+
}
34+
return spanCodeObjectId.substring(ix + this.codeObjectSeparator.length);
35+
}
36+
2837
}

src/views/codeAnalytics/InsightListView/ItemRender/SpanItemRendering.ts

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { decimal } from "vscode-languageclient";
44
import { Settings } from "../../../../settings";
55
import { WebViewUris } from "../../../webViewUtils";
66
import { Duration } from "../CommonInsightObjects";
7-
import { SpanDurationsInsight } from "../SpanInsight";
7+
import { CodeObjectId } from "../../../../services/codeObject";
8+
import { SpanDurationsInsight, ChildSpanDurationsInsight, ChildrenSpanDurationsInsight } from "../SpanInsight";
89
import { InsightTemplateHtml } from "./insightTemplateHtml";
910

1011
export class SpanItemHtmlRendering{
@@ -42,8 +43,9 @@ export class SpanItemHtmlRendering{
4243

4344
private findByPercentileAndPeriod(insight: SpanDurationsInsight, percentile: number, period:string){
4445

45-
return insight.periodicPercentiles.filter(x=>x.percentile===percentile && period===period).firstOrDefault()?.currentDuration.value;
46+
return insight.periodicPercentiles?.filter(x=>x.percentile===percentile && period===period).firstOrDefault()?.currentDuration.value;
4647
}
48+
4749
public spanDurationItemHtml(insight: SpanDurationsInsight): InsightTemplateHtml{
4850

4951
const percentileHtmls = [];
@@ -159,4 +161,74 @@ export class SpanItemHtmlRendering{
159161
});
160162
}
161163

162-
}
164+
private getUniquePercentiles(insight: ChildrenSpanDurationsInsight): Set<number> {
165+
const setOfNumbers: Set<number> = new Set();
166+
setOfNumbers.add(0.50); // make sure at least one entry is there - P50
167+
168+
for (const childInsight of insight.childInsights) {
169+
for (const pctl of childInsight.percentiles) {
170+
setOfNumbers.add(pctl.percentile);
171+
}
172+
}
173+
const sortedArray = [...setOfNumbers].sort((a, b) => a - b);
174+
const sortedSet = new Set(sortedArray);
175+
176+
return sortedSet;
177+
}
178+
179+
private getValueOfPercentile(insight: ChildSpanDurationsInsight, requestedPercentile: number): string {
180+
for (const pctl of insight.percentiles) {
181+
if (pctl.percentile === requestedPercentile) {
182+
return `${pctl.currentDuration.value} ${pctl.currentDuration.unit}`;
183+
}
184+
}
185+
return "";
186+
}
187+
188+
public childrenSpanDurationItemHtml(insight: ChildrenSpanDurationsInsight): InsightTemplateHtml {
189+
190+
const htmlRecords: string[] = [];
191+
192+
const percentilesSet = this.getUniquePercentiles(insight);
193+
194+
for (const childInsight of insight.childInsights) {
195+
const spanName = CodeObjectId.getSpanName(childInsight.codeObjectId);
196+
const pctlHtmlColumns: string[] = [];
197+
for (const pctl of percentilesSet) {
198+
const pctlValue = this.getValueOfPercentile(childInsight, pctl);
199+
pctlHtmlColumns.push(/*html*/ `<td>${pctlValue}</td>`);
200+
}
201+
const htmlRecord: string = /*html*/ `
202+
<tr>
203+
<td>${spanName}</td>
204+
${pctlHtmlColumns.join('')}
205+
</tr>`;
206+
207+
htmlRecords.push(htmlRecord);
208+
}
209+
210+
const tableHeaders: string[] = [];
211+
for (const percentile of percentilesSet) {
212+
tableHeaders.push(/*html*/ `<th>P${percentile*100}</th>`);
213+
}
214+
215+
const body = /*html*/ `
216+
<div class="span-durations-insight-body">
217+
<table>
218+
<tr>
219+
<th>Child Span</th>
220+
${tableHeaders.join('')}
221+
</tr>
222+
${htmlRecords.join('')}
223+
</table>
224+
</div>`;
225+
226+
return new InsightTemplateHtml({
227+
title: "Durations of children",
228+
body: body,
229+
icon: this._viewUris.image("duration.svg"),
230+
buttons: []
231+
});
232+
}
233+
234+
}

src/views/codeAnalytics/InsightListView/SpanInsight.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import moment = require("moment");
22
import { Uri } from "vscode";
33
import { decimal } from "vscode-languageclient";
44
import { EndpointSchema, UsageStatusResults } from "../../../services/analyticsProvider";
5+
import { CodeObjectId } from "../../../services/codeObject";
56
import { DocumentInfoProvider } from "../../../services/documentInfoProvider";
67
import { EditorHelper } from "../../../services/EditorHelper";
78
import { Settings } from "../../../settings";
@@ -120,6 +121,14 @@ export interface SpanDurationsInsight extends CodeObjectInsight{
120121
}[]
121122
}
122123

124+
export interface ChildSpanDurationsInsight extends SpanDurationsInsight {
125+
parentCodeObjectId: string
126+
}
127+
128+
export interface ChildrenSpanDurationsInsight extends CodeObjectInsight {
129+
childInsights: ChildSpanDurationsInsight[]
130+
}
131+
123132
export interface EndpointInfo {
124133
route: string,
125134
serviceName: string
@@ -137,11 +146,13 @@ export interface SpandSlowEndpointsInsight extends CodeObjectInsight{
137146
span: SpanInfo,
138147
slowEndpoints:SlowEndpointInfo[]
139148
}
149+
140150
export class SpanDurationsListViewItemsCreator implements IInsightListViewItemsCreator{
141151

142152
public constructor(private _viewUris:WebViewUris ){
143153

144154
}
155+
145156
public async create( codeObjectsInsight: SpanDurationsInsight[]): Promise<IListViewItemBase []>
146157
{
147158
return codeObjectsInsight.map(x=>this.createListViewItem(x));
@@ -161,6 +172,30 @@ export class SpanDurationsListViewItemsCreator implements IInsightListViewItemsC
161172
}
162173
}
163174

175+
export class ChildrenSpanDurationsListViewItemsCreator implements IInsightListViewItemsCreator {
176+
177+
public constructor(private _viewUris:WebViewUris) {
178+
179+
}
180+
181+
public async create( codeObjectsInsight: ChildrenSpanDurationsInsight[]): Promise<IListViewItemBase []> {
182+
return codeObjectsInsight.map(x=>this.createListViewItem(x));
183+
}
184+
185+
186+
public createListViewItem(insight: ChildrenSpanDurationsInsight) : IListViewItem {
187+
188+
let renderer = new SpanItemHtmlRendering(this._viewUris);
189+
190+
return {
191+
getHtml: ()=> renderer.childrenSpanDurationItemHtml(insight).renderHtml(),
192+
sortIndex: 55,
193+
// grouping by the parent span
194+
groupId: CodeObjectId.getSpanName(insight.codeObjectId)
195+
};
196+
}
197+
198+
}
164199

165200
export class SpanEndpointBottlenecksListViewItemsCreator implements IInsightListViewItemsCreator {
166201
constructor(

src/views/codeAnalytics/codeAnalyticsView.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { AnalyticsProvider } from "../../services/analyticsProvider";
1212
import { HotspotListViewItemsCreator } from "./InsightListView/HotspotInsight";
1313
import { ErrorsListViewItemsCreator } from "./InsightListView/ErrorsInsight";
1414
import { InsightListViewItemsCreator } from "./InsightListView/IInsightListViewItemsCreator";
15-
import { NPlusSpansListViewItemsCreator, SpanDurationsListViewItemsCreator, SpanEndpointBottlenecksListViewItemsCreator, SpanUsagesListViewItemsCreator } from "./InsightListView/SpanInsight";
15+
import { NPlusSpansListViewItemsCreator, SpanDurationsListViewItemsCreator, SpanEndpointBottlenecksListViewItemsCreator, SpanUsagesListViewItemsCreator, ChildrenSpanDurationsListViewItemsCreator } from "./InsightListView/SpanInsight";
1616
import { HighUsageListViewItemsCreator, LowUsageListViewItemsCreator, NormalUsageListViewItemsCreator, EPNPlusSpansListViewItemsCreator, SlowEndpointListViewItemsCreator, SlowestSpansListViewItemsCreator, UsageViewItemsTemplate } from "./InsightListView/EndpointInsight";
1717
import { Logger } from "../../services/logger";
1818
import { Settings } from "../../settings";
@@ -194,6 +194,7 @@ class CodeAnalyticsViewProvider implements vscode.WebviewViewProvider,vscode.Dis
194194
listViewItemsCreator.add("Errors", new ErrorsListViewItemsCreator(this._webViewUris));
195195
listViewItemsCreator.add("SpanUsages", new SpanUsagesListViewItemsCreator(this._webViewUris));
196196
listViewItemsCreator.add("SpanDurations", new SpanDurationsListViewItemsCreator(this._webViewUris));
197+
listViewItemsCreator.add("ChildrenSpanDurations", new ChildrenSpanDurationsListViewItemsCreator(this._webViewUris));
197198
listViewItemsCreator.add("SlowestSpans", new SlowestSpansListViewItemsCreator(this._webViewUris, editorHelper,_documentInfoProvider,this._channel));
198199
const usageTemplate = new UsageViewItemsTemplate(this._webViewUris);
199200
listViewItemsCreator.add("LowUsage", new LowUsageListViewItemsCreator(usageTemplate));

0 commit comments

Comments
 (0)