ntlogger 2.6.1 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -13,6 +13,11 @@
13
13
 
14
14
  /**
15
15
  * Change Log:
16
+ * v2.6.2 - 08/15/2024:
17
+ * [DEPENDENCY] Added pg package for Postgres Plugin
18
+ * [FEATURE] Postgres Plugin
19
+ * a simple mysql rewrite so not even going to make a minor version bump
20
+ *
16
21
  * v2.6.1 - 08/15/2024:
17
22
  * [UPDATED] @sentry/node ^8.25.0 --> ^8.26.0
18
23
  * [UPDATED] @sentry/profiling-node ^8.25.0 --> ^8.26.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ntlogger",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/NightSquawk/NightTimeLogger.git"
@@ -32,6 +32,7 @@
32
32
  "dependencies": {
33
33
  "@sentry/node": "^8.26.0",
34
34
  "mysql2": "^3.11.0",
35
+ "pg": "^8.12.0",
35
36
  "winston": "^3.14.2",
36
37
  "winston-transport": "^4.7.1"
37
38
  },
package/plugins/index.js CHANGED
@@ -7,10 +7,12 @@
7
7
  const plugins = {
8
8
  Sentry : require('./sentry'),
9
9
  MySQL : require('./mysql'),
10
+ Postgres: require('./postgres'),
10
11
  Jest : require('./jest'),
11
12
  Syslog : require('./syslog'),
12
13
  Discord : require('./discord'),
13
14
  Teams : require('./teams'),
15
+
14
16
  // WIP SMSMail : require('./smsMail'),
15
17
  };
16
18
 
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @file /plugins/postgres.js
3
+ * @description Stores logs in PostgresSQL database.
4
+ */
5
+
6
+ const Transport = require('winston-transport');
7
+ const { Pool } = require('pg');
8
+ const levels = require('../lib/levels');
9
+
10
+ let connectionPool = null;
11
+ let tableInitialized = false;
12
+
13
+ class PostgreSQLTransport extends Transport {
14
+ constructor(opts = {}) {
15
+ super(opts);
16
+
17
+ this.name = 'PostgreSQL Transport for NTLogger';
18
+ this.database = opts.database || 'test';
19
+ this.table = opts.table || 'logs';
20
+
21
+ this.logLevel = opts.level ? levels[opts.level] : levels.info;
22
+
23
+ this.poolConfig = {
24
+ host: opts.host || 'localhost',
25
+ port: opts.port || 5432,
26
+ user: opts.user || 'postgres',
27
+ password: opts.password || '',
28
+ database: this.database,
29
+ max: opts.connectionLimit || 10,
30
+ idleTimeoutMillis: opts.idleTimeout || 60000,
31
+ connectionTimeoutMillis: opts.connectionTimeout || 2000,
32
+ };
33
+
34
+ this.init();
35
+ }
36
+
37
+ async init() {
38
+ try {
39
+ if (!connectionPool) {
40
+ connectionPool = new Pool(this.poolConfig);
41
+ }
42
+ this.pool = connectionPool;
43
+ await this.checkLogTable();
44
+ } catch (err) {
45
+ console.error(`Failed to initialize ${this.name}:`, err);
46
+ }
47
+ }
48
+
49
+ async log(info, callback) {
50
+ setImmediate(() => {
51
+ this.emit('logged', info);
52
+ });
53
+
54
+ if (!tableInitialized) {
55
+ await this.checkLogTable();
56
+ }
57
+
58
+ const { level, message, ...meta } = info;
59
+
60
+ if (levels[level] > this.logLevel) {
61
+ callback();
62
+ return;
63
+ }
64
+
65
+ const metaString = JSON.stringify(meta);
66
+ const timestamp = this.formatTimestamp(meta.timeCreated);
67
+
68
+ try {
69
+ await this.pool.query(
70
+ `INSERT INTO ${this.table} (level, message, meta, timestamp) VALUES ($1, $2, $3, $4)`,
71
+ [level, message, metaString, timestamp]
72
+ );
73
+ } catch (err) {
74
+ console.error(`Failed to log message to ${this.name}:`, err);
75
+ }
76
+
77
+ callback();
78
+ }
79
+
80
+ formatTimestamp(timeCreated) {
81
+ if (!timeCreated) {
82
+ return new Date().toISOString().slice(0, 19).replace('T', ' ');
83
+ }
84
+
85
+ const date = new Date();
86
+ const [time, modifier] = timeCreated.split(' ');
87
+ let [hours, minutes, seconds] = time.split(':');
88
+
89
+ if (modifier === 'PM' && hours !== '12') {
90
+ hours = parseInt(hours, 10) + 12;
91
+ }
92
+ if (modifier === 'AM' && hours === '12') {
93
+ hours = '00';
94
+ }
95
+
96
+ return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${hours}:${minutes}:${seconds}`;
97
+ }
98
+
99
+ async checkLogTable() {
100
+ if (tableInitialized) return;
101
+
102
+ try {
103
+ const result = await this.pool.query(
104
+ `SELECT to_regclass('${this.table}') as tablename`
105
+ );
106
+
107
+ if (!result.rows[0].tablename) {
108
+ await this.pool.query(
109
+ `CREATE TABLE IF NOT EXISTS ${this.table} (
110
+ id SERIAL PRIMARY KEY,
111
+ level VARCHAR(255) NOT NULL,
112
+ message TEXT NOT NULL,
113
+ meta JSONB,
114
+ timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
115
+ )`
116
+ );
117
+ }
118
+
119
+ tableInitialized = true;
120
+ } catch (err) {
121
+ console.error(`Failed to check or create table ${this.table}:`, err);
122
+ }
123
+ }
124
+
125
+ isActive() {
126
+ return this.pool && !this.pool.ended;
127
+ }
128
+
129
+ async close() {
130
+ if (connectionPool) {
131
+ await connectionPool.end();
132
+ connectionPool = null;
133
+ console.log('Closed PostgreSQL connection pool.');
134
+ }
135
+ }
136
+ }
137
+
138
+ module.exports = {
139
+ transport: PostgreSQLTransport,
140
+ };