mirror of
https://github.com/denoland/deno.git
synced 2024-12-27 17:49:08 -05:00
parent
700b4ce0d9
commit
6624584dd4
9 changed files with 293 additions and 5 deletions
10
README.md
10
README.md
|
@ -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
12
logging/README.md
Normal 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
18
logging/handler.ts
Normal 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) {}
|
||||
}
|
26
logging/handlers/console.ts
Normal file
26
logging/handlers/console.ts
Normal 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
101
logging/index.ts
Normal 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
31
logging/levels.ts
Normal 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
44
logging/logger.ts
Normal 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
53
logging/test.ts
Normal 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);
|
||||
});
|
3
test.ts
3
test.ts
|
@ -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", "."]
|
||||
|
|
Loading…
Reference in a new issue