]> git.wincent.com - wincent.git/commitdiff
feat: add log levels
authorGreg Hurrell <greg@hurrell.net>
Tue, 31 Mar 2020 00:05:40 +0000 (02:05 +0200)
committerGreg Hurrell <greg@hurrell.net>
Tue, 31 Mar 2020 00:05:40 +0000 (02:05 +0200)
bin/common
src/Fig/task.ts
src/console/index.ts
src/main.ts

index 2c0a3b2dbd8f85f5afafed85a2a0ffc833642d9b..ae062c43c72a954c0524f1d4aed678c9c33d67e6 100755 (executable)
@@ -28,24 +28,56 @@ RED='\033[1;31m'
 RESET='\033[0m'
 YELLOW='\033[1;33m'
 
+# No associative arrays in Bash < v4, so can't do:
+#
+#   declare -A LOG_LEVEL
+#
+LOG_LEVEL_EMERGENCY=0
+LOG_LEVEL_ALERT=1
+LOG_LEVEL_CRITICAL=2
+LOG_LEVEL_ERROR=3
+LOG_LEVEL_WARNING=4
+LOG_LEVEL_NOTICE=5
+LOG_LEVEL_INFO=6
+LOG_LEVEL_DEBUG=7
+
+LOG_LEVEL=$LOG_LEVEL_INFO
+
+for VAR in "$@"
+do
+  if [[ $VAR = "--debug" ]]; then
+    LOG_LEVEL=$LOG_LEVEL_DEBUG
+  elif [[ $VAR = "--quiet" || $VAR = "-q" ]]; then
+    LOG_LEVEL=$LOG_LEVEL_ERROR
+  fi
+done
+
 log_debug() {
-  if [[ -n $DEBUG ]]; then
+  if [[ $LOG_LEVEL -ge $LOG_LEVEL_DEBUG ]]; then
     echo -e "${PURPLE}[debug]  ${RESET} $*" > /dev/stderr
   fi
 }
 
 log_error() {
-  echo -e "${RED}[error]  ${RESET} $*" > /dev/stderr
+  if [[ $LOG_LEVEL -ge $LOG_LEVEL_ERROR ]]; then
+    echo -e "${RED}[error]  ${RESET} $*" > /dev/stderr
+  fi
 }
 
 log_info() {
-  echo -e "${BOLD}[info]   ${RESET} $*" > /dev/stderr
+  if [[ $LOG_LEVEL -ge $LOG_LEVEL_INFO ]]; then
+    echo -e "${BOLD}[info]   ${RESET} $*" > /dev/stderr
+  fi
 }
 
 log_notice() {
-  echo -e "${GREEN}[notice] ${RESET} $*" > /dev/stderr
+  if [[ $LOG_LEVEL -ge $LOG_LEVEL_NOTICE ]]; then
+    echo -e "${GREEN}[notice] ${RESET} $*" > /dev/stderr
+  fi
 }
 
 log_warn() {
-  echo -e "${YELLOW}[warning]${RESET} $*" > /dev/stderr
+  if [[ $LOG_LEVEL -ge $LOG_LEVEL_WARNING ]]; then
+    echo -e "${YELLOW}[warning]${RESET} $*" > /dev/stderr
+  fi
 }
index f3370342b926218b4faffe076127915c7be87e82..2635f49ebbf9ad7ed983e32877c65d0188cedb77 100644 (file)
@@ -19,6 +19,8 @@ export default function task(name: string, callback: () => Promise<void>) {
 
   assertAspect(aspect);
   // TODO: use `caller` to make namespaced task name.
+  // (will be useful for --start-at)
+  // also, we can make an interactive mode that lets us choose where to start
 
   Context.tasks.register(aspect, callback, name);
 }
index 3a6fe76f5929520e6208bb09be463eb03316ce88..374289a40608e419618aa3738d412f57068f9f72 100644 (file)
@@ -1,26 +1,17 @@
-/**
- * Syslog levels:
- *
- * - 0, emergency (not implemented): "system is unusable"
- * - 1, alert (not implemented): "action must be taken immediately"
- * - 2, critical (not implemented): "hard device errors"
- * - 3, error: "error conditions"
- * - 4, warning: "warning conditions"
- * - 5, notice: "normal but significant conditions"
- * - 6, info: "informational messages"
- * - 7, debug: "debug-level messages"
- *
- * @see https://en.wikipedia.org/wiki/Syslog
- */
-
 import {clearLine, cursorTo} from 'readline';
 
 import COLORS from './colors';
 
 export {COLORS};
 
+type ValueOf<T> = T[keyof T];
+
+type LogLevel = ValueOf<typeof LOG_LEVEL>;
+
 const {bold, green, purple, red, yellow} = COLORS;
 
