mirror of
https://github.com/immich-app/immich.git
synced 2025-01-21 00:52:43 -05:00
initial sample implementation of metrics
This commit is contained in:
parent
8fdd3aaed1
commit
874f707c92
13 changed files with 109 additions and 1 deletions
|
@ -11,6 +11,7 @@ import { JobService } from './job';
|
|||
import { LibraryService } from './library';
|
||||
import { MediaService } from './media';
|
||||
import { MetadataService } from './metadata';
|
||||
import { MetricsService } from './metrics';
|
||||
import { PartnerService } from './partner';
|
||||
import { PersonService } from './person';
|
||||
import { SearchService } from './search';
|
||||
|
@ -34,6 +35,7 @@ const providers: Provider[] = [
|
|||
JobService,
|
||||
MediaService,
|
||||
MetadataService,
|
||||
MetricsService,
|
||||
LibraryService,
|
||||
PersonService,
|
||||
PartnerService,
|
||||
|
|
|
@ -14,6 +14,7 @@ export * from './job';
|
|||
export * from './library';
|
||||
export * from './media';
|
||||
export * from './metadata';
|
||||
export * from './metrics';
|
||||
export * from './partner';
|
||||
export * from './person';
|
||||
export * from './repositories';
|
||||
|
|
|
@ -81,6 +81,9 @@ export enum JobName {
|
|||
SIDECAR_DISCOVERY = 'sidecar-discovery',
|
||||
SIDECAR_SYNC = 'sidecar-sync',
|
||||
SIDECAR_WRITE = 'sidecar-write',
|
||||
|
||||
// metrics
|
||||
METRICS = 'metrics',
|
||||
}
|
||||
|
||||
export const JOBS_ASSET_PAGINATION_SIZE = 1000;
|
||||
|
@ -95,6 +98,7 @@ export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
|
|||
[JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.PERSON_DELETE]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.METRICS]: QueueName.BACKGROUND_TASK,
|
||||
|
||||
// conversion
|
||||
[JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION,
|
||||
|
|
2
server/src/domain/metrics/index.ts
Normal file
2
server/src/domain/metrics/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './metrics.dto';
|
||||
export * from './metrics.service';
|
14
server/src/domain/metrics/metrics.dto.ts
Normal file
14
server/src/domain/metrics/metrics.dto.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
export class MetricsServerInfoDto {
|
||||
version?: string;
|
||||
diskUse?: string;
|
||||
}
|
||||
|
||||
export class MetricsAssetCountDto {
|
||||
photo?: number;
|
||||
video?: number;
|
||||
}
|
||||
|
||||
export class MetricsDto {
|
||||
serverInfo!: MetricsServerInfoDto;
|
||||
assetCount!: MetricsAssetCountDto;
|
||||
}
|
50
server/src/domain/metrics/metrics.service.ts
Normal file
50
server/src/domain/metrics/metrics.service.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ICommunicationRepository,
|
||||
IServerInfoRepository,
|
||||
IStorageRepository,
|
||||
ISystemConfigRepository,
|
||||
IUserRepository,
|
||||
} from '../repositories';
|
||||
import { IMetricsRepository, SharedMetrics } from '../repositories/metrics.repository';
|
||||
import { ServerInfoService } from '../server-info';
|
||||
import { MetricsDto } from './metrics.dto';
|
||||
|
||||
@Injectable()
|
||||
export class MetricsService {
|
||||
private serverInfo: ServerInfoService;
|
||||
|
||||
constructor(
|
||||
@Inject(ICommunicationRepository) communicationRepository: ICommunicationRepository,
|
||||
@Inject(IMetricsRepository) private repository: IMetricsRepository,
|
||||
@Inject(IUserRepository) userRepository: IUserRepository,
|
||||
@Inject(IServerInfoRepository) serverInfoRepository: IServerInfoRepository,
|
||||
@Inject(IStorageRepository) storageRepository: IStorageRepository,
|
||||
@Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository,
|
||||
) {
|
||||
this.serverInfo = new ServerInfoService(
|
||||
communicationRepository,
|
||||
configRepository,
|
||||
userRepository,
|
||||
serverInfoRepository,
|
||||
storageRepository,
|
||||
);
|
||||
}
|
||||
|
||||
async shareMetrics(metrics: SharedMetrics) {
|
||||
const metricsPayload = new MetricsDto();
|
||||
if (metrics.serverInfo) {
|
||||
metricsPayload.serverInfo.version = this.serverInfo.getVersion().toString();
|
||||
metricsPayload.serverInfo.diskUse = (await this.serverInfo.getInfo()).diskUse;
|
||||
}
|
||||
|
||||
if (metrics.assetCount) {
|
||||
const stats = await this.serverInfo.getStatistics();
|
||||
metricsPayload.assetCount.photo = stats.photos;
|
||||
metricsPayload.assetCount.video = stats.videos;
|
||||
}
|
||||
|
||||
await this.repository.sendMetrics(metricsPayload);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ export * from './library.repository';
|
|||
export * from './machine-learning.repository';
|
||||
export * from './media.repository';
|
||||
export * from './metadata.repository';
|
||||
export * from './metrics.repository';
|
||||
export * from './move.repository';
|
||||
export * from './partner.repository';
|
||||
export * from './person.repository';
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
ILibraryRefreshJob,
|
||||
ISidecarWriteJob,
|
||||
} from '../job/job.interface';
|
||||
import { SharedMetrics } from './metrics.repository';
|
||||
|
||||
export interface JobCounts {
|
||||
active: number;
|
||||
|
@ -89,7 +90,10 @@ export type JobItem =
|
|||
| { name: JobName.LIBRARY_REMOVE_OFFLINE; data: IEntityJob }
|
||||
| { name: JobName.LIBRARY_DELETE; data: IEntityJob }
|
||||
| { name: JobName.LIBRARY_QUEUE_SCAN_ALL; data: IBaseJob }
|
||||
| { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob };
|
||||
| { name: JobName.LIBRARY_QUEUE_CLEANUP; data: IBaseJob }
|
||||
|
||||
// Metrics
|
||||
| { name: JobName.METRICS; data: SharedMetrics };
|
||||
|
||||
export type JobHandler<T = any> = (data: T) => boolean | Promise<boolean>;
|
||||
export type JobItemHandler = (item: JobItem) => Promise<void>;
|
||||
|
|
12
server/src/domain/repositories/metrics.repository.ts
Normal file
12
server/src/domain/repositories/metrics.repository.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { MetricsDto } from '../metrics';
|
||||
|
||||
export const IMetricsRepository = 'IMetricsRepository';
|
||||
|
||||
export interface SharedMetrics {
|
||||
serverInfo: boolean;
|
||||
assetCount: boolean;
|
||||
}
|
||||
|
||||
export interface IMetricsRepository {
|
||||
sendMetrics(payload: MetricsDto): Promise<void>;
|
||||
}
|
|
@ -13,6 +13,7 @@ import {
|
|||
IMachineLearningRepository,
|
||||
IMediaRepository,
|
||||
IMetadataRepository,
|
||||
IMetricsRepository,
|
||||
IMoveRepository,
|
||||
IPartnerRepository,
|
||||
IPersonRepository,
|
||||
|
@ -51,6 +52,7 @@ import {
|
|||
MachineLearningRepository,
|
||||
MediaRepository,
|
||||
MetadataRepository,
|
||||
MetricsRepository,
|
||||
MoveRepository,
|
||||
PartnerRepository,
|
||||
PersonRepository,
|
||||
|
@ -78,6 +80,7 @@ const providers: Provider[] = [
|
|||
{ provide: IKeyRepository, useClass: ApiKeyRepository },
|
||||
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
||||
{ provide: IMetadataRepository, useClass: MetadataRepository },
|
||||
{ provide: IMetricsRepository, useClass: MetricsRepository },
|
||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
||||
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
||||
{ provide: IPersonRepository, useClass: PersonRepository },
|
||||
|
|
|
@ -13,6 +13,7 @@ export * from './library.repository';
|
|||
export * from './machine-learning.repository';
|
||||
export * from './media.repository';
|
||||
export * from './metadata.repository';
|
||||
export * from './metrics.repository';
|
||||
export * from './move.repository';
|
||||
export * from './partner.repository';
|
||||
export * from './person.repository';
|
||||
|
|
11
server/src/infra/repositories/metrics.repository.ts
Normal file
11
server/src/infra/repositories/metrics.repository.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { MetricsDto } from '@app/domain/metrics';
|
||||
import { IMetricsRepository } from '@app/domain/repositories/metrics.repository';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import axios from 'axios';
|
||||
|
||||
@Injectable()
|
||||
export class MetricsRepository implements IMetricsRepository {
|
||||
async sendMetrics(payload: MetricsDto): Promise<void> {
|
||||
await axios.post('IMMICH-DATA-DOMAIN', payload);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import {
|
|||
SystemConfigService,
|
||||
UserService,
|
||||
} from '@app/domain';
|
||||
import { MetricsService } from '@app/domain/metrics';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
|
@ -27,6 +28,7 @@ export class AppService {
|
|||
private libraryService: LibraryService,
|
||||
private mediaService: MediaService,
|
||||
private metadataService: MetadataService,
|
||||
private metricsService: MetricsService,
|
||||
private personService: PersonService,
|
||||
private smartInfoService: SmartInfoService,
|
||||
private storageTemplateService: StorageTemplateService,
|
||||
|
@ -60,6 +62,7 @@ export class AppService {
|
|||
[JobName.VIDEO_CONVERSION]: (data) => this.mediaService.handleVideoConversion(data),
|
||||
[JobName.QUEUE_METADATA_EXTRACTION]: (data) => this.metadataService.handleQueueMetadataExtraction(data),
|
||||
[JobName.METADATA_EXTRACTION]: (data) => this.metadataService.handleMetadataExtraction(data),
|
||||
[JobName.METRICS]: (data) => this.metricsService.shareMetrics(data),
|
||||
[JobName.LINK_LIVE_PHOTOS]: (data) => this.metadataService.handleLivePhotoLinking(data),
|
||||
[JobName.QUEUE_RECOGNIZE_FACES]: (data) => this.personService.handleQueueRecognizeFaces(data),
|
||||
[JobName.RECOGNIZE_FACES]: (data) => this.personService.handleRecognizeFaces(data),
|
||||
|
|
Loading…
Add table
Reference in a new issue