Skip to content

Commit

Permalink
feat: seclude NodeLogWriter class
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Apr 9, 2019
1 parent f82045c commit 2399f45
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 99 deletions.
55 changes: 1 addition & 54 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,5 @@
"use strict";

const formatParts = require("sprintf-kit/format-parts")
, hasAnsi = require("has-ansi")
, { blackBright, red, yellow } = require("cli-color/bare")
, LogWriter = require("log/lib/writer")
, colorsSupportLevel = require("./lib/private/colors-support-level")
, levelPrefixes = require("./lib/level-prefixes")
, getNamespacePrefix = require("./lib/get-namespace-prefix")
, resolveParts = require("./lib/resolve-format-parts");

const WARNING_LEVEL_INDEX = 1, ERROR_LEVEL_INDEX = 0;

class NodeLogWriter extends LogWriter {
constructor(options = {}) { super(process.env, options); }
setupLevelLogger(logger) {
super.setupLevelLogger(logger);
if (colorsSupportLevel) this.setupLevelMessageDecorator(logger);
}
setupLevelMessageDecorator(levelLogger) {
if (levelLogger.levelIndex === ERROR_LEVEL_INDEX) {
levelLogger.messageContentDecorator = red;
} else if (levelLogger.levelIndex === WARNING_LEVEL_INDEX) {
levelLogger.messageContentDecorator = yellow;
}
}
resolveMessageTimestamp(event) {
super.resolveMessageTimestamp(event);
if (!colorsSupportLevel) return;
if (event.messageTimestamp) event.messageTimestamp = blackBright(event.messageTimestamp);
}
resolveMessageContent(event) {
const { logger } = event;
const parts = resolveParts(...event.messageTokens);
if (logger.messageContentDecorator) {
parts.literals = parts.literals.map(literal => logger.messageContentDecorator(literal));
for (const substitution of parts.substitutions) {
const { placeholder, value } = substitution;
if (
placeholder.type === "s" &&
placeholder.flags &&
placeholder.flags.includes("#") &&
!hasAnsi(value)
) {
// Raw string
substitution.value = logger.messageContentDecorator(value);
}
}
}
event.messageContent = formatParts(parts);
}
writeMessage(event) { process.stderr.write(`${ event.message }\n`); }
}
NodeLogWriter.levelPrefixes = levelPrefixes;

if (colorsSupportLevel) NodeLogWriter.resolveNamespaceMessagePrefix = getNamespacePrefix;
const NodeLogWriter = require("./lib/writer");

module.exports = (options = {}) => new NodeLogWriter(options);
58 changes: 58 additions & 0 deletions lib/writer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use strict";

const formatParts = require("sprintf-kit/format-parts")
, hasAnsi = require("has-ansi")
, { blackBright, red, yellow } = require("cli-color/bare")
, LogWriter = require("log/lib/writer")
, colorsSupportLevel = require("./private/colors-support-level")
, levelPrefixes = require("./level-prefixes")
, getNamespacePrefix = require("./get-namespace-prefix")
, resolveParts = require("./resolve-format-parts");

const WARNING_LEVEL_INDEX = 1, ERROR_LEVEL_INDEX = 0;

class NodeLogWriter extends LogWriter {
constructor(options = {}) { super(process.env, options); }
setupLevelLogger(logger) {
super.setupLevelLogger(logger);
if (colorsSupportLevel) this.setupLevelMessageDecorator(logger);
}
setupLevelMessageDecorator(levelLogger) {
if (levelLogger.levelIndex === ERROR_LEVEL_INDEX) {
levelLogger.messageContentDecorator = red;
} else if (levelLogger.levelIndex === WARNING_LEVEL_INDEX) {
levelLogger.messageContentDecorator = yellow;
}
}
resolveMessageTimestamp(event) {
super.resolveMessageTimestamp(event);
if (!colorsSupportLevel) return;
if (event.messageTimestamp) event.messageTimestamp = blackBright(event.messageTimestamp);
}
resolveMessageContent(event) {
const { logger } = event;
const parts = resolveParts(...event.messageTokens);
if (logger.messageContentDecorator) {
parts.literals = parts.literals.map(literal => logger.messageContentDecorator(literal));
for (const substitution of parts.substitutions) {
const { placeholder, value } = substitution;
if (
placeholder.type === "s" &&
placeholder.flags &&
placeholder.flags.includes("#") &&
!hasAnsi(value)
) {
// Raw string
substitution.value = logger.messageContentDecorator(value);
}
}
}
event.messageContent = formatParts(parts);
}
writeMessage(event) { process.stderr.write(`${ event.message }\n`); }
}
NodeLogWriter.levelPrefixes = levelPrefixes;

if (colorsSupportLevel) NodeLogWriter.resolveNamespaceMessagePrefix = getNamespacePrefix;

