Connect EventTracker to TB endpoint (#7240)
#7091 EventTrackers send information of events to the TinyBird instance: In order to test: 1. Set ANALYTICS_ENABLED= true and TELEMETRY_ENABLED=true in evironment-variables.ts 2. Set the TINYBIRD_TOKEN in environment variables (go to TiniyBird Tokens) 3. Log in to twenty's TinyBird and go to datasources/analytics_events in twenty_analytics workspace 4. Run twenty and navigate it 5. New events will be logged in the datasources, containing their timestamp, sessionId and payload. <img width="1189" alt="Screenshot 2024-09-24 at 17 23 01" src="https://github.com/user-attachments/assets/85375897-504d-4e75-98e4-98e6a9671f98"> Example of payload when user is not logged in ``` {"hostName":"localhost", "pathname":"/welcome", "locale":"en-US", "userAgent":"Mozilla/5.0", "href":"http://localhost:3001/welcome", "referrer":"", "timeZone":"Europe/Barcelona"} ``` Example of payload when user is logged in ``` {"userId":"2020202", "workspaceId":"202", "workspaceDisplayName":"Apple", "workspaceDomainName":"apple.dev", "hostName":"localhost", "pathname":"/objects/companies", "locale":"en-US", "userAgent":"Mozilla/5.0Chrome/128.0.0.0Safari/537.36", "href":"http://localhost:3001/objects/companies", "referrer":"", "timeZone":"Europe/Paris"} ``` --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
committed by
GitHub
parent
c9e882f4c0
commit
16bb1f22e4
@ -1,14 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { AnalyticsService } from './analytics.service';
|
||||
import { AnalyticsResolver } from './analytics.resolver';
|
||||
import { AnalyticsService } from './analytics.service';
|
||||
|
||||
const TINYBIRD_BASE_URL = 'https://api.eu-central-1.aws.tinybird.co/v0';
|
||||
|
||||
@Module({
|
||||
providers: [AnalyticsResolver, AnalyticsService],
|
||||
imports: [
|
||||
HttpModule.register({
|
||||
baseURL: 'https://t.twenty.com/api/v1/s2s',
|
||||
baseURL: TINYBIRD_BASE_URL,
|
||||
}),
|
||||
],
|
||||
exports: [AnalyticsService],
|
||||
|
||||
@ -31,9 +31,6 @@ export class AnalyticsResolver {
|
||||
createAnalyticsInput,
|
||||
user?.id,
|
||||
workspace?.id,
|
||||
workspace?.displayName,
|
||||
workspace?.domainName,
|
||||
this.environmentService.get('SERVER_URL') ?? request.hostname,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
|
||||
type CreateEventInput = {
|
||||
type: string;
|
||||
data: object;
|
||||
action: string;
|
||||
payload: object;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class AnalyticsService {
|
||||
private readonly logger = new Logger(AnalyticsService.name);
|
||||
private readonly datasource = 'event';
|
||||
|
||||
constructor(
|
||||
private readonly environmentService: EnvironmentService,
|
||||
@ -21,30 +24,42 @@ export class AnalyticsService {
|
||||
createEventInput: CreateEventInput,
|
||||
userId: string | null | undefined,
|
||||
workspaceId: string | null | undefined,
|
||||
workspaceDisplayName: string | undefined,
|
||||
workspaceDomainName: string | undefined,
|
||||
hostName: string | undefined,
|
||||
) {
|
||||
if (!this.environmentService.get('TELEMETRY_ENABLED')) {
|
||||
if (this.environmentService.get('ANALYTICS_ENABLED')) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
const data = {
|
||||
type: createEventInput.type,
|
||||
data: {
|
||||
hostname: hostName,
|
||||
userUUID: userId,
|
||||
workspaceUUID: workspaceId,
|
||||
workspaceDisplayName: workspaceDisplayName,
|
||||
workspaceDomainName: workspaceDomainName,
|
||||
...createEventInput.data,
|
||||
action: createEventInput.action,
|
||||
timestamp: new Date().toISOString(),
|
||||
version: '1',
|
||||
payload: {
|
||||
userId: userId,
|
||||
workspaceId: workspaceId,
|
||||
...createEventInput.payload,
|
||||
},
|
||||
};
|
||||
|
||||
const config: AxiosRequestConfig = {
|
||||
headers: {
|
||||
Authorization:
|
||||
'Bearer ' + this.environmentService.get('TINYBIRD_TOKEN'),
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
await this.httpService.axiosRef.post('/v1', data);
|
||||
} catch {
|
||||
this.logger.error('Failed to send analytics event');
|
||||
await this.httpService.axiosRef.post(
|
||||
`/events?name=${this.datasource}`,
|
||||
data,
|
||||
config,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error('Error occurred:', error);
|
||||
if (error.response) {
|
||||
this.logger.error(
|
||||
`Error response body: ${JSON.stringify(error.response.data)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { ArgsType, Field } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsObject, IsString } from 'class-validator';
|
||||
import graphqlTypeJson from 'graphql-type-json';
|
||||
import { IsNotEmpty, IsString, IsObject } from 'class-validator';
|
||||
|
||||
@ArgsType()
|
||||
export class CreateAnalyticsInput {
|
||||
@Field({ description: 'Type of the event' })
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
type: string;
|
||||
action: string;
|
||||
|
||||
@Field(() => graphqlTypeJson, { description: 'Event data in JSON format' })
|
||||
@Field(() => graphqlTypeJson, { description: 'Event payload in JSON format' })
|
||||
@IsObject()
|
||||
data: JSON;
|
||||
payload: JSON;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user