Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Using winston logging results in broken box #90

Open
1 task
rjjrbatarao opened this issue Jun 24, 2024 · 2 comments
Open
1 task

[Bug]: Using winston logging results in broken box #90

rjjrbatarao opened this issue Jun 24, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@rjjrbatarao
Copy link

rjjrbatarao commented Jun 24, 2024

What happened?

A bug happened! Broken box

What should have happened?

Box should be not broken

Code

image

/**
 * !Logger
 */
const os = require("node:os");
const chalk = require("chalk");
const winston = require("winston");
const { combine, timestamp, json, printf, label, errors } = winston.format;
/**
 * !console
 */
const {
  ConsoleManager,
  OptionPopup,
  InputPopup,
  PageBuilder,
  ButtonPopup,
  ConfirmPopup,
  CustomPopup,
  FileSelectorPopup,
  Progress,
  Control,
  InPageWidgetBuilder,
  Button,
  Box,
  EOL,
} = require("console-gui-tools");

const myFormat = printf(({ level, message, label, timestamp }) => {
  if (level === "info") {
    console.log(
      `${chalk.blue(timestamp)} ${chalk.yellow(
        "[" + label + "]"
      )} ${chalk.green(level)}: ${message}`
    );
  } else if (level === "warn") {
    console.log(
      `${chalk.blue(timestamp)} ${chalk.yellow("[" + label + "]")} ${chalk.red(
        level
      )}: ${message}`
    );
  } else {
    console.log(
      `${chalk.blue(timestamp)} ${chalk.yellow("[" + label + "]")} ${chalk.red(
        level
      )}: ${message}`
    );
  }
  return `${timestamp} [${label}] ${level}: ${message}`;
});
const logger = winston.createLogger({
  level: "info",
  format: combine(label({ label: "radiman" }), timestamp(), myFormat),
  transports: [
    //new winston.transports.Console(),
    new winston.transports.File({
      filename: "radiman.log",
    }),
    //new LogtailTransport(logtail), // onlien logging
  ],
});

const opt = {
  title: "Radiffy Radius Manager", // Title of the console
  logPageSize: 30, // Number of lines to show in logs page
  logLocation: 1, // Location of the logs page
  enableMouse: false, // Enable mouse support
  layoutOptions: {
    boxed: true, // Set to true to enable boxed layout
    showTitle: true, // Set to false to hide title
    //changeFocusKey: "ctrl+l", // Change layout with ctrl+l to switch to the logs page
    type: "double", // Set to 'double' to enable double layout
    direction: "vertical", // Set to 'horizontal' to enable horizontal layout
    boxColor: "yellow",
    boxStyle: "bold",
  },
};
const GUI = new ConsoleManager(opt);

let period = 2000;
let mode = "debug";
let valueEmitter = null;
let min = 9;
let max = 12;
let cpu_brand = "";
let cpu_speed = 0;
let cpu_cores = 0;
const periodList = [
  2000, 5000, 10000, 20000, 30000, 60000, 120000, 300000, 600000, 900000,
  1800000, 3600000, 7200000, 14400000, 28800000, 43200000, 86400000,
];

const numberOfCores = os.cpus().length;
const cores = [];
for (let i = 0; i < numberOfCores; i++) {
  cores.push(
    new Progress({
      id: `htop-cpu-${i}`,
      x: 2,
      y: 1 + i,
      interactive: false,
      draggable: false,
      label: i > 9 ? `${i} ` : `${i}  `,
      length: 40,
      min: 0,
      max: 100,
      style: {
        boxed: true,
        theme: "htop",
        showMinMax: false,
        showValue: false,
      },
    })
  );
}

const mem = new Progress({
  id: "htop-mem",
  x: 2,
  y: 1 + numberOfCores,
  label: "Mem",
  length: 40,
  min: 0,
  max: os.totalmem() / (1024 * 1024 * 1024),
  unit: "G",
  style: {
    boxed: true,
    theme: "htop",
    showMinMax: false,
  },
});

