Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@import 'color-palette';
@import 'font';

.exit-calls-count {
@include body-1-regular($gray-7);
}

.api-callee-name-count {
display: flex;
align-items: center;
justify-content: space-between;
padding: 2px;

.api-callee-name {
@include ellipsis-overflow();
max-width: 200px;
font-size: 13.5px;
color: $gray-2;
}

.api-callee-count {
color: white;
font-size: 15px;
margin-left: 50px;
}
}

.remaining-api-callee {
font-size: 13.5px;
padding: 2px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { TooltipDirective } from '@hypertrace/components';
import { TableCellNoOpParser, tableCellProviders, tableCellRowDataProvider } from '@hypertrace/components';
import { createComponentFactory } from '@ngneat/spectator/jest';
import { MockComponent } from 'ng-mocks';
import { ExitCallsTableCellRendererComponent } from './exit-calls-table-cell-renderer.component';

describe('Exit Calls table cell renderer component', () => {
const buildComponent = createComponentFactory({
component: ExitCallsTableCellRendererComponent,
providers: [
tableCellProviders(
{
id: 'test'
},
new TableCellNoOpParser(undefined!)
)
],
declarations: [MockComponent(TooltipDirective)],
shallow: true
});

test('should render a number as expected', () => {
const spectator = buildComponent({
providers: [tableCellRowDataProvider({ apiExitCalls: 1 })]
});

expect(spectator.query('.exit-calls-count')).toHaveText('1');
expect(spectator.query(TooltipDirective)).toExist();
});

test('testing getMaxShowAPICalleeNameCount function', () => {
const value = {
key1: '1',
key2: '2'
};
const spectator = buildComponent({
providers: [tableCellRowDataProvider({ apiExitCalls: 2, apiCalleeNameCount: value })]
});

expect(spectator.component.getMaxShowAPICalleeNameCount(value)).toMatchObject(value);
expect(spectator.component.totalCountOfDifferentAPICallee).toBe(2);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
import {
CoreTableCellParserType,
TableCellAlignmentType,
TableCellParserBase,
TableCellRenderer,
TableCellRendererBase,
TableColumnConfig,
TABLE_CELL_DATA,
TABLE_COLUMN_CONFIG,
TABLE_COLUMN_INDEX,
TABLE_DATA_PARSER,
TABLE_ROW_DATA
} from '@hypertrace/components';
import { Trace } from '@hypertrace/distributed-tracing';
import { ExploreValue } from '@hypertrace/observability';

export const EXIT_CALLS_CELL = 'EXIT_CALLS_CELL';

@Component({
selector: 'exit-calls-table-cell-renderer',
styleUrls: ['./exit-calls-table-cell-renderer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="exit-calls-cell" [htTooltip]="exitCallsTooltip">
<span class="exit-calls-count">{{ this.apiExitCalls }}</span>

<ng-template #exitCallsTooltip>
<ng-container *ngIf="this.apiExitCalls > 0">
Copy link
Contributor

@arjunlalb arjunlalb Apr 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This is an if-else use case. You can clean this up like below. There are many examples in the codebase.

<ng-container *ngIf="this.apiExitCalls > 0; else noExitCalls">
  Content goes here
</ng-container>
<ng-template #noExitCalls></ng-template>

<div *ngFor="let item of this.apiCalleeNameCount | keyvalue" class="api-callee-name-count">
<span class="api-callee-name">{{ item.key }}</span>
<span class="api-callee-count">{{ item.value }}</span>
</div>
<div
*ngIf="this.totalCountOfDifferentAPICallee > this.maxShowAPICalleeNameCount"
class="remaining-api-callee"
>
and {{ this.totalCountOfDifferentAPICallee - this.maxShowAPICalleeNameCount }} more
</div>
</ng-container>
<ng-container *ngIf="this.apiExitCalls <= 0" class="no-exit-calls">No exit calls</ng-container>
</ng-template>
</div>
`
})
@TableCellRenderer({
type: EXIT_CALLS_CELL,
alignment: TableCellAlignmentType.Left,
parser: CoreTableCellParserType.NoOp
})
export class ExitCallsTableCellRendererComponent extends TableCellRendererBase<ExploreValue, any> implements OnInit {
public readonly apiCalleeNameCount: any;
public readonly apiExitCalls: number;
public readonly maxShowAPICalleeNameCount: number = 10;
public totalCountOfDifferentAPICallee!: number;

public constructor(
@Inject(TABLE_COLUMN_CONFIG) columnConfig: TableColumnConfig,
@Inject(TABLE_COLUMN_INDEX) index: number,
@Inject(TABLE_DATA_PARSER) parser: TableCellParserBase<ExploreValue, Trace, unknown>,
@Inject(TABLE_CELL_DATA) cellData: ExploreValue,
@Inject(TABLE_ROW_DATA) rowData: Trace
) {
super(columnConfig, index, parser, cellData, rowData);
this.apiCalleeNameCount = this.getMaxShowAPICalleeNameCount(rowData.apiCalleeNameCount);
this.apiExitCalls = Number(rowData.apiExitCalls);
}

public getMaxShowAPICalleeNameCount(apiCalleeNameCount: any): any {
if (apiCalleeNameCount) {
const showAPICalleeNameCount: any = {};
let count = 0;
Object.keys(apiCalleeNameCount).forEach((key: string) => {
if (count < this.maxShowAPICalleeNameCount) {
showAPICalleeNameCount[key] = apiCalleeNameCount[key];
count++;
}
});
this.totalCountOfDifferentAPICallee = Object.keys(apiCalleeNameCount).length;
return showAPICalleeNameCount;
}
return {};
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TableModule } from '@hypertrace/components';
import { TableModule, TooltipModule } from '@hypertrace/components';
import { BackendIconTableCellParser } from './data-cell/backend-icon/backend-icon-table-cell-parser';
import { BackendIconTableCellRendererComponent } from './data-cell/backend-icon/backend-icon-table-cell-renderer.component';
import { BackendIconTableCellRendererModule } from './data-cell/backend-icon/backend-icon-table-cell-renderer.module';
import { EntityTableCellParser } from './data-cell/entity/entity-table-cell-parser';
import { EntityTableCellRendererComponent } from './data-cell/entity/entity-table-cell-renderer.component';
import { EntityTableCellRendererModule } from './data-cell/entity/entity-table-cell-renderer.module';
import { ExitCallsTableCellRendererComponent } from './data-cell/exit-calls/exit-calls-table-cell-renderer.component';

@NgModule({
imports: [
CommonModule,
TableModule.withCellParsers([EntityTableCellParser, BackendIconTableCellParser]),
TableModule.withCellRenderers([EntityTableCellRendererComponent, BackendIconTableCellRendererComponent]),
TableModule.withCellRenderers([
EntityTableCellRendererComponent,
BackendIconTableCellRendererComponent,
ExitCallsTableCellRendererComponent
]),
EntityTableCellRendererModule,
BackendIconTableCellRendererModule
]
BackendIconTableCellRendererModule,
TooltipModule
],
declarations: [ExitCallsTableCellRendererComponent],
exports: [ExitCallsTableCellRendererComponent]
})
export class ObservabilityTableCellRendererModule {}