1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-27 17:49:08 -05:00
Original: 25b88bcf8c
This commit is contained in:
Bartek Iwańczuk 2018-12-19 19:16:45 +01:00 committed by Ryan Dahl
parent 700b4ce0d9
commit 6624584dd4
9 changed files with 293 additions and 5 deletions

View file

@ -7,11 +7,11 @@ for Deno.
| Collection | Description |
| ---------------------------- | --------------------------------------------------------------- |
| [colors](./colors/README.md) | Modules that generate ANSI color codes for the console. |
| [net](./net/README.md) | A framework for creating HTTP/HTTPS servers inspired by GoLang. |
| [path](./path/README.md) | A path manipulation library. |
| [flags](./flags/README.md) | Command line arguments parser based on minimist. |
| [colors](./colors/) | Modules that generate ANSI color codes for the console. |
| [net](./net/) | A framework for creating HTTP/HTTPS servers inspired by GoLang. |
| [path](./path/) | File path manipulation. |
| [flags](./flags/) | Command line arguments parser. |
| [logging](./logging/) | Command line logging |
---
Copyright 2018 the Deno authors. All rights reserved. MIT license.

12
logging/README.md Normal file
View file

@ -0,0 +1,12 @@
# Logging module for Deno
Very much work in progress. Contributions welcome.
This library is heavily inspired by Python's [logging](https://docs.python.org/3/library/logging.html#logging.Logger.log) module, altough
it's not planned to be a direct port. Having separate loggers, handlers, formatters and filters gives developer very granular control over logging
which is most desirable for server side software.
Todo:
- [ ] implement formatters
- [ ] implement `FileHandler`
- [ ] tests

18
logging/handler.ts Normal file
View file

@ -0,0 +1,18 @@
import { getLevelByName } from "./levels";
export class BaseHandler {
level: number;
levelName: string;
constructor(levelName) {
this.level = getLevelByName(levelName);
this.levelName = levelName;
}
handle(level, ...args) {
if (this.level > level) return;
return this._log(level, ...args);
}
_log(level, ...args) {}
}

View file

@ -0,0 +1,26 @@
import { BaseHandler } from '../handler.ts';
import { LogLevel } from '../levels.ts';
export class ConsoleHandler extends BaseHandler {
_log(level, ...args) {
switch (level) {
case LogLevel.DEBUG:
console.log(...args);
return;
case LogLevel.INFO:
console.info(...args);
return;
case LogLevel.WARNING:
console.warn(...args);
return;
case LogLevel.ERROR:
console.error(...args);
return;
case LogLevel.CRITICAL:
console.error(...args);
return;
default:
return;
}
}
}

101
logging/index.ts Normal file
View file

@ -0,0 +1,101 @@
import { Logger } from "./logger.ts";
import { BaseHandler } from "./handler.ts";
import { ConsoleHandler } from "./handlers/console.ts";
export interface HandlerConfig {
// TODO: replace with type describing class derived from BaseHandler
class: typeof BaseHandler;
level?: string;
}
export class LoggerConfig {
level?: string;
handlers?: string[];
}
export interface LoggingConfig {
handlers?: {
[name: string]: HandlerConfig;
};
loggers?: {
[name: string]: LoggerConfig;
};
}
const DEFAULT_LEVEL = "INFO";
const DEFAULT_NAME = "";
const DEFAULT_CONFIG: LoggingConfig = {
handlers: {
[DEFAULT_NAME]: {
level: DEFAULT_LEVEL,
class: ConsoleHandler
}
},
loggers: {
[DEFAULT_NAME]: {
level: DEFAULT_LEVEL,
handlers: [DEFAULT_NAME]
}
}
};
const state = {
loggers: new Map(),
config: DEFAULT_CONFIG
};
function createNewHandler(name: string) {
let handlerConfig = state.config.handlers[name];
if (!handlerConfig) {
handlerConfig = state.config.handlers[DEFAULT_NAME];
}
const constructor = handlerConfig.class;
console.log(constructor);
const handler = new constructor(handlerConfig.level);
return handler;
}
function createNewLogger(name: string) {
let loggerConfig = state.config.loggers[name];
if (!loggerConfig) {
loggerConfig = state.config.loggers[DEFAULT_NAME];
}
const handlers = (loggerConfig.handlers || []).map(createNewHandler);
const levelName = loggerConfig.level || DEFAULT_LEVEL;
return new Logger(levelName, handlers);
}
export const handlers = {
BaseHandler: BaseHandler,
ConsoleHandler: ConsoleHandler
};
export function getLogger(name?: string) {
if (!name) {
name = DEFAULT_NAME;
}
if (!state.loggers.has(name)) {
return createNewLogger(name);
}
return state.loggers.get(name);
}
export function setup(config: LoggingConfig) {
state.config = {
handlers: {
...DEFAULT_CONFIG.handlers,
...config.handlers!
},
loggers: {
...DEFAULT_CONFIG.loggers,
...config.loggers!
}
};
}

