@ahmedhegazee/nestjs-telescope
Version:
Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling
245 lines (244 loc) • 7.04 kB
TypeScript
import { OnModuleInit } from '@nestjs/common';
import { Observable } from 'rxjs';
import { TelescopeConfig } from '../interfaces/telescope-config.interface';
export interface MultiTenantConfig {
enabled: boolean;
isolation: {
strategy: 'database' | 'schema' | 'row' | 'application';
databasePrefix: string;
schemaPrefix: string;
};
management: {
autoProvisioning: boolean;
resourceLimits: boolean;
billing: boolean;
quotas: {
storage: number;
requests: number;
users: number;
watchers: number;
};
};
features: {
customBranding: boolean;
customThemes: boolean;
customConfigurations: boolean;
whiteLabel: boolean;
};
security: {
tenantIsolation: boolean;
crossTenantAccess: boolean;
dataEncryption: boolean;
};
}
export interface Tenant {
id: string;
name: string;
slug: string;
domain?: string;
status: 'active' | 'suspended' | 'pending' | 'deleted';
plan: 'free' | 'basic' | 'professional' | 'enterprise';
createdAt: Date;
updatedAt: Date;
metadata: {
industry?: string;
size?: string;
region?: string;
timezone?: string;
language?: string;
};
configuration: TenantConfiguration;
limits: TenantLimits;
usage: TenantUsage;
branding: TenantBranding;
}
export interface TenantConfiguration {
features: {
requestWatcher: boolean;
queryWatcher: boolean;
exceptionWatcher: boolean;
jobWatcher: boolean;
cacheWatcher: boolean;
mlAnalytics: boolean;
alerting: boolean;
dashboard: boolean;
};
settings: {
dataRetention: number;
samplingRate: number;
alertChannels: string[];
notificationPreferences: Record<string, any>;
};
integrations: {
slack?: SlackIntegration;
email?: EmailIntegration;
webhook?: WebhookIntegration;
custom?: CustomIntegration[];
};
}
export interface TenantLimits {
storage: number;
requests: number;
users: number;
watchers: number;
apiCalls: number;
customFields: number;
retentionDays: number;
}
export interface TenantUsage {
storage: number;
requests: number;
users: number;
watchers: number;
apiCalls: number;
customFields: number;
lastUpdated: Date;
}
export interface TenantBranding {
logo?: string;
favicon?: string;
primaryColor?: string;
secondaryColor?: string;
companyName?: string;
customCss?: string;
customJs?: string;
theme: 'light' | 'dark' | 'auto';
}
export interface SlackIntegration {
webhookUrl: string;
channel: string;
enabled: boolean;
}
export interface EmailIntegration {
smtp: {
host: string;
port: number;
secure: boolean;
username: string;
password: string;
};
fromEmail: string;
fromName: string;
enabled: boolean;
}
export interface WebhookIntegration {
url: string;
method: 'GET' | 'POST' | 'PUT';
headers: Record<string, string>;
enabled: boolean;
}
export interface CustomIntegration {
name: string;
type: string;
config: Record<string, any>;
enabled: boolean;
}
export interface TenantProvisioningResult {
success: boolean;
tenant?: Tenant;
error?: string;
resources?: {
database: string;
schema?: string;
storage: string;
};
}
export interface TenantMetrics {
tenantId: string;
timestamp: Date;
requests: number;
storage: number;
users: number;
errors: number;
performance: {
averageResponseTime: number;
throughput: number;
errorRate: number;
};
}
export interface TenantQuotaExceeded {
tenantId: string;
resource: string;
current: number;
limit: number;
timestamp: Date;
}
export declare class MultiTenantService implements OnModuleInit {
private readonly telescopeConfig;
private readonly logger;
private readonly tenants;
private readonly tenantMetrics;
private readonly quotaExceeded;
private readonly config;
private readonly tenantSubject;
private readonly metricsSubject;
private readonly quotaSubject;
private monitoringInterval;
constructor(telescopeConfig: TelescopeConfig);
onModuleInit(): Promise<void>;
private getDefaultMultiTenantConfig;
private initializeMultiTenancy;
private createDefaultTenant;
private getDefaultConfiguration;
private getDefaultLimits;
private getDefaultUsage;
private getDefaultBranding;
private initializeTenantIsolation;
private initializeDatabaseIsolation;
private initializeSchemaIsolation;
private initializeRowIsolation;
private initializeApplicationIsolation;
private initializeResourceMonitoring;
private startMonitoring;
provisionTenant(tenantData: {
name: string;
slug: string;
domain?: string;
plan: Tenant['plan'];
metadata?: Tenant['metadata'];
}): Promise<TenantProvisioningResult>;
private getConfigurationForPlan;
private getLimitsForPlan;
private provisionTenantResources;
updateTenant(tenantId: string, updates: Partial<Tenant>): Promise<Tenant | null>;
suspendTenant(tenantId: string, reason?: string): Promise<boolean>;
activateTenant(tenantId: string): Promise<boolean>;
deleteTenant(tenantId: string): Promise<boolean>;
private hardDeleteTenant;
private deleteTenantResources;
private monitorTenantResources;
private checkTenantQuotas;
private handleQuotaExceeded;
private updateTenantUsage;
getTenantContext(tenantId: string): Promise<{
tenant: Tenant;
isolation: {
database: string;
schema?: string;
prefix: string;
};
} | null>;
validateTenantAccess(tenantId: string, userId: string): Promise<boolean>;
updateTenantBranding(tenantId: string, branding: Partial<TenantBranding>): Promise<Tenant | null>;
updateTenantConfiguration(tenantId: string, configuration: Partial<TenantConfiguration>): Promise<Tenant | null>;
getTenants(): Tenant[];
getTenantById(tenantId: string): Tenant | undefined;
getTenantBySlug(slug: string): Tenant | undefined;
getTenantMetrics(tenantId: string): TenantMetrics[];
getQuotaExceeded(tenantId: string): TenantQuotaExceeded[];
getTenantUpdates(): Observable<Tenant>;
getMetricsUpdates(): Observable<TenantMetrics>;
getQuotaUpdates(): Observable<TenantQuotaExceeded>;
getTenantReport(tenantId: string): Promise<{
tenant: Tenant;
metrics: TenantMetrics[];
quotaExceeded: TenantQuotaExceeded[];
usage: {
storage: number;
requests: number;
users: number;
watchers: number;
};
} | null>;
shutdown(): Promise<void>;
}