Skip to content

Commit b6a230c

Browse files
authored
Merge pull request #2231 from RedisInsight/feature/RI-4667_Telemetry_improvements
Feature/ri 4667 telemetry improvements
2 parents 340e968 + 152d930 commit b6a230c

File tree

12 files changed

+160
-32
lines changed

12 files changed

+160
-32
lines changed

redisinsight/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"start": "nest start",
2424
"start:dev": "cross-env NODE_ENV=development BUILD_TYPE=DOCKER_ON_PREMISE SERVER_STATIC_CONTENT=1 nest start --watch",
2525
"start:debug": "nest start --debug --watch",
26-
"start:stage": "cross-env NODE_ENV=staging SERVER_STATIC_CONTENT=true node dist/src/main",
26+
"start:stage": "cross-env NODE_ENV=staging BUILD_TYPE=DOCKER_ON_PREMISE SERVER_STATIC_CONTENT=true node dist/src/main",
2727
"start:prod": "cross-env NODE_ENV=production node dist/src/main",
2828
"test": "cross-env NODE_ENV=test ./node_modules/.bin/jest -w 1",
2929
"test:watch": "cross-env NODE_ENV=test jest --watch -w 1",

redisinsight/api/src/constants/telemetry-events.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ export enum TelemetryEvents {
7272
FeatureFlagConfigUpdateError = 'FEATURE_FLAG_CONFIG_UPDATE_ERROR',
7373
FeatureFlagInvalidRemoteConfig = 'FEATURE_FLAG_INVALID_REMOTE_CONFIG',
7474
FeatureFlagRecalculated = 'FEATURE_FLAG_RECALCULATED',
75+
76+
// Insights
77+
InsightsRecommendationGenerated = 'INSIGHTS_RECOMMENDATION_GENERATED',
7578
}
7679

