Skip to content

Commit 92726b6

Browse files
Merge branch 'log-components' into log-records
2 parents 1255a4b + c5b8a42 commit 92726b6

13 files changed

+216
-220
lines changed

projects/components/src/table/cells/data-renderers/relative-timestamp/relative-timestamp-table-cell-renderer.component.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ describe('relative timestamp table cell renderer component', () => {
3030

3131
test('testing component properties', () => {
3232
const logEvent: RowData = {
33-
baseTimestamp: 1619785437887
33+
baseTimestamp: new Date(1619785437887)
3434
};
3535
const spectator = buildComponent({
36-
providers: [tableCellRowDataProvider(logEvent), tableCellDataProvider('2021-04-30T12:23:57.889149Z')]
36+
providers: [tableCellRowDataProvider(logEvent), tableCellDataProvider(new Date(1619785437887))]
3737
});
3838

39-
expect(spectator.queryAll('.relative-timestamp')[0]).toContainText('2 ms');
40-
expect(spectator.component.duration).toBe(2);
39+
expect(spectator.queryAll('.relative-timestamp')[0]).toContainText('0 ms');
40+
expect(spectator.component.duration).toBe(0);
4141
});
4242
});

projects/components/src/table/cells/data-renderers/relative-timestamp/relative-timestamp-table-cell-renderer.component.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
2-
import { DateCoercer, DateFormatMode, DateFormatOptions, Dictionary } from '@hypertrace/common';
2+
import { DateFormatMode, DateFormatOptions, Dictionary } from '@hypertrace/common';
33
import { TableColumnConfig } from '../../../table-api';
44
import {
55
TABLE_CELL_DATA,
@@ -16,10 +16,8 @@ import { CoreTableCellRendererType } from '../../types/core-table-cell-renderer-
1616
import { TableCellAlignmentType } from '../../types/table-cell-alignment-type';
1717

1818
export interface RowData extends Dictionary<unknown> {
19-
baseTimestamp: DateOrNumber;
19+
baseTimestamp: Date;
2020
}
21-
22-
type DateOrNumber = Date | number;
2321
@Component({
2422
selector: 'ht-relative-timestamp-table-cell-renderer',
2523
styleUrls: ['./relative-timestamp-table-cell-renderer.component.scss'],
@@ -39,24 +37,21 @@ type DateOrNumber = Date | number;
3937
alignment: TableCellAlignmentType.Left,
4038
parser: CoreTableCellParserType.NoOp
4139
})
42-
export class RelativeTimestampTableCellRendererComponent extends TableCellRendererBase<DateOrNumber> implements OnInit {
40+
export class RelativeTimestampTableCellRendererComponent extends TableCellRendererBase<Date> implements OnInit {
4341
public readonly dateFormat: DateFormatOptions = {
4442
mode: DateFormatMode.DateAndTimeWithSeconds
4543
};
4644
public readonly duration: number;
47-
private readonly dateCoercer: DateCoercer = new DateCoercer();
4845

4946
public constructor(
5047
@Inject(TABLE_COLUMN_CONFIG) columnConfig: TableColumnConfig,
5148
@Inject(TABLE_COLUMN_INDEX) index: number,
5249
@Inject(TABLE_DATA_PARSER)
53-
parser: TableCellParserBase<DateOrNumber, DateOrNumber, unknown>,
54-
@Inject(TABLE_CELL_DATA) cellData: DateOrNumber,
50+
parser: TableCellParserBase<Date, Date, unknown>,
51+
@Inject(TABLE_CELL_DATA) cellData: Date,
5552
@Inject(TABLE_ROW_DATA) rowData: RowData
5653
) {
5754
super(columnConfig, index, parser, cellData, rowData);
58-
this.duration =
59-
(this.dateCoercer.coerce(cellData)?.getTime() ?? NaN) -
60-
(this.dateCoercer.coerce(rowData.baseTimestamp)?.getTime() ?? NaN);
55+
this.duration = cellData.getTime() - rowData.baseTimestamp.getTime();
6156
}
6257
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
@import 'font';
22

3+
.log-events-table {
4+
margin-top: 25px;
5+
}
6+
37
.content {
48
@include body-2-regular();
59
margin-left: 175px;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { HttpClientTestingModule } from '@angular/common/http/testing';
2+
import { fakeAsync, flush } from '@angular/core/testing';
3+
import { ActivatedRoute } from '@angular/router';
4+
import { IconLibraryTestingModule } from '@hypertrace/assets-library';
5+
import { NavigationService } from '@hypertrace/common';
6+
import { TableComponent, TableModule } from '@hypertrace/components';
7+
import { runFakeRxjs } from '@hypertrace/test-utils';
8+
import { createHostFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
9+
import { EMPTY } from 'rxjs';
10+
import { LogEventsTableComponent, LogEventsTableViewType } from './log-events-table.component';
11+
import { LogEventsTableModule } from './log-events-table.module';
12+
13+
describe('LogEventsTableComponent', () => {
14+
let spectator: Spectator<LogEventsTableComponent>;
15+
16+
const createHost = createHostFactory({
17+
component: LogEventsTableComponent,
18+
imports: [LogEventsTableModule, TableModule, HttpClientTestingModule, IconLibraryTestingModule],
19+
declareComponent: false,
20+
providers: [
21+
mockProvider(ActivatedRoute, {
22+
queryParamMap: EMPTY
23+
}),
24+
mockProvider(NavigationService, {
25+
navigation$: EMPTY
26+
})
27+
]
28+
});
29+
30+
test('should render data correctly for sheet view', fakeAsync(() => {
31+
spectator = createHost(
32+
`<ht-log-events-table [logEvents]="logEvents" [logEventsTableViewType]="logEventsTableViewType" [spanStartTime]="spanStartTime"></ht-log-events-table>`,
33+
{
34+
hostProps: {
35+
logEvents: [
36+
{ attributes: { attr1: 1, attr2: 2 }, summary: 'test', timestamp: '2021-04-30T12:23:57.889149Z' }
37+
],
38+
logEventsTableViewType: LogEventsTableViewType.Sheet,
39+
spanStartTime: 1619785437887
40+
}
41+
}
42+
);
43+
44+
expect(spectator.query('.log-events-table')).toExist();
45+
expect(spectator.query(TableComponent)).toExist();
46+
expect(spectator.query(TableComponent)!.resizable).toBe(false);
47+
expect(spectator.query(TableComponent)!.columnConfigs).toMatchObject([
48+
expect.objectContaining({
49+
id: 'timestamp'
50+
}),
51+
expect.objectContaining({
52+
id: 'summary'
53+
})
54+
]);
55+
expect(spectator.query(TableComponent)!.pageable).toBe(false);
56+
expect(spectator.query(TableComponent)!.detailContent).not.toBeNull();
57+
58+
runFakeRxjs(({ expectObservable }) => {
59+
expect(spectator.component.dataSource).toBeDefined();
60+
expectObservable(spectator.component.dataSource!.getData(undefined!)).toBe('(x|)', {
61+
x: {
62+
data: [expect.objectContaining({ summary: 'test' })],
63+
totalCount: 1
64+
}
65+
});
66+
67+
flush();
68+
});
69+
}));
70+
});
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
2+
import { DateCoercer, Dictionary } from '@hypertrace/common';
3+
import {
4+
CoreTableCellRendererType,
5+
ListViewHeader,
6+
ListViewRecord,
7+
TableColumnConfig,
8+
TableDataResponse,
9+
TableDataSource,
10+
TableMode,
11+
TableRow
12+
} from '@hypertrace/components';
13+
import { isEmpty } from 'lodash-es';
14+
import { Observable, of } from 'rxjs';
15+
16+
export const enum LogEventsTableViewType {
17+
Sheet = 'sheet',
18+
Page = 'page'
19+
}
20+
21+
@Component({
22+
selector: 'ht-log-events-table',
23+
styleUrls: ['./log-events-table.component.scss'],
24+
changeDetection: ChangeDetectionStrategy.OnPush,
25+
template: `
26+
<div class="log-events-table">
27+
<ht-table
28+
[columnConfigs]="this.columnConfigs"
29+
[data]="this.dataSource"
30+
[pageable]="false"
31+
[resizable]="false"
32+
mode=${TableMode.Detail}
33+
[detailContent]="detailContent"
34+
></ht-table>
35+
</div>
36+
<ng-template #detailContent let-row="row">
37+
<div class="content">
38+
<ht-list-view
39+
[records]="this.getLogEventAttributeRecords(row.attributes)"
40+
[header]="this.header"
41+
data-sensitive-pii
42+
></ht-list-view>
43+
</div>
44+
</ng-template>
45+
`
46+
})
47+
export class LogEventsTableComponent implements OnInit {
48+
@Input()
49+
public logEvents: Dictionary<unknown>[] = [];
50+
51+
@Input()
52+
public logEventsTableViewType: LogEventsTableViewType = LogEventsTableViewType.Sheet;
53+
54+
@Input()
55+
public spanStartTime?: number;
56+
57+
public readonly header: ListViewHeader = { keyLabel: 'key', valueLabel: 'value' };
58+
private readonly dateCoercer: DateCoercer = new DateCoercer();
59+
60+
public dataSource?: TableDataSource<TableRow>;
61+
public columnConfigs: TableColumnConfig[] = [];
62+
63+
public ngOnInit(): void {
64+
this.buildDataSource();
65+
this.columnConfigs = this.getTableColumnConfigs();
66+
}
67+
68+
public getLogEventAttributeRecords(attributes: Dictionary<unknown>): ListViewRecord[] {
69+
if (!isEmpty(attributes)) {
70+
return Object.entries(attributes).map((attribute: [string, unknown]) => ({
71+
key: attribute[0],
72+
value: attribute[1] as string | number
73+
}));
74+
}
75+
76+
return [];
77+
}
78+
79+
private buildDataSource(): void {
80+
this.dataSource = {
81+
getData: (): Observable<TableDataResponse<TableRow>> =>
82+
of({
83+
data: this.logEvents.map((logEvent: Dictionary<unknown>) => ({
84+
...logEvent,
85+
timestamp: this.dateCoercer.coerce(logEvent.timestamp),
86+
baseTimestamp: this.dateCoercer.coerce(this.spanStartTime)
87+
})),
88+
totalCount: this.logEvents.length
89+
}),
90+
getScope: () => undefined
91+
};
92+
}
93+
94+
private getTableColumnConfigs(): TableColumnConfig[] {
95+
if (this.logEventsTableViewType === LogEventsTableViewType.Sheet) {
96+
return [
97+
{
98+
id: 'timestamp',
99+
name: 'timestamp',
100+
title: 'Timestamp',
101+
display: CoreTableCellRendererType.RelativeTimestamp,
102+
visible: true,
103+
width: '150px',
104+
sortable: false,
105+
filterable: false
106+
},
107+
{
108+
id: 'summary',
109+
name: 'summary',
110+
title: 'Summary',
111+
visible: true,
112+
sortable: false,
113+
filterable: false
114+
}
115+
];
116+
}
117+
118+
return [];
119+
}
120+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { CommonModule } from '@angular/common';
2+
import { NgModule } from '@angular/core';
3+
import { FormattingModule } from '@hypertrace/common';
4+
import { IconModule, ListViewModule, TableModule, TooltipModule } from '@hypertrace/components';
5+
import { LogEventsTableComponent } from './log-events-table.component';
6+
@NgModule({
7+
imports: [CommonModule, TableModule, IconModule, TooltipModule, FormattingModule, ListViewModule],
8+
declarations: [LogEventsTableComponent],
9+
exports: [LogEventsTableComponent]
10+
})
11+
export class LogEventsTableModule {}

projects/distributed-tracing/src/shared/dashboard/widgets/log-detail/data/log-detail-data-source.model.test.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

projects/distributed-tracing/src/shared/dashboard/widgets/log-detail/data/log-detail-data-source.model.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

projects/distributed-tracing/src/shared/dashboard/widgets/log-detail/log-detail-widget-renderer.component.test.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)