From b1e8fa61527cb8ab7366f1ecaa894d73b3ad4d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Tue, 29 Jan 2019 20:47:07 +0100 Subject: [PATCH] refactor(logger): remove root prop from LogNode class ...and use concrete types instead of abstract. --- garden-service/src/logger/log-entry.ts | 17 ++++++++-- garden-service/src/logger/log-node.ts | 44 ++++++++------------------ garden-service/src/logger/logger.ts | 26 ++++----------- garden-service/src/logger/util.ts | 6 ++-- 4 files changed, 38 insertions(+), 55 deletions(-) diff --git a/garden-service/src/logger/log-entry.ts b/garden-service/src/logger/log-entry.ts index 834c386ae5..282cb170e0 100644 --- a/garden-service/src/logger/log-entry.ts +++ b/garden-service/src/logger/log-entry.ts @@ -42,7 +42,8 @@ export type CreateParam = string | CreateOpts export interface LogEntryConstructor { level: LogLevel opts: CreateOpts - parent: LogNode + root: Logger + parent?: LogEntry } // TODO Fix any cast @@ -54,9 +55,10 @@ export class LogEntry extends LogNode { public opts: UpdateOpts public root: Logger - constructor({ level, opts, parent }: LogEntryConstructor) { + constructor({ level, opts, root, parent }: LogEntryConstructor) { const { id, ...otherOpts } = opts super(level, parent, id) + this.root = root this.opts = otherOpts if (this.level === LogLevel.error) { this.opts.status = "error" @@ -108,7 +110,16 @@ export class LogEntry extends LogNode { indent: (this.opts.indent || 0) + 1, ...resolveParam(param), } - return new LogEntry({ level: childLevel, opts, parent: this }) + return new LogEntry({ + opts, + level: childLevel, + root: this.root, + parent: this, + }) + } + + protected onGraphChange(node: LogEntry) { + this.root.onGraphChange(node) } placeholder(level: LogLevel = LogLevel.info): LogEntry { diff --git a/garden-service/src/logger/log-node.ts b/garden-service/src/logger/log-node.ts index e7e5c577e6..c1b561e503 100644 --- a/garden-service/src/logger/log-node.ts +++ b/garden-service/src/logger/log-node.ts @@ -9,7 +9,6 @@ import * as uniqid from "uniqid" import { round } from "lodash" -import { findLogNode } from "./util" import { LogEntry, CreateParam } from "./log-entry" export enum LogLevel { @@ -21,64 +20,58 @@ export enum LogLevel { silly = 5, } -export abstract class LogNode { +export abstract class LogNode { public readonly timestamp: number public readonly key: string - public readonly children: T[] - public readonly root: RootLogNode + public readonly children: LogEntry[] constructor( public readonly level: LogLevel, - public readonly parent?: LogNode, + public readonly parent?: LogEntry, public readonly id?: string, ) { - if (this instanceof RootLogNode) { - this.root = this - } else { - // Non-root nodes have a parent - this.root = parent!.root - } this.key = uniqid() this.timestamp = Date.now() this.children = [] } - protected abstract createNode(level: LogLevel, param: U): T + protected abstract createNode(level: LogLevel, param: CreateParam): LogEntry + protected abstract onGraphChange(node: LogEntry): void /** * A placeholder entry is an empty entry whose children should be aligned with the parent context. * Useful for setting a placeholder in the middle of the log that can later be populated. */ - abstract placeholder(level: LogLevel): T + abstract placeholder(level: LogLevel): LogEntry - protected appendNode(level: LogLevel, param: U): T { + protected appendNode(level: LogLevel, param: CreateParam): LogEntry { const node = this.createNode(level, param) this.children.push(node) - this.root.onGraphChange(node) + this.onGraphChange(node) return node } - silly(param: U): T { + silly(param: CreateParam): LogEntry { return this.appendNode(LogLevel.silly, param) } - debug(param: U): T { + debug(param: CreateParam): LogEntry { return this.appendNode(LogLevel.debug, param) } - verbose(param: U): T { + verbose(param: CreateParam): LogEntry { return this.appendNode(LogLevel.verbose, param) } - info(param: U): T { + info(param: CreateParam): LogEntry { return this.appendNode(LogLevel.info, param) } - warn(param: U): T { + warn(param: CreateParam): LogEntry { return this.appendNode(LogLevel.warn, param) } - error(param: U): T { + error(param: CreateParam): LogEntry { return this.appendNode(LogLevel.error, param) } @@ -90,12 +83,3 @@ export abstract class LogNode { } } - -export abstract class RootLogNode extends LogNode { - abstract onGraphChange(node: T): void - - findById(id: string): T | void { - return findLogNode(this, node => node.id === id) - } - -} diff --git a/garden-service/src/logger/logger.ts b/garden-service/src/logger/logger.ts index a338ef64fe..f9de6b5fb3 100644 --- a/garden-service/src/logger/logger.ts +++ b/garden-service/src/logger/logger.ts @@ -6,17 +6,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import chalk from "chalk" - -import { RootLogNode } from "./log-node" +import { LogNode } from "./log-node" import { LogEntry, CreateOpts, resolveParam } from "./log-entry" -import { getChildEntries } from "./util" +import { getChildEntries, findLogNode } from "./util" import { Writer } from "./writers/base" import { InternalError, ParameterError } from "../exceptions" import { LogLevel } from "./log-node" import { FancyTerminalWriter } from "./writers/fancy-terminal-writer" import { BasicTerminalWriter } from "./writers/basic-terminal-writer" -import { combine, printEmoji } from "./renderers" export enum LoggerType { quiet = "quiet", @@ -47,7 +44,7 @@ export interface LoggerConfig { useEmoji?: boolean } -export class Logger extends RootLogNode { +export class Logger extends LogNode { public writers: Writer[] public useEmoji: boolean @@ -65,7 +62,7 @@ export class Logger extends RootLogNode { throw new InternalError("Logger already initialized", {}) } - let instance + let instance: Logger // If GARDEN_LOGGER_TYPE env variable is set it takes precedence over the config param if (process.env.GARDEN_LOGGER_TYPE) { @@ -95,7 +92,7 @@ export class Logger extends RootLogNode { } protected createNode(level: LogLevel, opts: CreateOpts): LogEntry { - return new LogEntry({ level, parent: this, opts: resolveParam(opts) }) + return new LogEntry({ level, root: this, opts: resolveParam(opts) }) } placeholder(level: LogLevel = LogLevel.info): LogEntry { @@ -115,17 +112,8 @@ export class Logger extends RootLogNode { return getChildEntries(this).filter(entry => entry.opts.section === section) } - // FIXME: This isn't currently used anywhere, we should find this another place and purpose. - finish( - { showDuration = true, level = LogLevel.info }: { showDuration?: boolean, level?: LogLevel } = {}, - ): LogEntry { - const msg = combine([ - [this.useEmoji ? `\n${printEmoji("sparkles")} Finished` : "Finished"], - [showDuration ? ` in ${chalk.bold(this.getDuration() + "s")}` : "!"], - ["\n"], - ]) - const lvlStr = LogLevel[level] - return this[lvlStr](msg) + findById(id: string): LogEntry | void { + return findLogNode(this, node => node.id === id) } stop(): void { diff --git a/garden-service/src/logger/util.ts b/garden-service/src/logger/util.ts index 955a3482d7..a13b6d65ac 100644 --- a/garden-service/src/logger/util.ts +++ b/garden-service/src/logger/util.ts @@ -44,9 +44,9 @@ export function getChildEntries(node: LogNode): LogEntry[] { return getChildNodes(node) } -export function findLogNode(node: LogNode, predicate: ProcessNode>): T | void { - let found - traverseChildren, LogNode>(node, entry => { +export function findLogNode(node: LogNode, predicate: ProcessNode): LogEntry | void { + let found: LogEntry | undefined + traverseChildren(node, entry => { if (predicate(entry)) { found = entry return false