diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts new file mode 100644 index 000000000..1a28c27bb --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; + +import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; +import { CreateAnalyticsInput } from 'src/engine/core-modules/analytics/dto/create-analytics.input'; +import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; + +@Injectable() +export class TelemetryListener { + constructor(private readonly analyticsService: AnalyticsService) {} + + @OnEvent('*.created') + async handleAllCreate(payload: ObjectRecordCreateEvent) { + this.analyticsService.create( + { + type: 'track', + name: payload.name, + data: JSON.parse(`{ + "eventName": "${payload.name}" + }`), + } as CreateAnalyticsInput, + payload.userId, + payload.workspaceId, + '', // voluntarely not retrieving this + '', // to avoid slowing down + '', + ); + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts index eccae0920..aca209118 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts @@ -11,6 +11,8 @@ import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature- import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +import { TelemetryListener } from 'src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener'; +import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; import { WorkspaceQueryRunnerService } from './workspace-query-runner.service'; @@ -24,12 +26,14 @@ import { EntityEventsToDbListener } from './listeners/entity-events-to-db.listen WorkspacePreQueryHookModule, TypeOrmModule.forFeature([Workspace, FeatureFlagEntity], 'core'), ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberObjectMetadata]), + AnalyticsModule, ], providers: [ WorkspaceQueryRunnerService, ...workspaceQueryRunnerFactories, RecordPositionListener, EntityEventsToDbListener, + TelemetryListener, ], exports: [WorkspaceQueryRunnerService], }) diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts index 6d9cc9178..7ce66bafd 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts @@ -11,5 +11,6 @@ import { AnalyticsResolver } from './analytics.resolver'; baseURL: 'https://t.twenty.com/api/v1/s2s', }), ], + exports: [AnalyticsService], }) export class AnalyticsModule {} diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts index c62f30e0e..7f3e710fc 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts @@ -28,9 +28,11 @@ export class AnalyticsResolver { ) { return this.analyticsService.create( createAnalyticsInput, - user, - workspace, - request, + user?.id, + workspace?.id, + workspace?.displayName, + workspace?.domainName, + request.hostname, ); } } diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts index c8105bb00..0f3de7b9f 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts @@ -1,12 +1,8 @@ import { Injectable, Logger } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; -import { Request } from 'express'; - import { anonymize } from 'src/utils/anonymize'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { CreateAnalyticsInput } from './dto/create-analytics.input'; @@ -21,9 +17,11 @@ export class AnalyticsService { async create( createEventInput: CreateAnalyticsInput, - user: User | undefined, - workspace: Workspace | undefined, - request: Request, + userId: string | undefined, + workspaceId: string | undefined, + workspaceDisplayName: string | undefined, + workspaceDomainName: string | undefined, + hostName: string | undefined, ) { if (!this.environmentService.get('TELEMETRY_ENABLED')) { return { success: true }; @@ -36,19 +34,14 @@ export class AnalyticsService { const data = { type: createEventInput.type, data: { - hostname: request.hostname, - userUUID: user - ? anonymizationEnabled - ? anonymize(user.id) - : user.id - : undefined, - workspaceUUID: workspace - ? anonymizationEnabled - ? anonymize(workspace.id) - : workspace.id - : undefined, - workspaceDisplayName: workspace ? workspace.displayName : undefined, - workspaceDomainName: workspace ? workspace.domainName : undefined, + hostname: hostName, + userUUID: anonymizationEnabled && userId ? anonymize(userId) : userId, + workspaceUUID: + anonymizationEnabled && workspaceId + ? anonymize(workspaceId) + : workspaceId, + workspaceDisplayName: workspaceDisplayName, + workspaceDomainName: workspaceDomainName, ...createEventInput.data, }, };