mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: configure logger during setup
This commit is contained in:
parent
09ac83caa5
commit
aaa49219dc
@ -8,6 +8,7 @@
|
|||||||
"files-scs:config/presets/ldp/operation-handler.json",
|
"files-scs:config/presets/ldp/operation-handler.json",
|
||||||
"files-scs:config/presets/ldp/permissions-extractor.json",
|
"files-scs:config/presets/ldp/permissions-extractor.json",
|
||||||
"files-scs:config/presets/ldp/request-parser.json",
|
"files-scs:config/presets/ldp/request-parser.json",
|
||||||
|
"files-scs:config/presets/logging.json",
|
||||||
"files-scs:config/presets/setup.json",
|
"files-scs:config/presets/setup.json",
|
||||||
"files-scs:config/presets/storage.json",
|
"files-scs:config/presets/storage.json",
|
||||||
"files-scs:config/presets/storage_wrapper.json",
|
"files-scs:config/presets/storage_wrapper.json",
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
{
|
{
|
||||||
"@id": "urn:solid-server:default:variable:rootFilePath",
|
"@id": "urn:solid-server:default:variable:rootFilePath",
|
||||||
"@type": "Variable"
|
"@type": "Variable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@id": "urn:solid-server:default:variable:loggingLevel",
|
||||||
|
"@type": "Variable"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
12
config/presets/logging.json
Normal file
12
config/presets/logging.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^1.0.0/components/context.jsonld",
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
|
"@id": "urn:solid-server:default:LoggerFactory",
|
||||||
|
"@type": "WinstonLoggerFactory",
|
||||||
|
"WinstonLoggerFactory:_level": {
|
||||||
|
"@id": "urn:solid-server:default:variable:loggingLevel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -13,6 +13,9 @@
|
|||||||
"Setup:_aclManager": {
|
"Setup:_aclManager": {
|
||||||
"@id": "urn:solid-server:default:AclManager"
|
"@id": "urn:solid-server:default:AclManager"
|
||||||
},
|
},
|
||||||
|
"Setup:_loggerFactory": {
|
||||||
|
"@id": "urn:solid-server:default:LoggerFactory"
|
||||||
|
},
|
||||||
"Setup:_base": {
|
"Setup:_base": {
|
||||||
"@id": "urn:solid-server:default:variable:base"
|
"@id": "urn:solid-server:default:variable:base"
|
||||||
},
|
},
|
||||||
|
10
index.ts
10
index.ts
@ -29,6 +29,16 @@ export * from './src/ldp/http/SparqlUpdateBodyParser';
|
|||||||
export * from './src/ldp/http/SparqlUpdatePatch';
|
export * from './src/ldp/http/SparqlUpdatePatch';
|
||||||
export * from './src/ldp/http/TargetExtractor';
|
export * from './src/ldp/http/TargetExtractor';
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
export * from './src/logging/LazyLogger';
|
||||||
|
export * from './src/logging/LazyLoggerFactory';
|
||||||
|
export * from './src/logging/Logger';
|
||||||
|
export * from './src/logging/LoggerFactory';
|
||||||
|
export * from './src/logging/LogLevel';
|
||||||
|
export * from './src/logging/LogUtil';
|
||||||
|
export * from './src/logging/VoidLoggerFactory';
|
||||||
|
export * from './src/logging/WinstonLoggerFactory';
|
||||||
|
|
||||||
// LDP/Operations
|
// LDP/Operations
|
||||||
export * from './src/ldp/operations/DeleteOperationHandler';
|
export * from './src/ldp/operations/DeleteOperationHandler';
|
||||||
export * from './src/ldp/operations/GetOperationHandler';
|
export * from './src/ldp/operations/GetOperationHandler';
|
||||||
|
@ -3,8 +3,11 @@ import type { ReadStream, WriteStream } from 'tty';
|
|||||||
import type { LoaderProperties } from 'componentsjs';
|
import type { LoaderProperties } from 'componentsjs';
|
||||||
import { Loader } from 'componentsjs';
|
import { Loader } from 'componentsjs';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
|
import { getLoggerFor } from '../logging/LogUtil';
|
||||||
import type { Setup } from './Setup';
|
import type { Setup } from './Setup';
|
||||||
|
|
||||||
|
const logger = getLoggerFor('CliRunner');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic run function for starting the server from a given config
|
* Generic run function for starting the server from a given config
|
||||||
* @param args - Command line arguments.
|
* @param args - Command line arguments.
|
||||||
@ -25,6 +28,7 @@ export const runCustom = function(
|
|||||||
.options({
|
.options({
|
||||||
port: { type: 'number', alias: 'p', default: 3000 },
|
port: { type: 'number', alias: 'p', default: 3000 },
|
||||||
config: { type: 'string', alias: 'c' },
|
config: { type: 'string', alias: 'c' },
|
||||||
|
level: { type: 'string', alias: 'l', default: 'info' },
|
||||||
})
|
})
|
||||||
.help();
|
.help();
|
||||||
|
|
||||||
@ -43,12 +47,14 @@ export const runCustom = function(
|
|||||||
'urn:solid-server:default:variable:port': argv.port,
|
'urn:solid-server:default:variable:port': argv.port,
|
||||||
'urn:solid-server:default:variable:base': `http://localhost:${argv.port}/`,
|
'urn:solid-server:default:variable:base': `http://localhost:${argv.port}/`,
|
||||||
'urn:solid-server:default:variable:rootFilePath': process.cwd(),
|
'urn:solid-server:default:variable:rootFilePath': process.cwd(),
|
||||||
|
'urn:solid-server:default:variable:loggingLevel': argv.level,
|
||||||
},
|
},
|
||||||
}) as Setup;
|
}) as Setup;
|
||||||
return await setup.setup();
|
return await setup.setup();
|
||||||
})().then((base: string): void => {
|
})().then((base: string): void => {
|
||||||
stdout.write(`Running at ${base}\n`);
|
logger.log('info', `Running at ${base}`);
|
||||||
}).catch((error): void => {
|
}).catch((error): void => {
|
||||||
|
// This is the only time we can *not* use the logger to print error messages, as dependency injection has failed.
|
||||||
stderr.write(`${error}\n`);
|
stderr.write(`${error}\n`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import streamifyArray from 'streamify-array';
|
import streamifyArray from 'streamify-array';
|
||||||
import type { AclManager } from '../authorization/AclManager';
|
import type { AclManager } from '../authorization/AclManager';
|
||||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||||
|
import { LazyLoggerFactory } from '../logging/LazyLoggerFactory';
|
||||||
|
import type { LoggerFactory } from '../logging/LoggerFactory';
|
||||||
|
import { getLoggerFor } from '../logging/LogUtil';
|
||||||
import type { ExpressHttpServer } from '../server/ExpressHttpServer';
|
import type { ExpressHttpServer } from '../server/ExpressHttpServer';
|
||||||
import type { ResourceStore } from '../storage/ResourceStore';
|
import type { ResourceStore } from '../storage/ResourceStore';
|
||||||
import { TEXT_TURTLE } from '../util/ContentTypes';
|
import { TEXT_TURTLE } from '../util/ContentTypes';
|
||||||
@ -10,9 +13,11 @@ import { CONTENT_TYPE } from '../util/UriConstants';
|
|||||||
* Invokes all logic to setup a server.
|
* Invokes all logic to setup a server.
|
||||||
*/
|
*/
|
||||||
export class Setup {
|
export class Setup {
|
||||||
|
protected readonly logger = getLoggerFor(this);
|
||||||
private readonly httpServer: ExpressHttpServer;
|
private readonly httpServer: ExpressHttpServer;
|
||||||
private readonly store: ResourceStore;
|
private readonly store: ResourceStore;
|
||||||
private readonly aclManager: AclManager;
|
private readonly aclManager: AclManager;
|
||||||
|
private readonly loggerFactory: LoggerFactory;
|
||||||
private readonly base: string;
|
private readonly base: string;
|
||||||
private readonly port: number;
|
private readonly port: number;
|
||||||
|
|
||||||
@ -20,12 +25,14 @@ export class Setup {
|
|||||||
httpServer: ExpressHttpServer,
|
httpServer: ExpressHttpServer,
|
||||||
store: ResourceStore,
|
store: ResourceStore,
|
||||||
aclManager: AclManager,
|
aclManager: AclManager,
|
||||||
|
loggerFactory: LoggerFactory,
|
||||||
base: string,
|
base: string,
|
||||||
port: number,
|
port: number,
|
||||||
) {
|
) {
|
||||||
this.httpServer = httpServer;
|
this.httpServer = httpServer;
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.aclManager = aclManager;
|
this.aclManager = aclManager;
|
||||||
|
this.loggerFactory = loggerFactory;
|
||||||
this.base = base;
|
this.base = base;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@ -34,6 +41,9 @@ export class Setup {
|
|||||||
* Set up a server.
|
* Set up a server.
|
||||||
*/
|
*/
|
||||||
public async setup(): Promise<string> {
|
public async setup(): Promise<string> {
|
||||||
|
// Configure the logger factory so that others can statically call it.
|
||||||
|
LazyLoggerFactory.getInstance().setLoggerFactory(this.loggerFactory);
|
||||||
|
|
||||||
// Set up acl so everything can still be done by default
|
// Set up acl so everything can still be done by default
|
||||||
// Note that this will need to be adapted to go through all the correct channels later on
|
// Note that this will need to be adapted to go through all the correct channels later on
|
||||||
const aclSetup = async(): Promise<void> => {
|
const aclSetup = async(): Promise<void> => {
|
||||||
@ -61,6 +71,7 @@ export class Setup {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
this.logger.log('debug', 'Setup default ACL settings');
|
||||||
await aclSetup();
|
await aclSetup();
|
||||||
|
|
||||||
this.httpServer.listen(this.port);
|
this.httpServer.listen(this.port);
|
||||||
|
30
src/logging/LogUtil.ts
Normal file
30
src/logging/LogUtil.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { LazyLoggerFactory } from './LazyLoggerFactory';
|
||||||
|
import type { Logger } from './Logger';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a logger instance for the given class instance.
|
||||||
|
*
|
||||||
|
* The returned type of logger depends on the configured {@link LoggerFactory} in {@link Setup}.
|
||||||
|
*
|
||||||
|
* The following shows a typical pattern on how to create loggers:
|
||||||
|
* ```
|
||||||
|
* class MyClass {
|
||||||
|
* protected readonly logger = getLoggerFor(this);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* If no class is applicable, a logger can also be created as follows:
|
||||||
|
* ```
|
||||||
|
* const logger = getLoggerFor('MyFunction');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param loggable - A class instance or a class string name.
|
||||||
|
*/
|
||||||
|
export const getLoggerFor = (loggable: string | Instance): Logger => LazyLoggerFactory.getInstance()
|
||||||
|
.createLogger(typeof loggable === 'string' ? loggable : loggable.constructor.name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper interface to identify class instances.
|
||||||
|
*/
|
||||||
|
interface Instance {
|
||||||
|
constructor: { name: string };
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { Setup } from '../../../src/init/Setup';
|
import { Setup } from '../../../src/init/Setup';
|
||||||
import type { ResourceIdentifier } from '../../../src/ldp/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../../src/ldp/representation/ResourceIdentifier';
|
||||||
|
import { VoidLoggerFactory } from '../../../src/logging/VoidLoggerFactory';
|
||||||
|
|
||||||
describe('Setup', (): void => {
|
describe('Setup', (): void => {
|
||||||
let httpServer: any;
|
let httpServer: any;
|
||||||
@ -16,7 +17,7 @@ describe('Setup', (): void => {
|
|||||||
httpServer = {
|
httpServer = {
|
||||||
listen: jest.fn(),
|
listen: jest.fn(),
|
||||||
};
|
};
|
||||||
setup = new Setup(httpServer, store, aclManager, 'http://localhost:3000/', 3000);
|
setup = new Setup(httpServer, store, aclManager, new VoidLoggerFactory(), 'http://localhost:3000/', 3000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('starts an HTTP server.', async(): Promise<void> => {
|
it('starts an HTTP server.', async(): Promise<void> => {
|
||||||
|
20
test/unit/logging/LogUtil.test.ts
Normal file
20
test/unit/logging/LogUtil.test.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { LazyLogger } from '../../../src/logging/LazyLogger';
|
||||||
|
import { LazyLoggerFactory } from '../../../src/logging/LazyLoggerFactory';
|
||||||
|
import { getLoggerFor } from '../../../src/logging/LogUtil';
|
||||||
|
import { VoidLogger } from '../../../src/logging/VoidLogger';
|
||||||
|
|
||||||
|
describe('LogUtil', (): void => {
|
||||||
|
beforeEach(async(): Promise<void> => {
|
||||||
|
LazyLoggerFactory.getInstance().setLoggerFactory(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows creating a lazy logger for a string label.', async(): Promise<void> => {
|
||||||
|
expect(getLoggerFor('MyLabel')).toBeInstanceOf(LazyLogger);
|
||||||
|
expect((getLoggerFor('MyLabel') as any).label).toEqual('MyLabel');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows creating a lazy logger for a class instance.', async(): Promise<void> => {
|
||||||
|
expect(getLoggerFor(new VoidLogger())).toBeInstanceOf(LazyLogger);
|
||||||
|
expect((getLoggerFor(new VoidLogger()) as any).label).toEqual('VoidLogger');
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user