7780
export enum CommandType {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { EventEmitter2 } from '@nestjs/event-emitter';
3+
import {
4+
mockDatabase,
5+
mockDatabaseRecommendation,
6+
mockDatabaseWithTlsAuth,
7+
} from 'src/__mocks__';
8+
import { TelemetryEvents } from 'src/constants';
9+
import { DatabaseRecommendationAnalytics } from './database-recommendation.analytics';
10+
11+
const provider = 'cloud';
12+
13+
describe('DatabaseRecommendationAnalytics', () => {
14+
let service: DatabaseRecommendationAnalytics;
15+
let sendEventSpy;
16+
let sendFailedEventSpy;
17+
18+
beforeEach(async () => {
19+
const module: TestingModule = await Test.createTestingModule({
20+
providers: [
21+
EventEmitter2,
22+
DatabaseRecommendationAnalytics,
23+
],
24+
}).compile();
25+
26+
service = await module.get(DatabaseRecommendationAnalytics);
27+
sendEventSpy = jest.spyOn(service as any, 'sendEvent');
28+
sendFailedEventSpy = jest.spyOn(service as any, 'sendFailedEvent');
29+
});
30+
31+
describe('sendInstanceAddedEvent', () => {
32+
it('should emit event with recommendationName and provider', () => {
33+
service.sendCreatedRecommendationEvent(
34+
mockDatabaseRecommendation,
35+
mockDatabaseWithTlsAuth,
36+
);
37+
38+
expect(sendEventSpy).toHaveBeenCalledWith(
39+
TelemetryEvents.InsightsRecommendationGenerated,
40+
{
41+
recommendationName: mockDatabaseRecommendation.name,
42+
databaseId: mockDatabase.id,
43+
provider: mockDatabaseWithTlsAuth.provider,
44+
},
45+
);
46+
});
47+
});
48+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { EventEmitter2 } from '@nestjs/event-emitter';
3+
import { TelemetryBaseService } from 'src/modules/analytics/telemetry.base.service';
4+
import { TelemetryEvents } from 'src/constants';
5+
import { DatabaseRecommendation } from './models';
6+
import { Database } from '../database/models/database';
7+
8+
@Injectable()
9+
export class DatabaseRecommendationAnalytics extends TelemetryBaseService {
10+
constructor(protected eventEmitter: EventEmitter2) {
11+
super(eventEmitter);
12+
}
13+
14+
sendCreatedRecommendationEvent(recommendation: DatabaseRecommendation, database: Database): void {
15+
try {
16+
this.sendEvent(
17+
TelemetryEvents.InsightsRecommendationGenerated,
18+
{
19+
recommendationName: recommendation.name,
20+
databaseId: database.id,
21+
provider: database.provider,
22+
},
23+
);
24+
} catch (e) {
25+
// ignore
26+
}
27+
}
28+
}

redisinsight/api/src/modules/database-recommendation/database-recommendation.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { DatabaseRecommendationGateway } from 'src/modules/database-recommendati
1010
import {
1111
DatabaseRecommendationEmitter,
1212
} from 'src/modules/database-recommendation/providers/database-recommendation.emitter';
13+
import { DatabaseRecommendationAnalytics } from 'src/modules/database-recommendation/database-recommendation.analytics';
1314

1415
@Module({})
1516
export class DatabaseRecommendationModule {
@@ -25,6 +26,7 @@ export class DatabaseRecommendationModule {
2526
RecommendationProvider,
2627
DatabaseRecommendationGateway,
2728
DatabaseRecommendationEmitter,
29+
DatabaseRecommendationAnalytics,
2830
{
2931
provide: DatabaseRecommendationRepository,
3032
useClass: databaseRecommendationRepository,

redisinsight/api/src/modules/database-recommendation/database-recommendation.service.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from 'src/modules/database-recommendation/dto/database-recommendations.response';
1212
import { Recommendation } from 'src/modules/database-analysis/models/recommendation';
1313
import { ModifyDatabaseRecommendationDto, DeleteDatabaseRecommendationResponse } from './dto';
14+
import { DatabaseRecommendationAnalytics } from './database-recommendation.analytics';
1415
import { DatabaseService } from '../database/database.service';
1516

1617
@Injectable()
@@ -21,19 +22,22 @@ export class DatabaseRecommendationService {
2122
private readonly databaseRecommendationRepository: DatabaseRecommendationRepository,
2223
private readonly scanner: RecommendationScanner,
2324
private readonly databaseService: DatabaseService,
25+
private readonly analytics: DatabaseRecommendationAnalytics,
2426
) {}
2527

2628
/**
2729
* Create recommendation entity
2830
* @param clientMetadata
29-
* @param recommendationName
31+
* @param entity
3032
*/
31-
public async create(clientMetadata: ClientMetadata, recommendationName: string): Promise<DatabaseRecommendation> {
32-
const entity = plainToClass(
33-
DatabaseRecommendation,
34-
{ databaseId: clientMetadata?.databaseId, name: recommendationName },
35-
);
36-
return this.databaseRecommendationRepository.create(entity);
33+
public async create(clientMetadata: ClientMetadata, entity: DatabaseRecommendation): Promise<DatabaseRecommendation> {
34+
const recommendation = await this.databaseRecommendationRepository.create(entity);
35+
36+
const database = await this.databaseService.get(clientMetadata?.databaseId);
37+
38+
this.analytics.sendCreatedRecommendationEvent(recommendation, database);
39+
40+
return recommendation;
3741
}
3842

3943
/**
@@ -74,7 +78,7 @@ export class DatabaseRecommendationService {
7478
{ databaseId: newClientMetadata?.databaseId, ...recommendation },
7579
);
7680

77-
return await this.databaseRecommendationRepository.create(entity);
81+
return await this.create(newClientMetadata, entity);
7882
}
7983
}
8084

redisinsight/ui/src/components/live-time-recommendations/components/recommendation/Recommendation.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,27 @@ const Recommendation = ({
135135
setIsLoading(false)
136136
}
137137

138+
const onRecommendationLinkClick = () => {
139+
sendEventTelemetry({
140+
event: TelemetryEvent.INSIGHTS_RECOMMENDATION_LINK_CLICKED,
141+
eventData: {
142+
databaseId: instanceId,
143+
name: recommendationsContent[name]?.telemetryEvent ?? name,
144+
provider
145+
}
146+
})
147+
setIsLoading(false)
148+
}
149+
138150
const recommendationContent = () => (
139151
<EuiText>
140152
{renderRecommendationContent(
141153
recommendationsContent[name]?.content,
142154
params,
143-
recommendationsContent[name]?.telemetryEvent ?? name,
155+
{
156+
onClickLink: onRecommendationLinkClick,
157+
telemetryName: recommendationsContent[name]?.telemetryEvent ?? name,
158+
},
144159
true
145160
)}
146161
{!!params?.keys?.length && (

redisinsight/ui/src/components/recommendation-voting/RecommendationVoting.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const RecommendationVoting = ({ vote, name, id = '', live = false, containerClas
3131
gutterSize={live ? 'none' : 'l'}
3232
data-testid="recommendation-voting"
3333
>
34-
<EuiText size="m">Is this useful?</EuiText>
34+
<EuiText size="m" className={cx({ [styles.highlightText]: live })}>Is this useful?</EuiText>
3535
<div className="voteContent">
3636
{Object.values(Vote).map((option) => (
3737
<VoteOption

redisinsight/ui/src/components/recommendation-voting/styles.module.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@
2929
}
3030
}
3131

32+
div.highlightText {
33+
color: var(--euiColorPrimary) !important;
34+
}

redisinsight/ui/src/telemetry/events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,5 @@ export enum TelemetryEvent {
237237
INSIGHTS_RECOMMENDATION_SHOW_HIDDEN = 'INSIGHTS_RECOMMENDATION_SHOW_HIDDEN',
238238
INSIGHTS_RECOMMENDATION_DATABASE_ANALYSIS_CLICKED = 'INSIGHTS_RECOMMENDATION_DATABASE_ANALYSIS_CLICKED',
239239
INSIGHTS_RECOMMENDATION_KEY_COPIED = 'INSIGHTS_RECOMMENDATION_KEY_COPIED',
240+
INSIGHTS_RECOMMENDATION_LINK_CLICKED = 'INSIGHTS_RECOMMENDATION_LINK_CLICKED',
240241
}

0 commit comments

Comments
 (0)