Skip to content

Commit

Permalink
feat: experimental plugins registry; logger and metrics recorder plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
chejimmy authored and diehbria committed Nov 21, 2023
1 parent ec11c82 commit 95b904f
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ export const SECOND_IN_MS = 1000;
export const MINUTE_IN_MS = 60 * SECOND_IN_MS;
export const HOUR_IN_MS = 60 * MINUTE_IN_MS;
export const DAY_IN_MS = 24 * HOUR_IN_MS;

export type { Logger } from './logger/logger.interface';
export type { MetricsRecorder } from './metric-recorder/metricsRecorder.interface';
34 changes: 34 additions & 0 deletions packages/core/src/logger/logger.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Log represents a single event message to record.
*/
type Log = {
/**
* Additional contexts to include.
*/
contexts?: Record<string, string>;
message: string;
timestamp?: Date;
};

/**
* Logger gathers/emits {@link Log}.
*/
export interface Logger {
/**
* Record logs by {@link Logger}.
* @param log log to record
*/
log: (log: Log) => void;

/**
* Record error logs by {@link Logger}.
* @param log error log to record
*/
error: (log: Log) => void;

/**
* Record warn logs by {@link Logger}.
* @param log warn log to record
*/
warn: (log: Log) => void;
}
60 changes: 60 additions & 0 deletions packages/core/src/metric-recorder/metricsRecorder.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Metric represents a single event datum to record.
*
* @example
* // Example 1, metrics with same namespace:
*
* const metric1 = {
* contexts: {
* component: "Dashboard",
* },
* metricName: "latency",
* metricValue: 1,
* };
*
* const metric2 = {
* contexts: {
* component: "Dashboard",
* },
* metricName: "latency",
* metricValue: 2,
* };
*
* // Example 2, metrics with different namespace due to different contexts:
*
* const metric1 = {
* contexts: {
* component: "Dashboard",
* },
* metricName: "latency",
* metricValue: 1,
* };
*
* const metric2 = {
* contexts: {
* component: "IotResourceExplorer",
* },
* metricName: "latency",
* metricValue: 2,
* };
*/
type Metric = {
/**
* Additional contexts to separate the metricName.
*/
contexts?: Record<string, string>;
metricName: string;
metricValue: number;
timestamp?: Date;
};

/**
* MetricsRecorder gathers/emits {@link Metric}.
*/
export interface MetricsRecorder {
/**
* Record metric by {@link MetricsRecorder}.
* @param metric metric to record
*/
record: (metric: Metric) => void;
}
3 changes: 3 additions & 0 deletions packages/core/src/plugins/loggerSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { Logger } from '../logger/logger.interface';

export type LoggerSettings = { provider: () => Logger };
3 changes: 3 additions & 0 deletions packages/core/src/plugins/metricsRecorderSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { MetricsRecorder } from '../metric-recorder/metricsRecorder.interface';

export type MetricsRecorderSettings = { provider: () => MetricsRecorder };
55 changes: 55 additions & 0 deletions packages/core/src/plugins/pluginsRegistry.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { Logger } from '../logger/logger.interface';
import type { MetricsRecorder } from '../metric-recorder/metricsRecorder.interface';
import { getLogger, getMetricsRecorder, registerLogger, registerMetricsRecorder } from './pluginsRegistry';

describe('Logger registry', () => {
class MockLogClient implements Logger {
log() {}
error() {}
warn() {}
}

test('does not provide logger by default', () => {
const logger = getLogger();

expect(logger).toBeUndefined();
});

test('provides given logger', () => {
const mockLogClient = new MockLogClient();
const mockProvider = jest.fn().mockReturnValue(mockLogClient);

registerLogger({
provider: mockProvider,
});
const logger = getLogger();

expect(logger).toBe(mockLogClient);
expect(mockProvider).toBeCalled();
});
});

describe('MetricsRecorder registry', () => {
class MockMetricsRecorder implements MetricsRecorder {
record() {}
}

test('does not provide MetricsRecorder by default', () => {
const metricsRecorder = getMetricsRecorder();

expect(metricsRecorder).toBeUndefined();
});

test('provides given MetricsRecorder', () => {
const mockMetricsRecorder = new MockMetricsRecorder();
const mockProvider = jest.fn().mockReturnValue(mockMetricsRecorder);

registerMetricsRecorder({
provider: mockProvider,
});
const metricsRecorder = getMetricsRecorder();

expect(metricsRecorder).toBe(mockMetricsRecorder);
expect(mockProvider).toBeCalled();
});
});
44 changes: 44 additions & 0 deletions packages/core/src/plugins/pluginsRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { LoggerSettings } from './loggerSettings';
import type { MetricsRecorderSettings } from './metricsRecorderSettings';

/**
* Internal object to hold all of the plugins.
*
* @emarks Not exported to encapsulate the registry
*/
const pluginsRegistry: {
loggerSettings?: LoggerSettings;
metricsRecorderSettings?: MetricsRecorderSettings;
} = {};

/**
* Register a Logger for logging AppKit logs.
* @param param0 settings for Logger
* @alpha
*/
export const registerLogger = (settings: LoggerSettings) => {
pluginsRegistry.loggerSettings = settings;
};

/**
* Return the registered Logger.
* @returns the registered Logger.
* @alpha
*/
export const getLogger = () => pluginsRegistry.loggerSettings?.provider();

/**
* Register a MetricsRecorder for recording AppKit metrics.
* @param param0 settings for MetricsRecorder
* @alpha
*/
export const registerMetricsRecorder = (settings: MetricsRecorderSettings) => {
pluginsRegistry.metricsRecorderSettings = settings;
};

/**
* Return the registered MetricsRecorder.
* @returns the registered MetricsRecorder.
* @alpha
*/
export const getMetricsRecorder = () => pluginsRegistry.metricsRecorderSettings?.provider();

0 comments on commit 95b904f

Please sign in to comment.