[javascript] カラフルなconsole.log

# はじめに
普段、一面の白いconsole.logを見て、イライラしたり、重要な情報を一目で見つけるのが難しいと感じたことはありませんか？今日は、console.logをカラフルに変える方法を皆さんに共有します。

# エクスポート関数を作る
```typescript:messageUtil.ts
export const success = (msg: string) => {
  console.log("\x1b[32m%s \x1b[0m", `SUCCESS: ${msg}`);
};

export const error = (msg: string) => {
  console.log("\x1b[31m%s \x1b[0m", `ERROR: ${msg}`);
};

export const warning = (msg: string) => {
  console.log("\x1b[33m%s \x1b[0m", `WARNING: ${msg}`);
};

export const task = (msg: string) => {
  console.log("\x1b[35m%s \x1b[0m", `TASK: ${msg}`);
};

export const info = (msg: string) => {
  if (!msg) return;
  const lines = msg.split("\n").filter(Boolean);
  for (const line of lines) {
    console.log("\x1b[34m%s \x1b[0m", `INFO: ${line}`);
  }
};
```
# いざ使おう！
```typescript:main.ts
import "module-alias/register"
import * as MU from "@util/messageUtil"

MU.info("infoです");
MU.task("taskです");
MU.warning("warningです");
MU.error("errorです");
```
https://qiita.com/oharu121/items/df81018ab29eb8daed4e