+let logLevel: LogLevel = 6;
+
 const PREFIXES = ['debug', 'error', 'info', 'notice', 'warning'];
 
 const PREFIX_LENGTH = PREFIXES.reduce((acc, prefix) => {
@@ -33,6 +24,31 @@ const PREFIX_MAP = Object.fromEntries(
   })
 );
 
+/**
+ * Syslog levels:
+ *
+ * - 0, emergency (not implemented): "system is unusable"
+ * - 1, alert (not implemented): "action must be taken immediately"
+ * - 2, critical (not implemented): "hard device errors"
+ * - 3, error: "error conditions"
+ * - 4, warning: "warning conditions"
+ * - 5, notice: "normal but significant conditions"
+ * - 6, info: "informational messages"
+ * - 7, debug: "debug-level messages"
+ *
+ * @see https://en.wikipedia.org/wiki/Syslog
+ */
+export const LOG_LEVEL = {
+  EMERGENCY: 0,
+  ALERT: 1,
+  CRITICAL: 2,
+  ERROR: 3,
+  WARNING: 4,
+  NOTICE: 5,
+  INFO: 6,
+  DEBUG: 7,
+} as const;
+
 export function clear() {
   return new Promise((resolve) => {
     clearLine(process.stderr, 0, () => {
@@ -42,15 +58,21 @@ export function clear() {
 }
 
 function debug(message: string) {
-  log(purple.bold`${PREFIX_MAP.debug}` + message);
+  if (logLevel >= LOG_LEVEL.DEBUG) {
+    log(purple.bold`${PREFIX_MAP.debug}` + message);
+  }
 }
 
 function error(message: string) {
-  log(red.bold`${PREFIX_MAP.error}` + message);
+  if (logLevel >= LOG_LEVEL.ERROR) {
+    log(red.bold`${PREFIX_MAP.error}` + message);
+  }
 }
 
 function info(message: string) {
-  log(bold`${PREFIX_MAP.info}` + message);
+  if (logLevel >= LOG_LEVEL.INFO) {
+    log(bold`${PREFIX_MAP.info}` + message);
+  }
 }
 
 export function log(...args: Array<any>) {
@@ -59,7 +81,9 @@ export function log(...args: Array<any>) {
 }
 
 function notice(message: string) {
-  log(green.bold`${PREFIX_MAP.notice}` + message);
+  if (logLevel >= LOG_LEVEL.NOTICE) {
+    log(green.bold`${PREFIX_MAP.notice}` + message);
+  }
 }
 
 export function print(...args: Array<any>) {
@@ -80,8 +104,14 @@ export function print(...args: Array<any>) {
   );
 }
 
+export function setLogLevel(level: LogLevel) {
+  logLevel = level;
+}
+
 function warn(message: string) {
-  log(yellow.bold`${PREFIX_MAP.warning}` + message);
+  if (logLevel >= LOG_LEVEL.WARNING) {
+    log(yellow.bold`${PREFIX_MAP.warning}` + message);
+  }
 }
 
 log.clear = clear;
index 768a8644a1663188925f692516fcd2f683e258c7..61dea7a17e8fcf7756c282f28c5a7ab8f18a702b 100644 (file)
@@ -4,7 +4,7 @@ import * as path from 'path';
 import ErrorWithMetadata from './ErrorWithMetadata';
 import Context from './Fig/Context';
 import {root} from './Fig';
-import {log} from './console';
+import {LOG_LEVEL, log, setLogLevel} from './console';
 import merge from './merge';
 import readAspect from './readAspect';
 import readProject from './readProject';
@@ -12,16 +12,25 @@ import regExpFromString from './regExpFromString';
 import simplify from './simplify';
 import test from './test';
 
-// argv[0] = node executable
-// argv[1] = JS script
-// argv[2] = script arg 0 etc
-log.debug(JSON.stringify(process.argv, null, 2));
 
 async function main() {
   if (Context.attributes.uid === 0) {
     throw new ErrorWithMetadata('Cannot run as root');
   }
 
+  process.argv.forEach(arg => {
+    if (arg === '--debug') {
+      setLogLevel(LOG_LEVEL.DEBUG);
+    } else if (arg === '--quiet' || arg === '-q') {
+      setLogLevel(LOG_LEVEL.ERROR);
+    }
+  });
+
+  // argv[0] = node executable
+  // argv[1] = JS script
+  // argv[2] = script arg 0 etc
+  log.debug(JSON.stringify(process.argv, null, 2));
+
   if (process.cwd() === root) {
     log.info(`Working from root: ${simplify(root)}`);
   } else {