diff --git a/apps/api/src/app/app.controller.ts b/apps/api/src/app/app.controller.ts index 1490f601..552c340d 100644 --- a/apps/api/src/app/app.controller.ts +++ b/apps/api/src/app/app.controller.ts @@ -32,6 +32,7 @@ import { link as LinkModel, Prisma, link } from '@prisma/client'; import { AddROToResponseInterceptor } from './interceptors/addROToResponseInterceptor'; import { ApiBody, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { ConfigService } from '@nestjs/config'; +import { TelemetryService } from './telemetry/telemetry.service'; @Controller() @UseInterceptors(AddROToResponseInterceptor) @@ -47,6 +48,7 @@ export class AppController { private prismaIndicator: PrismaHealthIndicator, private readonly configService: ConfigService, private readonly redisService: RedisService, + private readonly telemetryService: TelemetryService, @Inject('CLICK_SERVICE') private clickServiceClient: ClientProxy ) { this.redis = redisService.getClient(configService.get('REDIS_NAME')); @@ -92,7 +94,9 @@ export class AppController { @ApiResponse({ status: 301, description: 'will be redirected to the specified link'}) async redirect(@Param('hashid') hashid: string, @Res() res) { - const reRouteURL: string = await this.appService.resolveRedirect(hashid); + const response = await this.appService.resolveRedirect(hashid); + const reRouteURL: string = response?.reRouteurl; + const redirectedLink: LinkModel = response?.redirectedLink; if (reRouteURL !== '') { console.log({reRouteURL}); @@ -101,6 +105,18 @@ export class AppController { hashid: hashid, }) .subscribe(); + + this.telemetryService.sendEvent( + this.configService.get("POSTHOG_DISTINCT_KEY"), + `Redirected Link`, + { + linkId:redirectedLink.id, + routeName: `/${hashid}}`, + queryParams : redirectedLink?.params, + originalUrl: redirectedLink?.url, + redirectUrl: reRouteURL, + } + ); return res.redirect(302, reRouteURL); } else { throw new NotFoundException(); @@ -114,7 +130,18 @@ export class AppController { @ApiResponse({ type: Link, status: 200}) async register(@Body() link: Link): Promise { const response:Promise = this.appService.createLinkInDB(link); - return response; + return response + .then((createdLink) => { + this.telemetryService.sendEvent( + this.configService.get("POSTHOG_DISTINCT_KEY"), + `Created Link`, + { + routeName: `/register`, + link: createdLink, + } + ); + return createdLink; + }); } @Patch('update/:id') @@ -122,7 +149,21 @@ export class AppController { @ApiBody({ type: Link }) @ApiResponse({ type: Link, status: 200}) async update(@Param('id') id: string, @Body() link: link ): Promise { - return this.appService.updateLink(id, link); + + return this.appService.updateLink(id, link) + .then((updatedLink) => { + this.telemetryService.sendEvent( + this.configService.get("POSTHOG_DISTINCT_KEY"), + `Updated Link`, + { + linkId:updatedLink.id, + routeName: `update/:id`, + link: updatedLink, + updatedFields: Object.keys(link), + } + ); + return updatedLink; + }) } @MessagePattern('onClick') diff --git a/apps/api/src/app/app.service.ts b/apps/api/src/app/app.service.ts index 9c84d2b1..1e5bc6ad 100644 --- a/apps/api/src/app/app.service.ts +++ b/apps/api/src/app/app.service.ts @@ -187,7 +187,7 @@ export class AppService { * @param Id * @returns */ - async resolveRedirect(Id: string): Promise { + async resolveRedirect(Id: string): Promise<{reRouteurl:string,redirectedLink:link}> { const validHashIdRegex = /^[0-9]*$/; if(validHashIdRegex.test(Id)){ return this.redirect(Id); @@ -200,7 +200,7 @@ export class AppService { where: { customHashId: Id}, }); - let response = ""; + let response = { reRouteurl : "" , redirectedLink:null }; !(linkData == null) ? response = await this.redirect(linkData.hashid.toString()):0; return response; } @@ -216,26 +216,33 @@ export class AppService { * @param hashid * @returns */ - async redirect(hashid: string): Promise { + async redirect(hashid: string): Promise<{reRouteurl:string,redirectedLink:link}> { return this.redisUtils.fetchKey(hashid).then((value: string) => { const link = JSON.parse(value); - const url = link.url + let url = link.url const params = link.params const ret = []; if(params?.["status"] == "expired"){ - return ""; + return { reRouteurl : '' , redirectedLink:null }; + // return ""; } if(params == null){ - return url; + return { reRouteurl : url , redirectedLink:link }; + // return url; }else { Object.keys(params).forEach(function(d) { ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(params[d])); }) - return `${url}?${ret.join('&')}` || ''; + // check if url already has query params + const queryParams = new URL(url).searchParams; + url = ((queryParams.toString() === "") ? `${url}?${ret.join('&')}` || '' : `${url}&${ret.join('&')}` || ''); + + return { reRouteurl : url , redirectedLink:link }; + // return `${url}?${ret.join('&')}` || ''; } }) .catch(err => { @@ -251,7 +258,7 @@ export class AppService { * @param hashid * @returns */ - async redirectFromDB(hashid: string): Promise { + async redirectFromDB(hashid: string): Promise<{reRouteurl:string , redirectedLink:link}> { return this.prisma.link.findMany({ where: { OR: [ @@ -264,7 +271,7 @@ export class AppService { take: 1 }) .then(response => { - const url = response[0].url + let url = response[0].url const params = response[0].params const ret = []; @@ -278,23 +285,32 @@ export class AppService { // delete from DB and redis !!! // this.deleteLink({id: response[0].id}); // don't delete from DB keep it there this.redisUtils.clearKey(response[0]); - return ""; + return { reRouteurl : "" , redirectedLink: null }; + // return ""; } this.redisUtils.setKey(response[0]); if(params == null){ - return url; + return { reRouteurl : url , redirectedLink: null }; + // return url; }else { Object.keys(params).forEach(function(d) { ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(params[d])); }) - return `${url}?${ret.join('&')}` || ''; + + // check if url already has query params + const queryParams = new URL(url).searchParams; + url = ((queryParams.toString() === "") ? `${url}?${ret.join('&')}` || '' : `${url}&${ret.join('&')}` || ''); + + return { reRouteurl : url , redirectedLink:response[0] }; + // return `${url}?${ret.join('&')}` || ''; } }) .catch(err => { this.telemetryService.sendEvent(this.configService.get('POSTHOG_DISTINCT_KEY'), "Exception in getLinkFromHashIdOrCustomHashId query", {error: err.message}) - return ''; + return { reRouteurl : "" , redirectedLink: null }; + // return ''; }); } } diff --git a/apps/api/src/app/interceptors/addROToResponseInterceptor.ts b/apps/api/src/app/interceptors/addROToResponseInterceptor.ts index 0b31ce59..10cd34f4 100644 --- a/apps/api/src/app/interceptors/addROToResponseInterceptor.ts +++ b/apps/api/src/app/interceptors/addROToResponseInterceptor.ts @@ -43,7 +43,7 @@ import { URLSearchParams } from 'url'; this.telemetryService.sendEvent( this.configService.get("POSTHOG_DISTINCT_KEY"), - `${url} Execution Time`, + `Endpoint accessed`, { routeName: name, executionTime: `${Date.now() - now}ms`,