mirror of
https://github.com/denoland/deno.git
synced 2024-12-29 02:29:06 -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 |
|
| Collection | Description |
|
||||||
| ---------------------------- | --------------------------------------------------------------- |
|
| ---------------------------- | --------------------------------------------------------------- |
|
||||||
| [colors](./colors/README.md) | Modules that generate ANSI color codes for the console. |
|
| [colors](./colors/) | Modules that generate ANSI color codes for the console. |
|
||||||
| [net](./net/README.md) | A framework for creating HTTP/HTTPS servers inspired by GoLang. |
|
| [net](./net/) | A framework for creating HTTP/HTTPS servers inspired by GoLang. |
|
||||||
| [path](./path/README.md) | A path manipulation library. |
|
| [path](./path/) | File path manipulation. |
|
||||||
| [flags](./flags/README.md) | Command line arguments parser based on minimist. |
|
| [flags](./flags/) | Command line arguments parser. |
|
||||||
|
| [logging](./logging/) | Command line logging |
|
||||||
---
|
---
|
||||||
|
|
||||||
Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
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 "net/textproto_test.ts";
|
||||||
import { runTests, completePromise } from "net/file_server_test.ts";
|
import { runTests, completePromise } from "net/file_server_test.ts";
|
||||||
|
|
||||||
|
// logging tests
|
||||||
|
import "logging/test.ts";
|
||||||
|
|
||||||
// file server test
|
// file server test
|
||||||
const fileServer = run({
|
const fileServer = run({
|
||||||
args: ["deno", "--allow-net", "net/file_server.ts", "."]
|
args: ["deno", "--allow-net", "net/file_server.ts", "."]
|
||||||
|
|
Loading…
Reference in a new issue