module.exports = NodeLogWriter;
50 changes: 5 additions & 45 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ const resolveUncached = callback => {
require.resolve("log/lib/emitter"), require.resolve("log/lib/register-master"),
require.resolve("log/lib/setup-visibility"), require.resolve("supports-color"),
require.resolve("../lib/private/colors-support-level"),
require.resolve("../lib/resolve-format-parts"), require.resolve("../")
require.resolve("../lib/resolve-format-parts"), require.resolve("../lib/writer"),
require.resolve("..")
],
() => {
callback();
return { log: require("log"), initializeWriter: require("../") };
return { log: require("log"), initializeWriter: require("..") };
}
);
} finally {
Expand All @@ -33,7 +34,6 @@ test("log-nodejs", t => {
);
initializeWriter(null); // null passed to test no options recoverys
const originalWrite = process.stderr.write;
let isInvoked = false;
process.stderr.write = string => {
t.equal(
string,
Expand All @@ -42,50 +42,10 @@ test("log-nodejs", t => {
} foo bar\n`,
"Should write logs for enabled loggers to stderr"
);
isInvoked = true;
process.stderr.write = originalWrite;
t.end();
};
log("not enabled");
t.equal(isInvoked, false, "Should not write logs of disabled loggers");
log.error.get("elo")("foo bar");
t.equal(isInvoked, true, "Should write logs immediately");
process.stderr.write = originalWrite;
t.end();
});
t.test(t => {
t.plan(4);
const { log, initializeWriter } = resolveUncached(
() => (require("supports-color").stderr = { level: 1 })
);
initializeWriter({ defaultNamespace: "marko" });
const originalWrite = process.stderr.write;
process.stderr.write = string =>
t.equal(
string, "× \x1b[31msome \x1b[39m\x1b[32mfoo\x1b[39m\x1b[31m error\x1b[39m\n",
"Should decorate error logs when colors are enabled"
);
log.error("some %s error", "foo");
process.stderr.write = string =>
t.equal(
string, "‼ \x1b[33msome \x1b[39m\x1b[33m12\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should decorate warning logs when colors are enabled"
);
log.warning("some %d warning", 12);
process.stderr.write = string =>
t.equal(
string,
"‼ \x1b[33msome \x1b[39m\x1b[33mmarko\nfoo\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should decorate raw strings in warning logs when colors are enabled"
);
log.warning("some %#s warning", "marko\nfoo");
process.stderr.write = string =>
t.equal(
string,
"‼ \x1b[33msome \x1b[39mmarko\n\x1b[33mfoo\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should not decorate raw strings that contain ANSI codes in warning logs " +
"when colors are enabled"
);
log.warning("some %#s warning", "marko\n\x1b[33mfoo\x1b[39m");
process.stderr.write = originalWrite;
});
t.end();
});
96 changes: 96 additions & 0 deletions test/lib/writer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"use strict";

const test = require("tape")
, requireUncached = require("ncjsm/require-uncached")
, overrideEnv = require("process-utils/override-env");

const resolveUncached = callback => {
const { restoreEnv } = overrideEnv();
try {
return requireUncached(
[
require.resolve("log"), require.resolve("log/lib/writer"),
require.resolve("log/lib/private/logger-prototype"),
require.resolve("log/lib/emitter"), require.resolve("log/lib/register-master"),
require.resolve("log/lib/setup-visibility"), require.resolve("supports-color"),
require.resolve("../../lib/private/colors-support-level"),
require.resolve("../../lib/resolve-format-parts"),
require.resolve("../../lib/writer")
],
() => {
callback();
const LogNodeWriter = require("../../lib/writer");
return {
log: require("log"),
initializeWriter: options => new LogNodeWriter(options)
};
}
);
} finally {
restoreEnv();
}
};

test("log-nodejs", t => {
t.test(t => {
const { log, initializeWriter } = resolveUncached(
() => (require("supports-color").stderr = false)
);
initializeWriter(null); // null passed to test no options recoverys
const originalWrite = process.stderr.write;
let isInvoked = false;
process.stderr.write = string => {
t.equal(
string,
`${ log.error.get("elo").levelMessagePrefix } ${
log.error.get("elo").namespaceMessagePrefix
} foo bar\n`,
"Should write logs for enabled loggers to stderr"
);
isInvoked = true;
};
log("not enabled");
t.equal(isInvoked, false, "Should not write logs of disabled loggers");
log.error.get("elo")("foo bar");
t.equal(isInvoked, true, "Should write logs immediately");
process.stderr.write = originalWrite;
t.end();
});
t.test(t => {
t.plan(4);
const { log, initializeWriter } = resolveUncached(
() => (require("supports-color").stderr = { level: 1 })
);
initializeWriter({ defaultNamespace: "marko" });
const originalWrite = process.stderr.write;
process.stderr.write = string =>
t.equal(
string, "× \x1b[31msome \x1b[39m\x1b[32mfoo\x1b[39m\x1b[31m error\x1b[39m\n",
"Should decorate error logs when colors are enabled"
);
log.error("some %s error", "foo");
process.stderr.write = string =>
t.equal(
string, "‼ \x1b[33msome \x1b[39m\x1b[33m12\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should decorate warning logs when colors are enabled"
);
log.warning("some %d warning", 12);
process.stderr.write = string =>
t.equal(
string,
"‼ \x1b[33msome \x1b[39m\x1b[33mmarko\nfoo\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should decorate raw strings in warning logs when colors are enabled"
);
log.warning("some %#s warning", "marko\nfoo");
process.stderr.write = string =>
t.equal(
string,
"‼ \x1b[33msome \x1b[39mmarko\n\x1b[33mfoo\x1b[39m\x1b[33m warning\x1b[39m\n",
"Should not decorate raw strings that contain ANSI codes in warning logs " +
"when colors are enabled"
);
log.warning("some %#s warning", "marko\n\x1b[33mfoo\x1b[39m");
process.stderr.write = originalWrite;
});
t.end();
});

0 comments on commit 2399f45

Please sign in to comment.