Skip to content

feat: fetching log records and showing log icon #817

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

Merged
merged 12 commits into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions projects/distributed-tracing/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export { WaterfallData } from './shared/dashboard/widgets/waterfall/waterfall/wa
export { TraceWaterfallDataSourceModel } from './shared/dashboard/data/graphql/waterfall/trace-waterfall-data-source.model';
export { traceDetailDashboard } from './pages/trace-detail/trace-detail.dashboard';
export { TraceDetailPageComponent } from './pages/trace-detail/trace-detail.page.component';
export { LogEvent } from './shared/dashboard/widgets/waterfall/waterfall/waterfall-chart';

// Datasources
export * from './shared/dashboard/widgets/trace-detail/data/trace-detail-data-source.model';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Dictionary } from '@hypertrace/common';
import { LogEvent } from '../../dashboard/widgets/waterfall/waterfall/waterfall-chart';

export interface SpanData {
id: string;
Expand All @@ -12,4 +13,6 @@ export interface SpanData {
tags: Dictionary<unknown>;
requestUrl: string;
exitCallsBreakup?: Dictionary<string>;
startTime: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

We hold timestamps as dates generally - converting them as soon as feasible. In this PR, it looks like we're adding a few different timestamp fields - numbers in one spot, string in another. Can those be converted to dates up front?

logEvents?: LogEvent[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ describe('Span detail component', () => {
responseHeaders: { header1: 'value1', header2: 'value2' },
responseBody: '[{"data": 5000}]',
tags: { tag1: 'value1', tag2: 'value2' },
requestUrl: 'test-url'
requestUrl: 'test-url',
startTime: 1604567825671
};

spectator = createHost(`<ht-span-detail [spanData]="spanData"></ht-span-detail>`, {
Expand All @@ -52,7 +53,8 @@ describe('Span detail component', () => {
responseHeaders: { header1: 'value1', header2: 'value2' },
responseBody: '[{"data": 5000}]',
tags: { tag1: 'value1', tag2: 'value2' },
requestUrl: 'test-url'
requestUrl: 'test-url',
startTime: 1604567825671
};

spectator = createHost(`<ht-span-detail [spanData]="spanData"></ht-span-detail>`, {
Expand All @@ -77,7 +79,8 @@ describe('Span detail component', () => {
responseHeaders: { header1: 'value1', header2: 'value2' },
responseBody: '[{"data": 5000}]',
tags: { tag1: 'value1', tag2: 'value2' },
requestUrl: 'test-url'
requestUrl: 'test-url',
startTime: 1604567825671
};

spectator = createHost(`<ht-span-detail [spanData]="spanData"></ht-span-detail>`, {
Expand All @@ -101,7 +104,8 @@ describe('Span detail component', () => {
responseHeaders: {},
responseBody: '',
tags: { tag1: 'value1', tag2: 'value2' },
requestUrl: 'test-url'
requestUrl: 'test-url',
startTime: 1604567825671
};

spectator = createHost(`<ht-span-detail [spanData]="spanData"></ht-span-detail>`, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ describe('Trace Waterfall data source model', () => {
expect.objectContaining({
name: 'errorCount'
})
],
logEventProperties: [
expect.objectContaining({
name: 'attributes'
}),
expect.objectContaining({
name: 'timestamp'
}),
expect.objectContaining({
name: 'summary'
})
]
}
});
Expand Down Expand Up @@ -156,6 +167,17 @@ describe('Trace Waterfall data source model', () => {
expect.objectContaining({
name: 'errorCount'
})
],
logEventProperties: [
expect.objectContaining({
name: 'attributes'
}),
expect.objectContaining({
name: 'timestamp'
}),
expect.objectContaining({
name: 'summary'
})
]
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
TRACE_GQL_REQUEST
} from '../../../../graphql/request/handlers/traces/trace-graphql-query-handler.service';
import { MetadataService } from '../../../../services/metadata/metadata.service';
import { WaterfallData } from '../../../widgets/waterfall/waterfall/waterfall-chart';
import { LogEvent, WaterfallData } from '../../../widgets/waterfall/waterfall/waterfall-chart';
import { GraphQlDataSourceModel } from '../graphql-data-source.model';

@Model({
Expand Down Expand Up @@ -60,6 +60,12 @@ export class TraceWaterfallDataSourceModel extends GraphQlDataSourceModel<Waterf
this.specificationBuilder.attributeSpecificationForKey('errorCount')
];

protected readonly logEventSpecifications: Specification[] = [
this.specificationBuilder.attributeSpecificationForKey('attributes'),
this.specificationBuilder.attributeSpecificationForKey('timestamp'),
this.specificationBuilder.attributeSpecificationForKey('summary')
];

public getData(): Observable<WaterfallData[]> {
return combineLatest([this.getTraceData(), this.getDurationAttribute()]).pipe(
map(combinedData => this.mapResponseObject(combinedData[0], combinedData[1]))
Expand All @@ -73,7 +79,8 @@ export class TraceWaterfallDataSourceModel extends GraphQlDataSourceModel<Waterf
spanLimit: 1000,
timestamp: this.dateCoercer.coerce(this.startTime),
traceProperties: [],
spanProperties: this.spanSpecifications
spanProperties: this.spanSpecifications,
logEventProperties: this.logEventSpecifications
});
}

Expand Down Expand Up @@ -102,7 +109,8 @@ export class TraceWaterfallDataSourceModel extends GraphQlDataSourceModel<Waterf
apiName: span.displaySpanName as string,
spanType: span.type as SpanType,
tags: span.spanTags as Dictionary<unknown>,
errorCount: span.errorCount as number
errorCount: span.errorCount as number,
logEvents: ((span.logEvents as Dictionary<LogEvent[]>) ?? {}).results
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface SpanNameCellData {
apiName?: string;
color?: string;
hasError?: boolean;
hasLogs?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

.span-title {
display: grid;
grid-template-columns: 3px min-content min-content min-content auto;
grid-template-columns: 3px min-content min-content min-content min-content auto;
grid-template-rows: 1fr;
column-gap: 4px;

Expand Down Expand Up @@ -41,6 +41,10 @@
.text {
@include ellipsis-overflow();
}

.log-icon {
margin: auto 0;
}
}

.clickable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,15 @@ describe('Span name table cell renderer component', () => {
expect(spectator.query('.color-bar')).toExist();
expect(spectator.query('.error-icon')).toExist();
});

test('should render log icon ', () => {
const spanNameDataWithColor = {
...spanNameData,
hasLogs: true
};
const spectator = buildComponent({
providers: [tableCellDataProvider(spanNameDataWithColor)]
});
expect(spectator.query('.log-icon')).toExist();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ import { WaterfallTableCellType } from './span-name-cell-type';
size="${IconSize.Medium}"
color="${Color.Red5}"
></ht-icon>
<ht-icon
*ngIf="this.value.hasLogs"
class="log-icon"
icon="${IconType.Note}"
size="${IconSize.Small}"
color="${Color.Gray4}"
></ht-icon>
</div>
`
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ describe('Waterfall Chart component', () => {
responseHeaders: {},
responseBody: 'Response Body',
tags: {},
errorCount: 0
errorCount: 0,
logEvents: []
},
{
id: 'second-id',
Expand All @@ -52,7 +53,8 @@ describe('Waterfall Chart component', () => {
responseHeaders: {},
responseBody: '',
tags: {},
errorCount: 0
errorCount: 0,
logEvents: []
},
{
id: 'third-id',
Expand All @@ -73,7 +75,8 @@ describe('Waterfall Chart component', () => {
responseHeaders: {},
responseBody: '',
tags: {},
errorCount: 0
errorCount: 0,
logEvents: []
}
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export class WaterfallChartService {
apiName: datum.apiName,
serviceName: datum.serviceName,
protocolName: datum.protocolName,
hasError: datum.errorCount > 0
hasError: datum.errorCount > 0,
hasLogs: datum.logEvents.length > 0
},
$$iconType: this.iconLookupService.forSpanType(datum.spanType)!,
getChildren: () => of([]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface WaterfallData {
responseBody?: string;
tags: Dictionary<unknown>;
errorCount: number;
logEvents: LogEvent[];
}

export interface WaterfallDataNode extends WaterfallData, Omit<StatefulPrefetchedTreeTableRow, '$$state'> {
Expand All @@ -37,3 +38,9 @@ export interface WaterfallChartState {
children: WaterfallDataNode[];
expanded: boolean;
}

export interface LogEvent {
attributes: Dictionary<unknown>;
timestamp: string;
summary: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,23 @@ export class TraceGraphQlQueryHandlerService implements GraphQlQueryHandler<Grap
children: [
{
path: 'results',
children: [{ path: 'id' }, ...this.selectionBuilder.fromSpecifications(request.spanProperties!)]
children: [
{ path: 'id' },
...(!isEmpty(request.logEventProperties)
? [
{
path: 'logEvents',
children: [
{
path: 'results',
children: this.selectionBuilder.fromSpecifications(request.logEventProperties!)
}
]
}
]
: []),
...this.selectionBuilder.fromSpecifications(request.spanProperties!)
]
}
]
};
Expand Down Expand Up @@ -121,7 +137,8 @@ export class TraceGraphQlQueryHandlerService implements GraphQlQueryHandler<Grap

rawResult.results.forEach(spanRawResult => {
const span: Span = {
[spanIdKey]: spanRawResult.id as string
[spanIdKey]: spanRawResult.id as string,
...(!isEmpty(spanRawResult.logEvents) && { logEvents: spanRawResult.logEvents })
};

(request.spanProperties || []).forEach(property => {
Expand Down Expand Up @@ -175,6 +192,7 @@ export interface GraphQlTraceRequest {
spanLimit: number;
spanId?: string;
spanProperties?: Specification[];
logEventProperties?: Specification[];
}

interface TraceServerResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ describe('Api Trace Waterfall data source model', () => {
expect.objectContaining({
name: 'errorCount'
})
],
logEventProperties: [
expect.objectContaining({
name: 'attributes'
}),
expect.objectContaining({
name: 'timestamp'
}),
expect.objectContaining({
name: 'summary'
})
]
}
});
Expand Down Expand Up @@ -163,6 +174,17 @@ describe('Api Trace Waterfall data source model', () => {
expect.objectContaining({
name: 'errorCount'
})
],
logEventProperties: [
expect.objectContaining({
name: 'attributes'
}),
expect.objectContaining({
name: 'timestamp'
}),
expect.objectContaining({
name: 'summary'
})
]
}
});
Expand Down Expand Up @@ -195,7 +217,8 @@ describe('Api Trace Waterfall data source model', () => {
displaySpanName: 'Span Name 1',
protocolName: 'Protocol Name 1',
type: SpanType.Entry,
spanTags: {}
spanTags: {},
logEvents: []
},
{
[spanIdKey]: 'second-id',
Expand All @@ -207,7 +230,8 @@ describe('Api Trace Waterfall data source model', () => {
displaySpanName: 'Span Name 2',
protocolName: 'Protocol Name 2',
type: SpanType.Exit,
spanTags: {}
spanTags: {},
logEvents: []
}
]
})
Expand All @@ -227,7 +251,8 @@ describe('Api Trace Waterfall data source model', () => {
apiName: 'Span Name 1',
protocolName: 'Protocol Name 1',
spanType: SpanType.Entry,
tags: {}
tags: {},
logEvents: []
},
{
id: 'second-id',
Expand All @@ -243,7 +268,8 @@ describe('Api Trace Waterfall data source model', () => {
apiName: 'Span Name 2',
protocolName: 'Protocol Name 2',
spanType: SpanType.Exit,
tags: {}
tags: {},
logEvents: []
}
]
});
Expand Down
Loading