Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
TurtIeSocks committed Jun 18, 2023
1 parent 523c792 commit 61bdb95
Show file tree
Hide file tree
Showing 11 changed files with 2,087 additions and 3 deletions.
2 changes: 0 additions & 2 deletions .gitattributes

This file was deleted.

3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# These are supported funding model platforms

github: TurtIeSocks
26 changes: 26 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Publish

on:
release:
types: [created]

jobs:
publish-npm:
name: Publish to NPM
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 2

- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: 18
registry-url: https://registry.npmjs.org/
- run: yarn install
- run: yarn build:ts
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
131 changes: 130 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,131 @@
# pm2-discord-logger


PM2 Module for logging events & logs from your PM2 processes to Discord via webhooks. This module is designed to be used with [PM2](https://pm2.keymetrics.io/), it is not a standalone application.

## Install

To install and setup pm2-discord-logger, run the following commands:

```bash
pm2 install pm2-discord-logger
```

## Config Properties

```ts
interface Config {
/**
* Duration in seconds to aggregate messages.
* @default 1
* */
buffer_seconds?: number
/**
* Discord webhook url for logs
* @default null
* */
log_url: string | null
/**
* Discord webhook url for errors
* @default null
* */
error_url: string | null
/**
* Discord webhook url for events
* @default null
* */
event_url: string | null

// All of these are considered events and logged to the event channel

/**
* Enable kill event logs
* @default false
* */
kill: boolean
/**
* Enable exception event logs
* @default true
* */
exception: boolean
/**
* Enable restart event logs
* @default true
* */
restart: boolean
/**
* Enable exit event logs
* @default false
* */
exit: boolean
/**
* Enable delete event logs
* @default false
* */
delete: boolean
/**
* Enable start event logs
* @default true
* */
start: boolean
/**
* Enable stop event logs
* @default true
* */
stop: boolean
/**
* Enable online event logs
* @default true
* */
online: boolean
/**
* Enable restart overlimit event logs
* @default true
* */
'restart overlimit': boolean
}
```

## Setup

1. Create a Discord Webhook for your server. See [this article](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks) for more information.
1. Set your PM2 config values
1. e.g:

```bash
pm2 set pm2-discord-logger:log_url https://discordapp.com/api/webhooks/123456789/abcdefghijklmnopqrstuvwxyz
pm2 set pm2-discord-logger:restart true
```

1. You can set the same or different webhook for each channel but logs will not be recorded if the webhook is not set.

## Development

1. Fork and clone the repo
1. Install dependencies

```bash
yarn install
```

1. Build the project in watch mode

```bash
yarn watch
```

1. Copy the `package.json` file into the `dist` folder

```bash
cp package.json dist
```

1. Run the project locally in PM2

```bash
cd dist
pm2 install .
```

## Acknowledgements

Core concept inspired by [ben-sommer/pm2-discord](https://github.com/ben-sommer/pm2-discord-webhook)
55 changes: 55 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "pm2-discord-logger",
"version": "1.0.0",
"description": "PM2 Discord Logger",
"main": "dist/app.js",
"author": "Derick M. <[email protected]>",
"license": "MIT",
"files": [
"dist"
],
"private": false,
"repository": {
"type": "git",
"url": "https://github.com/TurtIeSocks/pm2-discord-logger.git"
},
"scripts": {
"start": "node dist/app.js",
"build": "tsc",
"watch": "tsc -w"
},
"dependencies": {
"@pm2/io": "^5.0.0",
"discord.js": "^14.11.0",
"pm2": "^5.3.0",
"pmx": "^1.6.7",
"strip-ansi": "^6.0.0"
},
"devDependencies": {
"@types/node": "^18",
"prettier": "^2.8.8",
"typescript": "^5.1.3"
},
"config": {
"log_url": null,
"error_url": null,
"event_url": null,
"kill": false,
"exception": true,
"restart": true,
"delete": false,
"stop": true,
"restart overlimit": true,
"exit": false,
"start": false,
"online": false,
"buffer_seconds": 1
},
"apps": [
{
"merge_logs": true,
"max_memory_restart": "256M",
"script": "app.js"
}
]
}
106 changes: 106 additions & 0 deletions src/Discord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { WebhookClient, APIEmbed } from 'discord.js'
import stripAnsi from 'strip-ansi'
import { Data, Message, Role } from './types'

const AUTHOR = {
name: 'PM2',
icon_url:
'https://cdn2.opsmatters.com/sites/default/files/logos/pm2-thumb.png',
}

export class DiscordLogger extends WebhookClient {
messages: APIEmbed[]
buffer: Message[]
role: Role
color: number

constructor(url: string, role: Role) {
super({ url })
this.messages = []
this.buffer = []
this.role = role
this.color =
role === 'log' ? 0x00ff00 : role === 'error' ? 0xff0000 : 0x0000ff

console.log(`DiscordLogger: ${role} client created`)
}

static getTitle(data: Data) {
return `${data.process.name}${
data.process?.version && data.process.version !== 'N/A'
? ` v${data.process.version}`
: ''
}${data.event ? ` - ${data.event}` : ''}`
}

static ensureString(data: string | object) {
return typeof data === 'string' ? data : JSON.stringify(data)
}

createMessage(
data: Data,
title?: string,
description?: string,
timestamp?: number
) {
const safeDesc = description || DiscordLogger.ensureString(data.data) || ''
const chunks = safeDesc.match(/[\s\S]{1,4095}/g)
if (chunks) {
chunks.forEach((chunk, i) => {
const message: APIEmbed = {
title: `${title || DiscordLogger.getTitle(data)}${
chunks.length > 1 ? ` (${i + 1}/${chunks.length})` : ''
}`,
description: chunk,
author: AUTHOR,
timestamp: new Date(timestamp || data.at).toISOString(),
color: this.color,
}
this.messages.push(message)
})
}
}

async sendMessages() {
this.collectLogs()
if (this.messages.length) {
await this.send({ embeds: this.messages })
this.messages = []
}
}

pushToBuffer(data: Data) {
if (data.process.name === 'pm2-discord-logger') {
return
}
const message = DiscordLogger.ensureString(data.data)

this.buffer.push({
process: {
name: DiscordLogger.getTitle(data),
},
data: stripAnsi(message),
at: Date.now(),
})
}

collectLogs() {
const nextMessage = this.buffer.shift()
if (!nextMessage) return

nextMessage.buffer = [nextMessage.data]

while (
this.buffer.length &&
this.buffer[0].at >= nextMessage.at &&
this.buffer[0].at < nextMessage.at + 1000
) {
nextMessage.buffer.push(this.buffer[0].data)
this.buffer.shift()
}
nextMessage.data = nextMessage.buffer.filter(Boolean).join('\n')
delete nextMessage.buffer

this.createMessage(nextMessage)
}
}
Loading

0 comments on commit 61bdb95

Please sign in to comment.