Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { fakeAsync } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { IconLibraryTestingModule } from '@hypertrace/assets-library';
import { NavigationService } from '@hypertrace/common';
import { runFakeRxjs } from '@hypertrace/test-utils';
import { createHostFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
import { EMPTY } from 'rxjs';
import { SpanExitCallsComponent } from './span-exit-calls.component';
import { SpanExitCallsModule } from './span-exit-calls.module';

describe('SpanExitCallsComponent', () => {
let spectator: Spectator<SpanExitCallsComponent>;

const createHost = createHostFactory({
component: SpanExitCallsComponent,
imports: [SpanExitCallsModule, HttpClientTestingModule, IconLibraryTestingModule],
declareComponent: false,
providers: [
mockProvider(ActivatedRoute, {
queryParamMap: EMPTY
}),
mockProvider(NavigationService, {
navigation$: EMPTY
})
]
});

it('should render data correctly', fakeAsync(() => {
spectator = createHost(`<ht-span-exit-calls [exitCalls]="exitCalls"></ht-span-exit-calls>`, {
hostProps: { exitCalls: { 'name 1': '10', 'name 2': '11' } }
});

runFakeRxjs(({ expectObservable }) => {
expect(spectator.component.dataSource).toBeDefined();
expectObservable(spectator.component.dataSource!.getData(undefined!)).toBe('(x|)', {
x: {
data: [
{ name: 'name 1', calls: '10' },
{ name: 'name 2', calls: '11' }
],
totalCount: 2
}
});
});
}));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { Dictionary } from '@hypertrace/common';
import { TableColumnConfig, TableDataResponse, TableDataSource, TableRow } from '@hypertrace/components';
import { Observable, of } from 'rxjs';

@Component({
selector: 'ht-span-exit-calls',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<div class="span-exit-calls">
<ht-table [columnConfigs]="this.columnConfigs" [data]="this.dataSource" [pageable]="false"></ht-table>
</div> `
})
export class SpanExitCallsComponent implements OnInit {
@Input()
public exitCalls?: Dictionary<string>;

public dataSource?: TableDataSource<TableRow>;
public columnConfigs: TableColumnConfig[] = [
{
id: 'name',
name: 'name',
title: 'Service',
visible: true,
width: '80%',
sortable: false,
filterable: false
},
{
id: 'calls',
name: 'calls',
title: 'Calls',
visible: true,
sortable: false,
filterable: false
}
];

public ngOnInit(): void {
this.buildDataSource();
}

private buildDataSource(): void {
this.dataSource = {
getData: (): Observable<TableDataResponse<TableRow>> =>
of({
data: Object.entries(this.exitCalls ?? {}).map(item => ({ name: item[0], calls: item[1] })),
totalCount: Object.keys(this.exitCalls ?? {}).length
}),
getScope: () => undefined
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TableModule } from '@hypertrace/components';
import { SpanExitCallsComponent } from './span-exit-calls.component';

@NgModule({
declarations: [SpanExitCallsComponent],
exports: [SpanExitCallsComponent],
imports: [CommonModule, TableModule]
})
export class SpanExitCallsModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export interface SpanData {
responseBody: string;
tags: Dictionary<unknown>;
requestUrl: string;
exitCallsBreakup?: Dictionary<string>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ import { SpanDetailLayoutStyle } from './span-detail-layout-style';
<ht-tab label="Attributes" class="attributes">
<ht-span-tags-detail [tags]="this.spanData.tags"></ht-span-tags-detail>
</ht-tab>
<ht-tab label="Exit Calls" *ngIf="this.showExitCallsTab">
<ht-span-exit-calls [exitCalls]="this.spanData.exitCallsBreakup"></ht-span-exit-calls>
</ht-tab>
</ht-tab-group>
</div>
`
Expand All @@ -62,11 +65,13 @@ export class SpanDetailComponent implements OnChanges {

public showRequestTab?: boolean;
public showResponseTab?: boolean;
public showExitCallsTab?: boolean;

public ngOnChanges(changes: TypedSimpleChanges<this>): void {
if (changes.spanData) {
this.showRequestTab = !isEmpty(this.spanData?.requestHeaders) || !isEmpty(this.spanData?.requestBody);
this.showResponseTab = !isEmpty(this.spanData?.responseHeaders) || !isEmpty(this.spanData?.responseBody);
this.showExitCallsTab = Object.keys(this.spanData?.exitCallsBreakup ?? {}).length > 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ToggleButtonModule,
TooltipModule
} from '@hypertrace/components';
import { SpanExitCallsModule } from './exit-calls/span-exit-calls.module';
import { SpanDetailTitleHeaderModule } from './headers/title/span-detail-title-header.module';
import { SpanRequestDetailModule } from './request/span-request-detail.module';
import { SpanResponseDetailModule } from './response/span-response-detail.module';
Expand All @@ -32,7 +33,8 @@ import { SpanTagsDetailModule } from './tags/span-tags-detail.module';
JsonViewerModule,
LoadAsyncModule,
ListViewModule,
SpanDetailTitleHeaderModule
SpanDetailTitleHeaderModule,
SpanExitCallsModule
],
declarations: [SpanDetailComponent],
exports: [SpanDetailComponent]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { Model } from '@hypertrace/hyperdash';
import { Trace, traceIdKey } from '../../../../graphql/model/schema/trace';

import { Dictionary } from '@hypertrace/common';
import { TraceDetailData, TraceDetailDataSourceModel } from './trace-detail-data-source.model';

@Model({
type: 'api-trace-detail-data-source'
})
export class ApiTraceDetailDataSourceModel extends TraceDetailDataSourceModel {
protected getTraceAttributes(): string[] {
// TODO : request for 'apiCalleeNameCount' here
return [...super.getTraceAttributes(), 'traceId'];
}

protected constructTraceDetailData(trace: Trace): ApiTraceDetailData {
return {
...super.constructTraceDetailData(trace),
traceId: trace.traceId as string, // For API Trace traceId is real Trace ID. NOT Symbol('traceId').
entrySpanId: trace[traceIdKey] // API Trace Symbol('traceId') same as apiTraceId which is actually Entry Span ID
entrySpanId: trace[traceIdKey], // API Trace Symbol('traceId') same as apiTraceId which is actually Entry Span ID,
exitCallsBreakup: trace.exitCallsBreakup as Dictionary<string>
};
}
}

export interface ApiTraceDetailData extends TraceDetailData {
entrySpanId: string;
exitCallsBreakup: Dictionary<string>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface WaterfallData {
responseHeaders?: Dictionary<unknown>;
responseBody?: string;
tags: Dictionary<unknown>;
exitCallsBreakup?: Dictionary<string>;
}

export interface WaterfallDataNode extends WaterfallData, Omit<StatefulPrefetchedTreeTableRow, '$$state'> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class ApiTraceWaterfallDataSourceModel extends GraphQlDataSourceModel<Wat
);
}

// TODO : request for 'apiCalleeNameCount' here
protected getSpanAttributes(): string[] {
return [
'displayEntityName',
Expand Down Expand Up @@ -106,7 +107,8 @@ export class ApiTraceWaterfallDataSourceModel extends GraphQlDataSourceModel<Wat
name: span.displaySpanName as string,
protocolName: span.protocolName as string,
spanType: span.type as SpanType,
tags: span.spanTags as Dictionary<unknown>
tags: span.spanTags as Dictionary<unknown>,
exitCallsBreakup: span.exitCallsBreakup as Dictionary<string>
};
}
}