Skip to content

Commit b2ca2b1

Browse files
committed
Merge branch 'main' into user-telemetry-3
2 parents 816baec + 6ed8f86 commit b2ca2b1

15 files changed

+264
-61
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"d3-shape": "^1.3.5",
5959
"d3-transition": "^1.2.0",
6060
"d3-zoom": "^1.8.3",
61-
"graphql": "^15.5.3",
61+
"graphql": "^15.6.0",
6262
"graphql-tag": "^2.12.5",
6363
"iso8601-duration": "^1.3.0",
6464
"lodash-es": "^4.17.21",

projects/common/src/telemetry/track/track.directive.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ export class TrackDirective implements OnInit, OnChanges, OnDestroy {
5858
}
5959

6060
private trackUserEvent(userEvent: string, eventObj: MouseEvent): void {
61+
const targetElement = eventObj.target as HTMLElement;
6162
this.userTelemetryImplService.trackEvent(`${userEvent}: ${this.trackedEventLabel}`, {
62-
...(eventObj.target as HTMLElement),
63+
tagName: targetElement.tagName,
64+
className: targetElement.className,
6365
type: userEvent
6466
});
6567
}

projects/observability/src/pages/api-trace-detail/api-trace-detail.page.component.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
display: flex;
3636
align-items: center;
3737

38+
.filterable-summary-value {
39+
display: flex;
40+
align-items: center;
41+
}
42+
3843
.separation {
3944
flex: 1 1 auto;
4045
}
@@ -45,7 +50,7 @@
4550
}
4651

4752
.summary-value {
48-
margin-right: 24px;
53+
margin-right: 8px;
4954
}
5055

5156
.tabs {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { fakeAsync, tick } from '@angular/core/testing';
2+
import { MemoizeModule, NavigationService } from '@hypertrace/common';
3+
import { LoadAsyncModule } from '@hypertrace/components';
4+
import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest';
5+
import { MockComponent } from 'ng-mocks';
6+
import { of } from 'rxjs';
7+
import { ExploreFilterLinkComponent } from '../../shared/components/explore-filter-link/explore-filter-link.component';
8+
import { ExplorerService } from '../explorer/explorer-service';
9+
import { ApiTraceDetailPageComponent } from './api-trace-detail.page.component';
10+
import { ApiTraceDetails, ApiTraceDetailService } from './api-trace-detail.service';
11+
describe('Api Trace Details Page Component', () => {
12+
const mockTraceDetails: ApiTraceDetails = {
13+
id: 'test-id',
14+
traceId: 'test-123',
15+
type: 'trace-type',
16+
timeString: 'test-time-string',
17+
titleString: 'test-title',
18+
startTime: 'test-start-time'
19+
};
20+
21+
const createComponent = createComponentFactory({
22+
component: ApiTraceDetailPageComponent,
23+
shallow: true,
24+
providers: [
25+
mockProvider(NavigationService),
26+
mockProvider(ExplorerService, {
27+
buildNavParamsWithFilters: jest.fn().mockReturnValue(of('traceId_eq_test-123'))
28+
})
29+
],
30+
imports: [LoadAsyncModule, MemoizeModule],
31+
componentProviders: [
32+
mockProvider(ApiTraceDetailService, {
33+
fetchTraceDetails: jest.fn().mockReturnValue(of(mockTraceDetails))
34+
})
35+
],
36+
declarations: [MockComponent(ExploreFilterLinkComponent)]
37+
});
38+
39+
test('should render content correctly', fakeAsync(() => {
40+
const spectator = createComponent();
41+
42+
spectator.click('.label');
43+
tick();
44+
expect(spectator.inject(NavigationService).navigateBack).toHaveBeenCalled();
45+
46+
spectator.click('.full-trace-button');
47+
tick();
48+
expect(spectator.inject(NavigationService).navigateWithinApp).toHaveBeenCalledWith([
49+
'/trace',
50+
mockTraceDetails.traceId,
51+
{ startTime: mockTraceDetails.startTime }
52+
]);
53+
}));
54+
55+
test('should render explorer link component', fakeAsync(() => {
56+
const spectator = createComponent();
57+
expect(spectator.query(ExploreFilterLinkComponent)?.paramsOrUrl).toBe('traceId_eq_test-123');
58+
}));
59+
});

projects/observability/src/pages/api-trace-detail/api-trace-detail.page.component.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { ChangeDetectionStrategy, Component } from '@angular/core';
22
import { IconType } from '@hypertrace/assets-library';
3-
import { NavigationService, SubscriptionLifecycle } from '@hypertrace/common';
4-
import { ButtonRole, ButtonStyle, IconSize } from '@hypertrace/components';
3+
import { NavigationParams, NavigationService, SubscriptionLifecycle } from '@hypertrace/common';
4+
import { ButtonRole, ButtonStyle, FilterOperator, IconSize } from '@hypertrace/components';
55
import { Observable } from 'rxjs';
66
import { LogEvent } from '../../shared/dashboard/widgets/waterfall/waterfall/waterfall-chart';
7+
import { ExplorerService } from '../explorer/explorer-service';
8+
import { ScopeQueryParam } from '../explorer/explorer.component';
79
import { ApiTraceDetails, ApiTraceDetailService } from './api-trace-detail.service';
810

911
@Component({
@@ -31,12 +33,21 @@ import { ApiTraceDetails, ApiTraceDetailService } from './api-trace-detail.servi
3133
icon="${IconType.Time}"
3234
[value]="traceDetails.timeString"
3335
></ht-summary-value>
34-
<ht-summary-value
35-
class="summary-value"
36-
icon="${IconType.TraceId}"
37-
label="Trace ID"
38-
[value]="traceDetails.traceId"
39-
></ht-summary-value>
36+
37+
<div class="filterable-summary-value">
38+
<ht-summary-value
39+
class="summary-value"
40+
icon="${IconType.TraceId}"
41+
label="Trace ID"
42+
[value]="traceDetails.traceId"
43+
></ht-summary-value>
44+
<ht-explore-filter-link
45+
class="filter-link"
46+
[paramsOrUrl]="getExplorerNavigationParams | htMemoize: traceDetails | async"
47+
htTooltip="See traces in Explorer"
48+
>
49+
</ht-explore-filter-link>
50+
</div>
4051
4152
<div class="separation"></div>
4253
@@ -50,17 +61,17 @@ import { ApiTraceDetails, ApiTraceDetailService } from './api-trace-detail.servi
5061
(click)="this.navigateToFullTrace(traceDetails.traceId, traceDetails.startTime)"
5162
></ht-button>
5263
</div>
53-
</div>
5464
55-
<ht-navigable-tab-group class="tabs">
56-
<ht-navigable-tab path="sequence"> Sequence </ht-navigable-tab>
57-
<ng-container *ngIf="this.logEvents$ | async as logEvents">
58-
<ht-navigable-tab path="logs" [labelTag]="logEvents.length"> Logs </ht-navigable-tab>
59-
</ng-container>
60-
</ht-navigable-tab-group>
65+
<ht-navigable-tab-group class="tabs">
66+
<ht-navigable-tab path="sequence"> Sequence </ht-navigable-tab>
67+
<ng-container *ngIf="this.logEvents$ | async as logEvents">
68+
<ht-navigable-tab path="logs" [labelTag]="logEvents.length"> Logs </ht-navigable-tab>
69+
</ng-container>
70+
</ht-navigable-tab-group>
6171
62-
<div class="scrollable-container">
63-
<router-outlet></router-outlet>
72+
<div class="scrollable-container">
73+
<router-outlet></router-outlet>
74+
</div>
6475
</div>
6576
</div>
6677
`
@@ -73,7 +84,8 @@ export class ApiTraceDetailPageComponent {
7384

7485
public constructor(
7586
protected readonly navigationService: NavigationService,
76-
private readonly apiTraceDetailService: ApiTraceDetailService
87+
private readonly apiTraceDetailService: ApiTraceDetailService,
88+
private readonly explorerService: ExplorerService
7789
) {
7890
this.traceDetails$ = this.apiTraceDetailService.fetchTraceDetails();
7991
this.logEvents$ = this.apiTraceDetailService.fetchLogEvents();
@@ -86,4 +98,9 @@ export class ApiTraceDetailPageComponent {
8698
public navigateToFullTrace(traceId: string, startTime: string): void {
8799
this.navigationService.navigateWithinApp(['/trace', traceId, { startTime: startTime }]);
88100
}
101+
102+
public getExplorerNavigationParams = (traceDetails: ApiTraceDetails): Observable<NavigationParams> =>
103+
this.explorerService.buildNavParamsWithFilters(ScopeQueryParam.EndpointTraces, [
104+
{ field: 'traceId', operator: FilterOperator.Equals, value: traceDetails.traceId }
105+
]);
89106
}

projects/observability/src/pages/api-trace-detail/api-trace-detail.page.module.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { CommonModule } from '@angular/common';
22
import { NgModule } from '@angular/core';
33
import { RouterModule } from '@angular/router';
4-
import { FormattingModule, HtRoute } from '@hypertrace/common';
4+
import { FormattingModule, HtRoute, MemoizeModule } from '@hypertrace/common';
55
import {
66
ButtonModule,
77
CopyShareableLinkToClipboardModule,
88
IconModule,
99
LabelModule,
1010
LoadAsyncModule,
1111
NavigableTabModule,
12-
SummaryValueModule
12+
SummaryValueModule,
13+
TooltipModule
1314
} from '@hypertrace/components';
15+
import { ExploreFilterLinkModule } from '../../shared/components/explore-filter-link/explore-filter-link.module';
1416
import { LogEventsTableModule } from '../../shared/components/log-events/log-events-table.module';
1517
import { NavigableDashboardModule } from '../../shared/dashboard/dashboard-wrapper/navigable-dashboard.module';
1618
import { ObservabilityDashboardModule } from '../../shared/dashboard/observability-dashboard.module';
@@ -51,8 +53,11 @@ const ROUTE_CONFIG: HtRoute[] = [
5153
IconModule,
5254
SummaryValueModule,
5355
LoadAsyncModule,
56+
MemoizeModule,
5457
FormattingModule,
5558
ButtonModule,
59+
TooltipModule,
60+
ExploreFilterLinkModule,
5661
CopyShareableLinkToClipboardModule,
5762
NavigableTabModule,
5863
LogEventsTableModule,

projects/observability/src/pages/trace-detail/trace-detail.page.component.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@
3737
height: 18px;
3838
align-items: center;
3939

40+
.filterable-summary-value {
41+
display: flex;
42+
align-items: center;
43+
}
44+
4045
.separation {
4146
flex: 1 1 auto;
4247
}
4348
}
4449

4550
.summary-value {
46-
margin-right: 24px;
51+
margin-right: 8px;
4752
}
4853

4954
.tabs {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { fakeAsync, tick } from '@angular/core/testing';
2+
import { MemoizeModule, NavigationService } from '@hypertrace/common';
3+
import { LoadAsyncModule } from '@hypertrace/components';
4+
import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest';
5+
import { MockComponent } from 'ng-mocks';
6+
import { of } from 'rxjs';
7+
import { ExploreFilterLinkComponent } from '../../shared/components/explore-filter-link/explore-filter-link.component';
8+
import { ExplorerService } from '../explorer/explorer-service';
9+
import { TraceDetailPageComponent } from './trace-detail.page.component';
10+
import { TraceDetails, TraceDetailService } from './trace-detail.service';
11+
describe('Trace Details Page Component', () => {
12+
const mockTraceDetails: TraceDetails = {
13+
id: 'test-id',
14+
entrySpanId: 'test-123',
15+
type: 'trace-type',
16+
timeString: 'test-time-string',
17+
titleString: 'test-title',
18+
startTime: 'test-start-time'
19+
};
20+
21+
const createComponent = createComponentFactory({
22+
component: TraceDetailPageComponent,
23+
shallow: true,
24+
providers: [
25+
mockProvider(NavigationService),
26+
mockProvider(ExplorerService, {
27+
buildNavParamsWithFilters: jest.fn().mockReturnValue(of('traceId_eq_test-123'))
28+
})
29+
],
30+
imports: [LoadAsyncModule, MemoizeModule],
31+
componentProviders: [
32+
mockProvider(TraceDetailService, {
33+
fetchTraceDetails: jest.fn().mockReturnValue(of(mockTraceDetails))
34+
})
35+
],
36+
declarations: [MockComponent(ExploreFilterLinkComponent)]
37+
});
38+
39+
test('should render content correctly', fakeAsync(() => {
40+
const spectator = createComponent();
41+
42+
spectator.click('.label');
43+
tick();
44+
expect(spectator.inject(NavigationService).navigateBack).toHaveBeenCalled();
45+
}));
46+
47+
test('should render explorer link component', fakeAsync(() => {
48+
const spectator = createComponent();
49+
expect(spectator.query(ExploreFilterLinkComponent)?.paramsOrUrl).toBe('traceId_eq_test-123');
50+
}));
51+
});

0 commit comments

Comments
 (0)