Skip to content

Commit e6b0b69

Browse files
Merge branch 'main' into to-jfrog
2 parents f3951d0 + 4325a3c commit e6b0b69

File tree

8 files changed

+193
-13
lines changed

8 files changed

+193
-13
lines changed

projects/distributed-tracing/src/shared/graphql/request/handlers/traces/traces-graphql-query-handler.service.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
22
import { Dictionary, forkJoinSafeEmpty } from '@hypertrace/common';
33
import { GraphQlHandlerType, GraphQlQueryHandler, GraphQlSelection } from '@hypertrace/graphql-client';
44
import { Observable } from 'rxjs';
5-
import { map } from 'rxjs/operators';
5+
import { defaultIfEmpty, map } from 'rxjs/operators';
66
import { MetadataService } from '../../../../services/metadata/metadata.service';
77
import { GlobalGraphQlFilterService } from '../../../model/schema/filter/global-graphql-filter.service';
88
import { GraphQlFilter } from '../../../model/schema/filter/graphql-filter';
@@ -98,9 +98,10 @@ export class TracesGraphQlQueryHandlerService implements GraphQlQueryHandler<Gra
9898
}
9999

100100
private resultUnits(specification: Specification, scope: string): Observable<string | undefined> {
101-
return this.metadataService
102-
.getAttribute(scope, specification.name)
103-
.pipe(map(attribute => (attribute.units !== '' ? attribute.units : undefined)));
101+
return this.metadataService.getAttribute(scope, specification.name).pipe(
102+
map(attribute => (attribute.units !== '' ? attribute.units : undefined)),
103+
defaultIfEmpty<string | undefined>(undefined)
104+
);
104105
}
105106
}
106107

projects/observability/src/pages/apis/api-detail/traces/api-trace-list.dashboard.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { CoreTableCellRendererType, TableMode, TableSortDirection, TableStyle } from '@hypertrace/components';
22
import { TracingTableCellType } from '@hypertrace/distributed-tracing';
3+
import { ObservabilityTableCellType } from '../../../../shared/components/table/observability-table-cell-type';
34
import { ObservabilityTraceType } from '../../../../shared/graphql/model/schema/observability-traces';
45

56
export const apiTraceListDashboard = {
@@ -25,9 +26,20 @@ export const apiTraceListDashboard = {
2526
type: 'table-widget-column',
2627
title: 'Exit Calls',
2728
filterable: true,
29+
display: ObservabilityTableCellType.ExitCalls,
2830
value: {
29-
type: 'attribute-specification',
30-
attribute: 'apiExitCalls'
31+
type: 'composite-specification',
32+
specifications: [
33+
{
34+
type: 'attribute-specification',
35+
attribute: 'apiExitCalls'
36+
},
37+
{
38+
type: 'attribute-specification',
39+
attribute: 'apiCalleeNameCount'
40+
}
41+
],
42+
'order-by': 'apiExitCalls'
3143
},
3244
'click-handler': {
3345
type: 'api-trace-navigation-handler'

projects/observability/src/pages/apis/service-detail/traces/service-trace-list.dashboard.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { CoreTableCellRendererType, TableMode, TableSortDirection, TableStyle } from '@hypertrace/components';
22
import { TracingTableCellType } from '@hypertrace/distributed-tracing';
3+
import { ObservabilityTableCellType } from '../../../../shared/components/table/observability-table-cell-type';
34
import { ObservabilityTraceType } from '../../../../shared/graphql/model/schema/observability-traces';
45

56
export const serviceTraceListDashboard = {
@@ -51,9 +52,20 @@ export const serviceTraceListDashboard = {
5152
type: 'table-widget-column',
5253
title: 'Exit Calls',
5354
filterable: true,
55+
display: ObservabilityTableCellType.ExitCalls,
5456
value: {
55-
type: 'attribute-specification',
56-
attribute: 'apiExitCalls'
57+
type: 'composite-specification',
58+
specifications: [
59+
{
60+
type: 'attribute-specification',
61+
attribute: 'apiExitCalls'
62+
},
63+
{
64+
type: 'attribute-specification',
65+
attribute: 'apiCalleeNameCount'
66+
}
67+
],
68+
'order-by': 'apiExitCalls'
5769
},
5870
'click-handler': {
5971
type: 'api-trace-navigation-handler'
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@import 'color-palette';
2+
@import 'font';
3+
4+
.exit-calls-count {
5+
@include body-1-regular($gray-7);
6+
}
7+
8+
.api-callee-name-count {
9+
@include body-small($gray-3);
10+
display: flex;
11+
align-items: center;
12+
justify-content: space-between;
13+
padding: 2px;
14+
15+
.api-callee-name {
16+
@include ellipsis-overflow();
17+
max-width: 200px;
18+
}
19+
20+
.api-callee-count {
21+
color: white;
22+
margin-left: 50px;
23+
}
24+
}
25+
26+
.remaining-api-callee {
27+
@include body-small($gray-3);
28+
padding: 2px;
29+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
tableCellDataProvider,
3+
TableCellNoOpParser,
4+
tableCellProviders,
5+
TooltipDirective
6+
} from '@hypertrace/components';
7+
import { createComponentFactory } from '@ngneat/spectator/jest';
8+
import { MockComponent } from 'ng-mocks';
9+
import { ExitCallsTableCellRendererComponent } from './exit-calls-table-cell-renderer.component';
10+
11+
describe('Exit Calls table cell renderer component', () => {
12+
const buildComponent = createComponentFactory({
13+
component: ExitCallsTableCellRendererComponent,
14+
providers: [
15+
tableCellProviders(
16+
{
17+
id: 'test'
18+
},
19+
new TableCellNoOpParser(undefined!)
20+
)
21+
],
22+
declarations: [MockComponent(TooltipDirective)],
23+
shallow: true
24+
});
25+
26+
test('testing component properties', () => {
27+
const value = {
28+
key1: '1',
29+
key2: '2'
30+
};
31+
const spectator = buildComponent({
32+
providers: [tableCellDataProvider({ value: [3, value] })]
33+
});
34+
35+
expect(spectator.queryAll('.exit-calls-count')[0]).toContainText('3');
36+
expect(spectator.component.apiCalleeNameCount).toMatchObject([
37+
['key1', '1'],
38+
['key2', '2']
39+
]);
40+
expect(spectator.component.totalCountOfDifferentApiCallee).toBe(2);
41+
expect(spectator.component.apiExitCalls).toBe(3);
42+
});
43+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
2+
import { Dictionary } from '@hypertrace/common';
3+
import {
4+
CoreTableCellParserType,
5+
TableCellAlignmentType,
6+
TableCellParserBase,
7+
TableCellRenderer,
8+
TableCellRendererBase,
9+
TableColumnConfig,
10+
TABLE_CELL_DATA,
11+
TABLE_COLUMN_CONFIG,
12+
TABLE_COLUMN_INDEX,
13+
TABLE_DATA_PARSER,
14+
TABLE_ROW_DATA
15+
} from '@hypertrace/components';
16+
import { Trace } from '@hypertrace/distributed-tracing';
17+
import { ObservabilityTableCellType } from '../../observability-table-cell-type';
18+
19+
interface CellData {
20+
units: number;
21+
value: [number, Dictionary<string>];
22+
}
23+
@Component({
24+
selector: 'ht-exit-calls-table-cell-renderer',
25+
styleUrls: ['./exit-calls-table-cell-renderer.component.scss'],
26+
changeDetection: ChangeDetectionStrategy.OnPush,
27+
template: `
28+
<div class="exit-calls-cell" [htTooltip]="exitCallsTooltip">
29+
<span class="exit-calls-count">{{ this.apiExitCalls }}</span>
30+
31+
<ng-template #exitCallsTooltip>
32+
<ng-container *ngIf="this.apiExitCalls > 0">
33+
<div *ngFor="let item of this.apiCalleeNameCount" class="api-callee-name-count">
34+
<span class="api-callee-name">{{ item[0] }}</span>
35+
<span class="api-callee-count">{{ item[1] }}</span>
36+
</div>
37+
<div
38+
*ngIf="this.totalCountOfDifferentApiCallee > this.maxShowApiCalleeNameCount"
39+
class="remaining-api-callee"
40+
>
41+
and {{ this.totalCountOfDifferentApiCallee - this.maxShowApiCalleeNameCount }} more
42+
</div>
43+
</ng-container>
44+
<ng-container *ngIf="this.apiExitCalls <= 0" class="no-exit-calls">No exit calls</ng-container>
45+
</ng-template>
46+
</div>
47+
`
48+
})
49+
@TableCellRenderer({
50+
type: ObservabilityTableCellType.ExitCalls,
51+
alignment: TableCellAlignmentType.Left,
52+
parser: CoreTableCellParserType.NoOp
53+
})
54+
export class ExitCallsTableCellRendererComponent extends TableCellRendererBase<CellData, Trace> implements OnInit {
55+
public readonly apiCalleeNameCount: string[][];
56+
public readonly apiExitCalls: number;
57+
public readonly maxShowApiCalleeNameCount: number = 10;
58+
public readonly totalCountOfDifferentApiCallee!: number;
59+
60+
public constructor(
61+
@Inject(TABLE_COLUMN_CONFIG) columnConfig: TableColumnConfig,
62+
@Inject(TABLE_COLUMN_INDEX) index: number,
63+
@Inject(TABLE_DATA_PARSER)
64+
parser: TableCellParserBase<CellData, Trace, unknown>,
65+
@Inject(TABLE_CELL_DATA) cellData: CellData,
66+
@Inject(TABLE_ROW_DATA) rowData: Trace
67+
) {
68+
super(columnConfig, index, parser, cellData, rowData);
69+
const apiCalleeNameCount: string[][] = Object.entries(cellData.value[1]);
70+
this.totalCountOfDifferentApiCallee = apiCalleeNameCount.length;
71+
this.apiCalleeNameCount = apiCalleeNameCount.slice(0, this.maxShowApiCalleeNameCount);
72+
this.apiExitCalls = cellData.value[0];
73+
}
74+
}
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
import { CommonModule } from '@angular/common';
22
import { NgModule } from '@angular/core';
3-
import { TableModule } from '@hypertrace/components';
3+
import { TableModule, TooltipModule } from '@hypertrace/components';
44
import { BackendIconTableCellParser } from './data-cell/backend-icon/backend-icon-table-cell-parser';
55
import { BackendIconTableCellRendererComponent } from './data-cell/backend-icon/backend-icon-table-cell-renderer.component';
66
import { BackendIconTableCellRendererModule } from './data-cell/backend-icon/backend-icon-table-cell-renderer.module';
77
import { EntityTableCellParser } from './data-cell/entity/entity-table-cell-parser';
88
import { EntityTableCellRendererComponent } from './data-cell/entity/entity-table-cell-renderer.component';
99
import { EntityTableCellRendererModule } from './data-cell/entity/entity-table-cell-renderer.module';
10+
import { ExitCallsTableCellRendererComponent } from './data-cell/exit-calls/exit-calls-table-cell-renderer.component';
1011

1112
@NgModule({
1213
imports: [
1314
CommonModule,
1415
TableModule.withCellParsers([EntityTableCellParser, BackendIconTableCellParser]),
15-
TableModule.withCellRenderers([EntityTableCellRendererComponent, BackendIconTableCellRendererComponent]),
16+
TableModule.withCellRenderers([
17+
EntityTableCellRendererComponent,
18+
BackendIconTableCellRendererComponent,
19+
ExitCallsTableCellRendererComponent
20+
]),
1621
EntityTableCellRendererModule,
17-
BackendIconTableCellRendererModule
18-
]
22+
BackendIconTableCellRendererModule,
23+
TooltipModule
24+
],
25+
declarations: [ExitCallsTableCellRendererComponent],
26+
exports: [ExitCallsTableCellRendererComponent]
1927
})
2028
export class ObservabilityTableCellRendererModule {}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const enum ObservabilityTableCellType {
22
Entity = 'entity',
3-
BackendIcon = 'backend-icon'
3+
BackendIcon = 'backend-icon',
4+
ExitCalls = 'exit-calls'
45
}

0 commit comments

Comments
 (0)