31
logging/levels.ts Normal file
View file

@ -0,0 +1,31 @@
export const LogLevel = {
DEBUG: 10,
INFO: 20,
WARNING: 30,
ERROR: 40,
CRITICAL: 50
};
const byName = {
DEBUG: LogLevel.DEBUG,
INFO: LogLevel.INFO,
WARNING: LogLevel.WARNING,
ERROR: LogLevel.ERROR,
CRITICAL: LogLevel.DEBUG
};
const byLevel = {
[LogLevel.DEBUG]: "DEBUG",
[LogLevel.INFO]: "INFO",
[LogLevel.WARNING]: "WARNING",
[LogLevel.ERROR]: "ERROR",
[LogLevel.CRITICAL]: "CRITICAL"
};
export function getLevelByName(name) {
return byName[name];
}
export function getLevelName(level) {
return byLevel[level];
}

44
logging/logger.ts Normal file
View file

@ -0,0 +1,44 @@
import { LogLevel, getLevelByName, getLevelName } from "./levels.ts";
export class Logger {
level: number;
levelName: string;
handlers: any[];
constructor(levelName, handlers) {
this.level = getLevelByName(levelName);
this.levelName = levelName;
this.handlers = handlers;
}
_log(level, ...args) {
this.handlers.forEach(handler => {
handler.handle(level, ...args);
});
}
log(level, ...args) {
if (this.level > level) return;
return this._log(level, ...args);
}
debug(...args) {
return this.log(LogLevel.DEBUG, ...args);
}
info(...args) {
return this.log(LogLevel.INFO, ...args);
}
warning(...args) {
return this.log(LogLevel.WARNING, ...args);
}
error(...args) {
return this.log(LogLevel.ERROR, ...args);
}
critical(...args) {
return this.log(LogLevel.CRITICAL, ...args);
}
}

53
logging/test.ts Normal file
View file

@ -0,0 +1,53 @@
import { assertEqual, test } from "https://deno.land/x/testing/testing.ts";
import * as logging from "index.ts";
// TODO: establish something more sophisticated
let testOutput = "";
class TestHandler extends logging.handlers.BaseHandler {
_log(level, ...args) {
testOutput += `${level} ${args[0]}\n`;
}
}
logging.setup({
handlers: {
debug: {
level: "DEBUG",
class: TestHandler
},
info: {
level: "INFO",
class: TestHandler
}
},
loggers: {
default: {
level: "DEBUG",
handlers: ["debug"]
},
info: {
level: "INFO",
handlers: ["info"]
}
}
});
const logger = logging.getLogger("default");
const unknownLogger = logging.getLogger("info");
test(function basicTest() {
logger.debug("I should be printed.");
unknownLogger.debug("I should not be printed.");
unknownLogger.info("And I should be printed as well.");
const expectedOutput =
"10 I should be printed.\n20 And I should be printed as well.\n";
assertEqual(testOutput, expectedOutput);
});

View file

@ -13,6 +13,9 @@ import "net/http_test.ts";
import "net/textproto_test.ts";
import { runTests, completePromise } from "net/file_server_test.ts";
// logging tests
import "logging/test.ts";
// file server test
const fileServer = run({
args: ["deno", "--allow-net", "net/file_server.ts", "."]