//Create function to get CPU information
function cpuAverage(core) {
  //Initialise sum of idle and time of cores and fetch CPU info
  let totalIdle = 0,
    totalTick = 0;

  //Select CPU core
  const cpu = os.cpus()[core];

  //Total up the time in the cores tick
  for (let i = 0, len = Object.keys(cpu.times).length; i < len; i++) {
    totalTick += Object.values(cpu.times)[i];
  }

  //Total up the idle time of the core
  totalIdle += cpu.times.idle;

  //Return the average Idle and Tick times
  return { idle: totalIdle, total: totalTick };
}

function getCPULoadAVG(core, avgTime = 1000, delay = 500) {
  return new Promise((resolve, reject) => {
    const n = ~~(avgTime / delay);
    if (n <= 1) {
      reject("Error: interval to small");
    }
    let i = 0;
    const samples = [];
    const avg1 = cpuAverage(core);

    const interval = setInterval(() => {
      //GUI.log("CPU Interval: " + i)

      if (i >= n) {
        clearInterval(interval);
        resolve(
          ~~((samples.reduce((a, b) => a + b, 0) / samples.length) * 100)
        );
      }

      const avg2 = cpuAverage(core);
      const totalDiff = avg2.total - avg1.total;
      const idleDiff = avg2.idle - avg1.idle;

      samples[i] = 1 - idleDiff / totalDiff;
      i++;
    }, delay);
  });
}

const getSystemInfo = async () => {
  const coresPercent = [];

  for (let i = 0; i < numberOfCores; i++) {
    const load = await getCPULoadAVG(i).catch((err) => console.error(err));
    coresPercent.push(load);
  }
  const memUsage = os.totalmem() - os.freemem();
  return {
    cpuUsage: coresPercent,
    memUsage,
  };
};

const modeList = [
  "debug",
  "info",
  "error",
  "warning",
  "notice",
  "crit",
  "alert",
  "emerg",
];

const fetchSystemInformation = async () => {
  getSystemInfo().then((info) => {
    info.cpuUsage.forEach((core, i) => {
      cores[i].setValue(core);
    });
    mem.setValue(info.memUsage / (1024 * 1024 * 1024));
  });
  drawGui();
};

const frame = async () => {
  await fetchSystemInformation();
};

/**
 * @description Updates the console screen
 *
 */
const updateConsole = async () => {
  const uptime = os.uptime();
  const hours = Math.floor(uptime / 3600);
  const minutes = Math.floor((uptime % 3600) / 60);
  const seconds = Math.floor(uptime % 60);
  const uptimeText = `${hours}:${minutes}:${seconds}s`;
  const p = new PageBuilder();
  p.addSpacer(numberOfCores + 1);

  if (!valueEmitter) {
    p.addRow(
      { text: "Sysinfo is not running! ", color: "red" },
      { text: "press 'space' to start", color: "white" }
    );
  } else {
    p.addRow(
      { text: "Sysinfo is running! ", color: "green" },
      { text: "press 'space' to stop", color: "white" }
    );
  }

  // Print mode:
  p.addRow(
    { text: "Logging Mode: ", color: "magenta" },
    { text: `${mode}`, color: "white" }
  );

  GUI.setPage(p, 0);
  GUI.refresh();
};

GUI.on("exit", () => {
  closeApp();
});

