-
Notifications
You must be signed in to change notification settings - Fork 11
feat: show exit calls break up on hover on exit calls cell in trace list #756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c13757a
040f804
b92bbea
d56cb57
1f2f9d1
5d5126d
1c394d6
0584eb7
541751a
b0c8c46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
@import 'color-palette'; | ||
@import 'font'; | ||
|
||
.exit-calls-count { | ||
@include body-1-regular($gray-7); | ||
} | ||
|
||
.api-callee-name-count { | ||
@include body-small($gray-3); | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
padding: 2px; | ||
|
||
.api-callee-name { | ||
@include ellipsis-overflow(); | ||
max-width: 200px; | ||
} | ||
|
||
.api-callee-count { | ||
color: white; | ||
margin-left: 50px; | ||
} | ||
} | ||
|
||
.remaining-api-callee { | ||
@include body-small($gray-3); | ||
padding: 2px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { | ||
tableCellDataProvider, | ||
TableCellNoOpParser, | ||
tableCellProviders, | ||
TooltipDirective | ||
} 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('testing component properties', () => { | ||
const value = { | ||
key1: '1', | ||
key2: '2' | ||
}; | ||
const spectator = buildComponent({ | ||
providers: [tableCellDataProvider({ value: [3, value] })] | ||
}); | ||
|
||
expect(spectator.queryAll('.exit-calls-count')[0]).toContainText('3'); | ||
expect(spectator.component.apiCalleeNameCount).toMatchObject([ | ||
['key1', '1'], | ||
['key2', '2'] | ||
]); | ||
expect(spectator.component.totalCountOfDifferentApiCallee).toBe(2); | ||
expect(spectator.component.apiExitCalls).toBe(3); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core'; | ||
import { Dictionary } from '@hypertrace/common'; | ||
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 { ObservabilityTableCellType } from '../../observability-table-cell-type'; | ||
|
||
interface CellData { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Wouldn't the cell data be an array of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the query handlers append units on to everything so instead of that array, it's wrapped in an object with units like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did this change recently? I remember using composite spec where I have used value as array directly(let me find it). And regardless, imo the specification should reflect this object structure.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Possibly, table is calling parser's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does seem a bit suspicious - the wrapping object should only be there if units are defined, which they shouldn't be for a composite spec. |
||
units: number; | ||
value: [number, Dictionary<string>]; | ||
} | ||
@Component({ | ||
selector: 'ht-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"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
|
||
<div *ngFor="let item of this.apiCalleeNameCount" class="api-callee-name-count"> | ||
<span class="api-callee-name">{{ item[0] }}</span> | ||
<span class="api-callee-count">{{ item[1] }}</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: ObservabilityTableCellType.ExitCalls, | ||
alignment: TableCellAlignmentType.Left, | ||
parser: CoreTableCellParserType.NoOp | ||
}) | ||
export class ExitCallsTableCellRendererComponent extends TableCellRendererBase<CellData, Trace> implements OnInit { | ||
public readonly apiCalleeNameCount: string[][]; | ||
public readonly apiExitCalls: number; | ||
public readonly maxShowApiCalleeNameCount: number = 10; | ||
public readonly totalCountOfDifferentApiCallee!: number; | ||
|
||
public constructor( | ||
@Inject(TABLE_COLUMN_CONFIG) columnConfig: TableColumnConfig, | ||
@Inject(TABLE_COLUMN_INDEX) index: number, | ||
@Inject(TABLE_DATA_PARSER) | ||
parser: TableCellParserBase<CellData, Trace, unknown>, | ||
@Inject(TABLE_CELL_DATA) cellData: CellData, | ||
@Inject(TABLE_ROW_DATA) rowData: Trace | ||
) { | ||
super(columnConfig, index, parser, cellData, rowData); | ||
const apiCalleeNameCount: string[][] = Object.entries(cellData.value[1]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
can we call it
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree naming is confusing/type suggestions. Line 71 is meant to limit the amount of pairs to show in the tooltip, but again naming would help clarify ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's also rename |
||
this.totalCountOfDifferentApiCallee = apiCalleeNameCount.length; | ||
this.apiCalleeNameCount = apiCalleeNameCount.slice(0, this.maxShowApiCalleeNameCount); | ||
this.apiExitCalls = cellData.value[0]; | ||
} | ||
} |
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 {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export const enum ObservabilityTableCellType { | ||
Entity = 'entity', | ||
BackendIcon = 'backend-icon' | ||
BackendIcon = 'backend-icon', | ||
ExitCalls = 'exit-calls' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test has value, but what would be even better would be to verify that this data renders - for example by querying for the rendered spans and checking their content (e.g.
expect(spectator.queryAll('.api-callee-name')[0]).toContainText('key1');
)That checks both how the data is processed but also that the template is correctly binding what we expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this change I can make.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, discussed offline - because this is a template that's not rendered in the scope of this component, it's ugly to test and not worth it.