下記のようにカラフルなログができましたね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/a108ac0b-27d8-ab55-8b25-1efcb7e2bc0a.png)
<details><summary>カラー一覧</summary>
<table>
    <tr>
        <th>Color Name</th>
        <th>Code</th>
    </tr>
    <tr>
        <td>Reset</td>
        <td>\x1b[0m</td>
    </tr>
    <tr>
        <td>Bright</td>
        <td>\x1b[1m</td>
    </tr>
    <tr>
        <td>Dim</td>
        <td>\x1b[2m</td>
    </tr>
    <tr>
        <td>Underscore</td>
        <td>\x1b[4m</td>
    </tr>
    <tr>
        <td>Blink</td>
        <td>\x1b[5m</td>
    </tr>
    <tr>
        <td>Reverse</td>
        <td>\x1b[7m</td>
    </tr>
    <tr>
        <td>Hidden</td>
        <td>\x1b[8m</td>
    </tr>
    <tr>
        <td>FgBlack</td>
        <td>\x1b[30m</td>
    </tr>
    <tr>
        <td>FgRed</td>
        <td>\x1b[31m</td>
    </tr>
    <tr>
        <td>FgGreen</td>
        <td>\x1b[32m</td>
    </tr>
    <tr>
        <td>FgYellow</td>
        <td>\x1b[33m</td>
    </tr>
    <tr>
        <td>FgBlue</td>
        <td>\x1b[34m</td>
    </tr>
    <tr>
        <td>FgMagenta</td>
        <td>\x1b[35m</td>
    </tr>
    <tr>
        <td>FgCyan</td>
        <td>\x1b[36m</td>
    </tr>
    <tr>
        <td>FgWhite</td>
        <td>\x1b[37m</td>
    </tr>
    <tr>
        <td>FgGray</td>
        <td>\x1b[90m</td>
    </tr>
    <tr>
        <td>BgBlack</td>
        <td>\x1b[40m</td>
    </tr>
    <tr>
        <td>BgRed</td>
        <td>\x1b[41m</td>
    </tr>
    <tr>
        <td>BgGreen</td>
        <td>\x1b[42m</td>
    </tr>
    <tr>
        <td>BgYellow</td>
        <td>\x1b[43m</td>
    </tr>
    <tr>
        <td>BgBlue</td>
        <td>\x1b[44m</td>
    </tr>
    <tr>
        <td>BgMagenta</td>
        <td>\x1b[45m</td>
    </tr>
    <tr>
        <td>BgCyan</td>
        <td>\x1b[46m</td>
    </tr>
    <tr>
        <td>BgWhite</td>
        <td>\x1b[47m</td>
    </tr>
    <tr>
        <td>BgGray</td>
        <td>\x1b[100m</td>
    </tr>
</table>

全部出力してみました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/fdbab7e2-77c5-230f-9a98-abfd2e57ab5a.png)

</details>

# 補足：タイムスタンプを追加する
dayjsライブラリを使用してログにタイムスタンプを追加することで、ログが記録された正確な時刻を把握することが可能になります。

https://qiita.com/oharu121/items/50db13169afb5369fa1e

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/ae3d10a2-1310-743e-fce9-16ffc72ea24a.png)
実装は以下です。
```typescript:messageUtil.ts
import dayjs from "dayjs";

const getTime = () => {
  return dayjs().format("HH:mm:ss:SSS");
};
const getLabel = () => {
  return `[${getTime()}]`;
};

export const success = (msg: string) => {
  console.log("\x1b[32m%s \x1b[0m", `${getLabel()} SUCCESS: ${msg}`);
};

export const error = (msg: string) => {
  console.log("\x1b[31m%s \x1b[0m", `${getLabel()} ERROR: ${msg}`);
};

export const warning = (msg: string) => {
  console.log("\x1b[33m%s \x1b[0m", `${getLabel()} WARNING: ${msg}`);
};

export const task = (msg: string) => {
  console.log("\x1b[35m%s \x1b[0m", `${getLabel()} TASK: ${msg}`);
};

export const info = (msg: string) => {
  if (!msg) return;
  const lines = msg.split("\n").filter(Boolean);
  for (const line of lines) {
    console.log("\x1b[34m%s \x1b[0m", `${getLabel()} INFO: ${line}`);
  }
};
```



# 補足：呼び出し位置を表示する
今回はクラス「foo」を追加しました。
```typescript:Foo.ts
import * as MU from "@util/messageUtil"

class Foo {
  constructor() {
    MU.info("Foo だよ！")
  }
}

export default Foo;
```
そして、main.tsでFooを呼び出します。
```diff_typescript:main.ts
import "module-alias/register";
import * as MU from "@util/messageUtil";
+import Foo from "@class/Foo";

MU.success("successです");
MU.info("infoです");
MU.task("taskです");
MU.warning("warningです");
MU.error("errorです");
+const foo = new Foo();
```
どこで呼び出すかがわかるようになりましたね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/a83efa3b-6b78-893a-fb5f-1d9ca2e51ddd.png)
実装は以下です。
```typescript:messageUtil.ts
import dayjs from "dayjs";

const getTime = () => {
  return dayjs().format("HH:mm:ss:SSS");
};
const getLabel = () => {
  return `[${getScriptName()} ${getTime()}]`;
};

const getScriptName = () => {
  const error = new Error();
  const stack = error.stack || "";
  const stackLines = stack.split("\n");

  // スタックトレースの3行目から開始して、呼び出し元のコードを探します。
  // 最初の行はエラーメッセージで、2行目はこの関数の呼び出しです。
  // 必要に応じて開始インデックスを調整してください。
  let callerInfo = "";
  for (let i = 2; i < stackLines.length; i++) {
    if (stackLines[i].includes(__filename)) {
      // 現在のファイル名を含む行はスキップします
      continue;
    } else {
      callerInfo = stackLines[i];
      break;
    }
  }

  let callerLocation = "Unknown location";
  if (callerInfo) {
    callerLocation = callerInfo.split("(")[1].replace(")", "");
  }

  return callerLocation;
};

export const success = (msg: string) => {
  console.log("\x1b[32m%s \x1b[0m", `${getLabel()} SUCCESS: ${msg}`);
};

export const error = (msg: string) => {
  console.log("\x1b[31m%s \x1b[0m", `${getLabel()} ERROR: ${msg}`);
};

export const warning = (msg: string) => {
  console.log("\x1b[33m%s \x1b[0m", `${getLabel()} WARNING: ${msg}`);
};

export const task = (msg: string) => {
  console.log("\x1b[35m%s \x1b[0m", `${getLabel()} TASK: ${msg}`);
};

export const info = (msg: string) => {
  if (!msg) return;
  const lines = msg.split("\n").filter(Boolean);
  for (const line of lines) {
    console.log("\x1b[34m%s \x1b[0m", `${getLabel()} INFO: ${line}`);
  }
};

```
# 追記：サードパーティライブラリ
サードパーティライブラリを使用することでエラーメッセージを赤色など、好みの色で簡単に表示できます。例えば、chalkライブラリを使用してエラーメッセージを赤色で表示するには、次のようにします：
```
npm install chalk
```
```typescript:example.ts
import chalk from "chalk";
console.error(chalk.red('This is an error message'));
```
https://www.npmjs.com/package/chalk
# まとめ
この記事では、一般的な白黒のconsole.log出力を、より視認性が高く、情報が把握しやすいカラフルなログに変える方法をご紹介しました。messageUtil.tsを用いて、ログの種類ごとに異なる色を割り当てることで、エラー、警告、情報などのログを一目で区別できるようになります。また、dayjsライブラリを使用してログにタイムスタンプを追加することで、ログが記録された正確な時刻を把握することが可能になります。