Skip to content

Commit

Permalink
refactor(logger): remove root prop from LogNode class
Browse files Browse the repository at this point in the history
...and use concrete types instead of abstract.
  • Loading branch information
eysi09 committed Jan 29, 2019
1 parent c5e6dce commit b1e8fa6
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 55 deletions.
17 changes: 14 additions & 3 deletions garden-service/src/logger/log-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
44 changes: 14 additions & 30 deletions garden-service/src/logger/log-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -21,64 +20,58 @@ export enum LogLevel {
silly = 5,
}

export abstract class LogNode<T = LogEntry, U = CreateParam> {
export abstract class LogNode {
public readonly timestamp: number
public readonly key: string
public readonly children: T[]
public readonly root: RootLogNode<T>
public readonly children: LogEntry[]

constructor(
public readonly level: LogLevel,
public readonly parent?: LogNode<T>,
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)
}

Expand All @@ -90,12 +83,3 @@ export abstract class LogNode<T = LogEntry, U = CreateParam> {
}

}

export abstract class RootLogNode<T = LogEntry> extends LogNode<T> {
abstract onGraphChange(node: T): void

findById(id: string): T | void {
return findLogNode(this, node => node.id === id)
}

}
26 changes: 7 additions & 19 deletions garden-service/src/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -47,7 +44,7 @@ export interface LoggerConfig {
useEmoji?: boolean
}

export class Logger extends RootLogNode<LogEntry> {
export class Logger extends LogNode {
public writers: Writer[]
public useEmoji: boolean

Expand All @@ -65,7 +62,7 @@ export class Logger extends RootLogNode<LogEntry> {
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) {
Expand Down Expand Up @@ -95,7 +92,7 @@ export class Logger extends RootLogNode<LogEntry> {
}

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 {
Expand All @@ -115,17 +112,8 @@ export class Logger extends RootLogNode<LogEntry> {
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 {
Expand Down
6 changes: 3 additions & 3 deletions garden-service/src/logger/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ export function getChildEntries(node: LogNode): LogEntry[] {
return getChildNodes<LogNode, LogEntry>(node)
}

export function findLogNode<T>(node: LogNode<T>, predicate: ProcessNode<LogNode<T>>): T | void {
let found
traverseChildren<LogNode<T>, LogNode<T>>(node, entry => {
export function findLogNode(node: LogNode, predicate: ProcessNode<LogNode>): LogEntry | void {
let found: LogEntry | undefined
traverseChildren<LogNode, LogEntry>(node, entry => {
if (predicate(entry)) {
found = entry
return false
Expand Down

0 comments on commit b1e8fa6

Please sign in to comment.