GUI.on("keypressed", (key) => {
  switch (key.name) {
    case "space":
      if (valueEmitter) {
        clearInterval(valueEmitter);
        valueEmitter = null;
        drawGui();
      } else {
        valueEmitter = setInterval(frame, period);
        drawGui();
      }
      break;
    case "m":
      new OptionPopup({
        id: "popupSelectMode",
        title: "Select logging mode",
        options: modeList,
        selected: mode,
      })
        .show()
        .on("confirm", (_mode) => {
          mode = _mode;
          //logger.transports.console.level = mode;
          GUI.warn(`NEW MODE: ${mode}`);
          drawGui();
        });
      break;
    case "s":
      new OptionPopup({
        id: "popupSelectPeriod",
        title: "Select update period",
        options: periodList,
        selected: period,
      })
        .show()
        .on("confirm", (_period) => {
          const msgMultiLine = `Changing period from ${period} to ${_period} ms.${EOL}This will restart the monitor.${EOL}Do you want to continue?`;
          new ButtonPopup({
            id: "popupConfirmPeriod",
            title: "Confirm period",
            message: msgMultiLine,
            buttons: ["Yes", "No", "?"],
          })
            .show()
            .on("confirm", (answer) => {
              if (answer === "Yes") {
                period = _period;
                GUI.warn(`NEW PERIOD: ${period}`);
              } else if (answer === "?") {
                GUI.info("Choose ok to confirm period");
              }
              drawGui();
            });
        });
      break;
    case "a":
      new InputPopup({
        id: "popupTypeMax",
        title: "Type max value",
        value: max,
        numeric: true,
      })
        .show()
        .on("confirm", (_max) => {
          max = _max;
          GUI.warn(`NEW MAX VALUE: ${max}`);
          drawGui();
        });
      break;
    case "d":
      new InputPopup({
        id: "popupTypeMin",
        title: "Type min value",
        value: min,
        numeric: true,
      })
        .show()
        .on("confirm", (_min) => {
          min = _min;
          GUI.warn(`NEW MIN VALUE: ${min}`);
          drawGui();
        });
      break;
    case "1":
      {
        const p = new PageBuilder(5); // Add a scroll limit so it will be scrollable with up and down
        p.addRow({
          text: "Example of a custom popup content!",
          color: "yellow",
        });
        p.addRow({ text: "This is a custom popup!", color: "green" });
        p.addRow({
          text: "It can be used to show a message,",
          color: "green",
        });
        p.addRow({ text: "or to show variables.", color: "green" });
        p.addRow(
          { text: "TCP Message sent: ", color: "green" },
          { text: `${12}`, color: "white" }
        );
        p.addRow(
          { text: "Connected clients: ", color: "green" },
          { text: `${20}`, color: "white" }
        );
        p.addRow(
          { text: "Mode: ", color: "green" },
          { text: `${"radsec"}`, color: "white" }
        );
        p.addRow(
          { text: "Message period: ", color: "green" },
          { text: `${100} ms`, color: "white" }
        );
        new CustomPopup({
          id: "popupCustom1",
          title: "See that values",
          content: p,
          width: 32,
        }).show();
      }
      break;
    case "q":
      new ConfirmPopup({
        id: "popupQuit",
        title: "Are you sure you want to quit?",
      })
        .show()
        .on("confirm", () => closeApp());
      break;
    default:
      break;
  }
});

const closeApp = () => {
  console.clear();
  process.exit();
};

GUI.refresh();

const footer = new Box({
  id: "footer",
  x: 0,
  y: GUI.Screen.height - 1,
  width: GUI.Screen.width,
  height: 1,
});
const row_footer = new InPageWidgetBuilder(1);

row_footer.addRow(
  { text: "F1:", color: "white", bold: true },
  { text: "Help  ", color: "black", bg: "bgCyan", bold: false },
  { text: "F6:", color: "white", bold: true },
  { text: "SortBy", color: "black", bg: "bgCyan", bold: false },
  { text: "F9:", color: "white", bold: true },
  { text: "Kill  ", color: "black", bg: "bgCyan", bold: false },
  { text: "F10:", color: "white", bold: true },
  { text: "Quit  ", color: "black", bg: "bgCyan", bold: false }
);
footer.setContent(row_footer);

GUI.on("resize", () => {
  footer.absoluteValues = {
    x: 0,
    y: GUI.Screen.height - 2,
    width: GUI.Screen.width,
    height: 1,
  };
  GUI.refresh();
});

const drawGui = () => {
  updateConsole();
};

drawGui();
valueEmitter = setInterval(frame, 2000);

setInterval(() => {
  logger.info("test");
}, 5000);

Library Version

^3.7.0

Node Version

^3.7.0

What operating system are you using?

Windows

Terminal

powershell and git bash

Interest to fix the bug

  • I would like to fix this bug!
@rjjrbatarao rjjrbatarao added the bug Something isn't working label Jun 24, 2024
@Elius94
Copy link
Owner

Elius94 commented Jun 24, 2024

can you provide me the full code? I can't see where you are using my lib

@rjjrbatarao
Copy link
Author

Hello I updated the code so you could check. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants