mirror of
https://github.com/docmost/docmost.git
synced 2025-11-13 05:32:38 +10:00
telemetry module (#934)
* update lockfile * fix color check * telemetry * complete * Use interval
This commit is contained in:
@ -46,6 +46,7 @@
|
||||
"@nestjs/passport": "^11.0.5",
|
||||
"@nestjs/platform-fastify": "^11.0.10",
|
||||
"@nestjs/platform-socket.io": "^11.0.10",
|
||||
"@nestjs/schedule": "^5.0.1",
|
||||
"@nestjs/terminus": "^11.0.0",
|
||||
"@nestjs/websockets": "^11.0.10",
|
||||
"@node-saml/passport-saml": "^5.0.1",
|
||||
|
||||
@ -15,6 +15,7 @@ import { HealthModule } from './integrations/health/health.module';
|
||||
import { ExportModule } from './integrations/export/export.module';
|
||||
import { ImportModule } from './integrations/import/import.module';
|
||||
import { SecurityModule } from './integrations/security/security.module';
|
||||
import { TelemetryModule } from './integrations/telemetry/telemetry.module';
|
||||
|
||||
const enterpriseModules = [];
|
||||
try {
|
||||
@ -50,6 +51,7 @@ try {
|
||||
}),
|
||||
EventEmitterModule.forRoot(),
|
||||
SecurityModule,
|
||||
TelemetryModule,
|
||||
...enterpriseModules,
|
||||
],
|
||||
controllers: [AppController],
|
||||
|
||||
@ -182,4 +182,11 @@ export class EnvironmentService {
|
||||
.toLowerCase();
|
||||
return isStandalone === 'true';
|
||||
}
|
||||
|
||||
isDisableTelemetry(): boolean {
|
||||
const disable = this.configService
|
||||
.get<string>('DISABLE_TELEMETRY', 'false')
|
||||
.toLowerCase();
|
||||
return disable === 'true';
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TelemetryService } from './telemetry.service';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
|
||||
@Module({
|
||||
providers: [TelemetryService],
|
||||
imports: [ScheduleModule.forRoot()],
|
||||
})
|
||||
export class TelemetryModule {}
|
||||
87
apps/server/src/integrations/telemetry/telemetry.service.ts
Normal file
87
apps/server/src/integrations/telemetry/telemetry.service.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Interval, SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { EnvironmentService } from '../environment/environment.service';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
||||
import { createHmac } from 'node:crypto';
|
||||
import { WorkspaceRepo } from '@docmost/db/repos/workspace/workspace.repo';
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const packageJson = require('./../../../package.json');
|
||||
|
||||
@Injectable()
|
||||
export class TelemetryService {
|
||||
private readonly ENDPOINT_URL = 'https://tel.docmost.com/api/event';
|
||||
|
||||
constructor(
|
||||
private readonly environmentService: EnvironmentService,
|
||||
@InjectKysely() private readonly db: KyselyDB,
|
||||
private readonly workspaceRepo: WorkspaceRepo,
|
||||
private schedulerRegistry: SchedulerRegistry,
|
||||
) {}
|
||||
|
||||
@Interval('telemetry', 24 * 60 * 60 * 1000)
|
||||
async sendTelemetry() {
|
||||
try {
|
||||
if (
|
||||
this.environmentService.isDisableTelemetry() ||
|
||||
this.environmentService.isCloud() ||
|
||||
this.environmentService.getNodeEnv() !== 'production'
|
||||
) {
|
||||
this.schedulerRegistry.deleteInterval('telemetry');
|
||||
return;
|
||||
}
|
||||
|
||||
const workspace = await this.workspaceRepo.findFirst();
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
const anonymizedHash = createHmac(
|
||||
'sha256',
|
||||
this.environmentService.getAppSecret(),
|
||||
)
|
||||
.update(workspace.id)
|
||||
.digest('hex');
|
||||
|
||||
const { userCount } = await this.db
|
||||
.selectFrom('users')
|
||||
.select((eb) => eb.fn.count('id').as('userCount'))
|
||||
.executeTakeFirst();
|
||||
|
||||
const { pageCount } = await this.db
|
||||
.selectFrom('pages')
|
||||
.select((eb) => eb.fn.count('id').as('pageCount'))
|
||||
.executeTakeFirst();
|
||||
|
||||
const { workspaceCount } = await this.db
|
||||
.selectFrom('workspaces')
|
||||
.select((eb) => eb.fn.count('id').as('workspaceCount'))
|
||||
.executeTakeFirst();
|
||||
|
||||
const { spaceCount } = await this.db
|
||||
.selectFrom('spaces')
|
||||
.select((eb) => eb.fn.count('id').as('spaceCount'))
|
||||
.executeTakeFirst();
|
||||
|
||||
const data = {
|
||||
instanceId: anonymizedHash,
|
||||
version: packageJson.version,
|
||||
userCount,
|
||||
pageCount,
|
||||
spaceCount,
|
||||
workspaceCount,
|
||||
};
|
||||
|
||||
await fetch(this.ENDPOINT_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'User-Agent': 'docmost:' + data.version,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
} catch (err) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user