§2024-05-31

resolved: # uri("mongodb+srv://alexlai:alex1765@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=syslog_ng_db&tls=false") failed, but uri("mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false") works??

¶ syslog-ng write into a mongoDB capped collection by ChatGPT

To configure syslog-ng to write log messages into a MongoDB capped collection, you need to follow these general steps:

¶Configure MongoDB: Set up a capped collection in MongoDB where you want to store the log messages.

Here's a basic example configuration for syslog-ng to write log messages into a MongoDB capped collection:

@version: 3.28
@include "scl.conf"

source s_network {
    tcp(ip(0.0.0.0) port(514));
};

parser p_syslog {
    syslog-parser();
};

destination d_mongodb {
    mongodb(
        database("your_database_name")
        collection("your_capped_collection_name")
        server("mongodb://localhost:27017")
        template("$(format-json --scope rfc5424 --scope nv-pairs)")
    );
};

log {
    source(s_network);
    parser(p_syslog);
    destination(d_mongodb);
};

¶ see of module for mongodb is compiled in the ubuntu packages?

alexlai@n2Bookworm:~$ /usr/sbin/syslog-ng --version
syslog-ng 3 (3.38.1)
Config version: 3.35
Installer-Version: 3.38.1
Revision: 3.38.1-5
Compile-Date: Jan 30 2023 18:18:56
Module-Directory: /usr/lib/syslog-ng/3.38
Module-Path: /usr/lib/syslog-ng/3.38
Include-Path: /usr/share/syslog-ng/include
Available-Modules: azure-auth-header,mod-python.cpython-311-aarch64-linux-gnu,riemann,secure-logging,afsmtp,xml,affile,afprog,afsocket,afuser,appmodel,basicfuncs,cef,confgen,cryptofuncs,csvparser,dbparser,disk-buffer,hook-commands,json-plugin,kvformat,linux-kmsg-format,map-value-pairs,pacctformat,pseudofile,rate-limit-filter,regexp-parser,sdjournal,syslogformat,system-source,tags-parser,tfgetent,timestamp,afsql,afmongodb,add-contextual-data,afamqp,examples,geoip2-plugin,graphite,http,kafka,redis,afsnmp,afstomp,stardate
Enable-Debug: off
Enable-GProf: off
Enable-Memtrace: off
Enable-IPv6: on
Enable-Spoof-Source: on
Enable-TCP-Wrapper: on
Enable-Linux-Caps: on
Enable-Systemd: on

¶ Here's how you can set up syslog-ng to write logs to a MongoDB capped collection:

  1. Create a Capped Collection in MongoDB

First, ensure you have a MongoDB instance running. Then, create a capped collection in your MongoDB database:

lexlai@n2Bookworm:~$ mongosh "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/YuSheiDBTest?replicaSet=odroid01&authSource=admin&tls=false"
Current Mongosh Log ID:	665a5aba74c201d0f28db5fa
Connecting to:		mongodb+srv://<credentials>@inLaneCatch.yushei.com.tw/YuSheiDBTest?replicaSet=odroid01&authSource=admin&tls=false&appName=mongosh+2.2.6
Using MongoDB:		7.0.0-rc8
Using Mongosh:		2.2.6

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

odroid01 [primary] YuSheiDBTest> show databases
Learn          72.00 KiB
Syslog-NG     308.00 KiB
WuShunDB      312.00 KiB
YuSheiDBTest    2.07 GiB
YuSheiERP      40.00 KiB
admin         252.00 KiB
config        332.00 KiB
local          13.10 GiB
odroid01 [primary] YuSheiDBTest> use Syslog-NG
switched to db Syslog-NG
odroid01 [primary] Syslog-NG> db.dropDatabase();
{ ok: 1, dropped: 'Syslog-NG' }
odroid01 [primary] Syslog-NG> show databases
Learn          72.00 KiB
WuShunDB      312.00 KiB
YuSheiDBTest    2.07 GiB
YuSheiERP      40.00 KiB
admin         252.00 KiB
config        332.00 KiB
local          13.10 GiB

odroid01 [primary] YuSheiDBTest> use syslog_ng_db
switched to db syslog_ng_db

odroid01 [primary] syslog_ng_db> db.createCollection("Odroid01Replication", { capped: true, size: 5242880, max: 5000 })
{ ok: 1 }


db.createUser({
  user: "alexlai",
  pwd: "alex1765",
  roles: [ { role: "readWrite", db: "syslog_ng_db" }]
})

odroid01 [primary] syslog_ng_db> db.createUser({
...   user: "alexlai",
...   pwd: "alexlai",
...   roles: [ { role: "readWrite", db: "syslog_ng_db" }]
... })
{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1717198301, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('WWrWe4AQGeNLUYjG/WcRvA3X12U=', 0),
      keyId: Long('7326325939019710465')
    }
  },
  operationTime: Timestamp({ t: 1717198301, i: 1 })
}

odroid01 [primary] syslog_ng_db> show collections
Odroid01Replication

odroid01 [primary] syslog_ng_db> db.getUsers()
{
  users: [
    {
      _id: 'syslog_ng_db.alexlai',
      userId: UUID('479031a6-e2c3-4274-9dec-4e3abcbb9877'),
      user: 'alexlai',
      db: 'syslog_ng_db',
      roles: [ { role: 'readWrite', db: 'syslog_ng_db' } ],
      mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1717198419, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('1vovkra54pclvf7w8jdKl6vnk48=', 0),
      keyId: Long('7326325939019710465')
    }
  },
  operationTime: Timestamp({ t: 1717198419, i: 1 })
}

odroid01 [primary] syslog_ng_db> use admin
switched to db admin
odroid01 [primary] admin> db.auth("siteRootAdmin", "b23258585")
{ ok: 1 }
odroid01 [primary] admin> use syslog_ng_db
switched to db syslog_ng_db
odroid01 [primary] syslog_ng_db> db.updateUser("alexlai", {
...     roles: [
...         { role: "readWrite", db: "syslog_ng_db" },
...         { role: "dbAdmin", db: "syslog_ng_db" }
...     ]
... })
{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1717208035, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('cE+V9A34xCR33Qwbym4ai4xfUQU=', 0),
      keyId: Long('7326325939019710465')
    }
  },
  operationTime: Timestamp({ t: 1717208035, i: 1 })
}

odroid01 [primary] syslog_ng_db> db.getUser("alexlai")
{
  _id: 'syslog_ng_db.alexlai',
  userId: UUID('479031a6-e2c3-4274-9dec-4e3abcbb9877'),
  user: 'alexlai',
  db: 'syslog_ng_db',
  roles: [
    { role: 'readWrite', db: 'syslog_ng_db' },
    { role: 'dbAdmin', db: 'syslog_ng_db' }
  ],
  mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
}

alexlai@n2Bookworm:~$ mongosh "mongodb+srv://alexlai:alex1765@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=syslog_ng_db&tls=false"
Current Mongosh Log ID:	665a625b0f4879d4908db5fa
Connecting to:		mongodb+srv://<credentials>@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=syslog_ng_db&tls=false&appName=mongosh+2.2.6
Using MongoDB:		7.0.0-rc8
Using Mongosh:		2.2.6

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

odroid01 [primary] syslog_ng_db> show tables;
Odroid01Replication
odroid01 [primary] syslog_ng_db> db.Odroid01Replication.count(_)
DeprecationWarning: Collection.count() is deprecated. Use countDocuments or estimatedDocumentCount.
0
odroid01 [primary] syslog_ng_db> 
  1. modify /etc/syslog-ng/syslog-ng.conf
@version: 3.38
@include "scl.conf"

@module afmongodb

source s_mongo_log {
    file("/var/log/mongodb/mongod.log" flags(no-parse));
};

parser p_syslog {
    syslog-parser();
};

destination d_mongodb {
    mongodb(
      # using alexlai:alex1765 is not working
      # uri("mongodb+srv://alexlai:alex1765@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=syslog_ng_db&tls=false")
      uri("mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false")
      collection("Odroid01Replication")
      # template("$(format-json --scope rfc5424 --scope nv-pairs)")
    );
};

log {
    source(s_mongo_log);
    parser(p_syslog);
    destination(d_mongodb);
};


testing with

root@n2Bookworm:/home/alexlai# /sbin/syslog-ng -s -f /etc/syslog-ng/syslog-ng.conf
root@n2Bookworm:/home/alexlai# systemctl restart syslog-ng
root@n2Bookworm:/home/alexlai# systemctl status  syslog-ng
● syslog-ng.service - System Logger Daemon
     Loaded: loaded (/lib/systemd/system/syslog-ng.service; enabled; preset: enabled)
     Active: active (running) since Sat 2024-06-01 08:08:49 CST; 6s ago
       Docs: man:syslog-ng(8)
   Main PID: 9401 (syslog-ng)
      Tasks: 12 (limit: 3414)
     Memory: 3.9M
        CPU: 164ms
     CGroup: /system.slice/syslog-ng.service
             └─9401 /usr/sbin/syslog-ng -F

Jun 01 08:08:48 n2Bookworm systemd[1]: Starting syslog-ng.service - System Logger Daemon...
Jun 01 08:08:49 n2Bookworm systemd[1]: Started syslog-ng.service - System Logger Daemon.
@version: 3.27
@include "scl.conf"

source s_mongo_log {
    file("/var/log/mongodb/mongod.log" flags(no-parse));
};

# Destinations
destination d_hc4Jammy {
    syslog("hc4Jammy.yushei.com.tw" transport("udp") port(514));
};

destination d_mongodb {
    mongodb(
        database("Syslog-NG")
        collection("odroid-01-replication")
        server("mongodb://alexlai:alexlai@inLaneCatch.yushei.com.tw:27017/?replicaSet=odroid01&authSource=admin&tls=false")
        template("$(format-json --scope rfc5424 --scope nv-pairs)")
    );
};

parser p_syslog {
    syslog-parser();
};


filter f_mongodb_replication {
    match("PRIMARY" value("MESSAGE") flags("icase")) or
    match("SECONDARY" value("MESSAGE") flags("icase")) or
    match("RECOVERING" value("MESSAGE") flags("icase")) or
    match("STARTUP" value("MESSAGE") flags("icase")) or
    match("ROLLBACK" value("MESSAGE") flags("icase")) or
    match("RESYNCING" value("MESSAGE") flags("icase")) or
    match("heartbeat" value("MESSAGE") flags("icase")) or
    match("election" value("MESSAGE") flags("icase")) or
    match("sync source" value("MESSAGE") flags("icase")) or
    match("initial sync" value("MESSAGE") flags("icase")) or
    match("vote" value("MESSAGE") flags("icase")) or
    match("Term changed" value("MESSAGE") flags("icase")) or
    match("cannot connect" value("MESSAGE") flags("icase")) or
    match("failed to connect" value("MESSAGE") flags("icase")) or
    match("Stepping down" value("MESSAGE") flags("icase")) or
    match("replSet" value("MESSAGE") flags("icase")) or
    match("replication lag" value("MESSAGE") flags("icase")) or
    match("slow" value("MESSAGE") flags("icase")) or
    match("error" value("MESSAGE") flags("icase")) or
    match("exceeded" value("MESSAGE") flags("icase"));
};

# Filters
# filter f_hc4Jammy {
#     host("hc4Jammyyushei.com.tw");
# };

# Bind Sources, Destinations, and Filters

# Send mongod.log from redismongo03.yushei.com.tw to hc4nas02.yushei.net
log {
    source(s_mongo_log);
    filter(f_mongodb_replication);
    # destination(d_hc4Jammy);
    parser(p_syslog);
    destination(d_mongodb);
};
@version: 3.38
@include "scl.conf"

source s_mongo_log {
    file("/var/log/mongodb/mongod.log" flags(no-parse));
};

parser p_syslog {
    syslog-parser();
};

# Destinations
destination d_hc4Jammy {
    syslog("hc4Jammy.yushei.com.tw" transport("udp") port(514));
};

destination d_mongodb {
    mongodb(
        database("Syslog-NG")
        collection("odroid-01-replication")
        server("mongodb://alexlai:alexlai@inLaneCatch.yushei.com.tw:27017/?replicaSet=odroid01&authSource=admin&tls=false")
        template("$(format-json --scope rfc5424 --scope nv-pairs)")
    );
};

filter f_mongodb_replication {
    match("PRIMARY" value("MESSAGE") flags("icase")) or
    match("SECONDARY" value("MESSAGE") flags("icase")) or
    match("RECOVERING" value("MESSAGE") flags("icase")) or
    match("STARTUP" value("MESSAGE") flags("icase")) or
    match("ROLLBACK" value("MESSAGE") flags("icase")) or
    match("RESYNCING" value("MESSAGE") flags("icase")) or
    match("heartbeat" value("MESSAGE") flags("icase")) or
    match("election" value("MESSAGE") flags("icase")) or
    match("sync source" value("MESSAGE") flags("icase")) or
    match("initial sync" value("MESSAGE") flags("icase")) or
    match("vote" value("MESSAGE") flags("icase")) or
    match("Term changed" value("MESSAGE") flags("icase")) or
    match("cannot connect" value("MESSAGE") flags("icase")) or
    match("failed to connect" value("MESSAGE") flags("icase")) or
    match("Stepping down" value("MESSAGE") flags("icase")) or
    match("replSet" value("MESSAGE") flags("icase")) or
    match("replication lag" value("MESSAGE") flags("icase")) or
    match("slow" value("MESSAGE") flags("icase")) or
    match("error" value("MESSAGE") flags("icase")) or
    match("exceeded" value("MESSAGE") flags("icase"));
};

# Filters
# filter f_hc4Jammy {
#     host("hc4Jammyyushei.com.tw");
# };

# Bind Sources, Destinations, and Filters

# Send mongod.log
log {
    source(s_mongo_log);
    filter(f_mongodb_replication);
    # destination(d_hc4Jammy);
    parser(p_syslog);
    destination(d_mongodb);
};
root@n2Bookworm:/home/alexlai# cat  /etc/syslog-ng/syslog-ng.conf
@version: 3.38
@include "scl.conf"

@module afmongodb

source s_mongo_log {
    file("/var/log/mongodb/mongod.log" flags(no-parse));
};

parser p_syslog {
    syslog-parser();
};

destination d_mongodb {
    mongodb(
      # uri("mongodb+srv://alexlai:alex1765@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=syslog_ng_db&tls=false")
      uri("mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false")
      collection("Odroid01Replication")
      # template("$(format-json --scope rfc5424 --scope nv-pairs)")
    );
};

log {
    source(s_mongo_log);
    parser(p_syslog);
    destination(d_mongodb);
};

GPT,

I had a mongodb replicationSet that could be connected with "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false". I would like to write a javascript using MongoClient to watch a capped collection of "Odroid01Replication" inside the database "syslog_ng_db" and evertime a document was inserted into this capped collection, it will output with console.log.

const { MongoClient } = require('mongodb');

const uri = "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

async function run() {
    try {
        await client.connect();
        console.log("Connected to the database!");

        const db = client.db('syslog_ng_db');
        const collection = db.collection('Odroid01Replication');

        console.log("Watching for changes in the 'Odroid01Replication' collection...");

        // Open a change stream on the collection
        const changeStream = collection.watch([], { fullDocument: 'updateLookup' });

        // Listen for changes in the stream
        changeStream.on('change', (change) => {
            if (change.operationType === 'insert') {
                console.log('New document inserted:');
                console.log(change.fullDocument);
            }
        });
    } catch (err) {
        console.error(err);
    }
}

run().catch(console.dir);
const { MongoClient } = require('mongodb');

const uri = "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

async function run() {
    try {
        await client.connect();
        console.log("Connected to the database!");

        const db = client.db('syslog_ng_db');
        const collection = db.collection('Odroid01Replication');

        console.log("Watching for insertions in the 'Odroid01Replication' collection...");

        // Open a change stream on the collection with a filter for insert operations
        const changeStream = collection.watch(
            [{ $match: { 'operationType': 'insert' } }],
            { fullDocument: 'updateLookup' }
        );

        // Listen for changes in the stream
        changeStream.on('change', (change) => {
            console.log('New document inserted:');
            console.log(change.fullDocument);
        });
    } catch (err) {
        console.error(err);
    }
}

run().catch(console.dir);
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const { MongoClient } = require('mongodb');

const uri = "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

const port = process.env.PORT || 48597;

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

async function run() {
    try {
        await client.connect();
        console.log("Connected to the database!");

        const db = client.db('syslog_ng_db');
        const collection = db.collection('Odroid01Replication');

        console.log("Watching for insertions in the 'Odroid01Replication' collection...");

        // Open a change stream on the collection with a filter for insert operations
        const changeStream = collection.watch(
            [{ $match: { 'operationType': 'insert' } }],
            { fullDocument: 'updateLookup' }
        );

        // Listen for changes in the stream
        changeStream.on('change', (change) => {
            console.log('New document inserted:');
            console.log(change.fullDocument);
            io.emit('newDocument', change.fullDocument);
        });
    } catch (err) {
        console.error(err);
    }
}

run().catch(console.dir);

server.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});
<!DOCTYPE html>
<html>
<head>
    <title>MongoDB Insert Monitor</title>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', (event) => {
            const socket = io();

            socket.on('newDocument', (doc) => {
                const container = document.getElementById('documents');
                const docDiv = document.createElement('div');
                docDiv.textContent = JSON.stringify(doc, null, 2);
                container.appendChild(docDiv);
            });
        });
    </script>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        #documents {
            margin: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            max-height: 500px;
            overflow-y: scroll;
        }
        #documents div {
            margin-bottom: 10px;
            padding: 10px;
            border-bottom: 1px solid #eee;
        }
    </style>
</head>
<body>
    <h1>MongoDB Insert Monitor</h1>
    <div id="documents">
        <!-- New documents will be appended here -->
    </div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
    <title>MongoDB Insert Monitor</title>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', (event) => {
            const socket = io();

            socket.on('newDocument', (doc) => {
                const container = document.getElementById('documents');
                const docDiv = document.createElement('div');
                docDiv.textContent = JSON.stringify(doc, null, 2);
                container.appendChild(docDiv);
                limitLines(container, 180);
            });

            function limitLines(container, maxLines) {
                const lines = container.children;
                while (lines.length > maxLines) {
                    container.removeChild(lines[0]);
                }
            }
        });
    </script>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        #documents {
            margin: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            max-height: 500px;
            overflow-y: scroll;
        }
        #documents div {
            margin-bottom: 10px;
            padding: 10px;
            border-bottom: 1px solid #eee;
        }
    </style>
</head>
<body>
    <h1>MongoDB Insert Monitor</h1>
    <div id="documents">
        <!-- New documents will be appended here -->
    </div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
    <title>MongoDB Insert Monitor</title>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', (event) => {
            const socket = io();
            const maxLines = 180;
            let currentIndex = 0;
            let container = document.getElementById('documents');

            // Pre-create div elements for the circular buffer
            let docDivs = [];
            for (let i = 0; i < maxLines; i++) {
                let docDiv = document.createElement('div');
                container.appendChild(docDiv);
                docDivs.push(docDiv);
            }

            socket.on('newDocument', (doc) => {
                docDivs[currentIndex].textContent = JSON.stringify(doc, null, 2);
                currentIndex = (currentIndex + 1) % maxLines;
            });
        });
    </script>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #1e1e1e;
            color: #c5c6c7;
            margin: 0;
            padding: 0;
        }
        h1 {
            text-align: center;
            color: #66fcf1;
            padding: 20px 0;
            margin: 0;
            border-bottom: 1px solid #c5c6c7;
        }
        #documents {
            margin: 20px;
            padding: 10px;
            border: 1px solid #c5c6c7;
            border-radius: 5px;
            max-height: 80vh;
            overflow-y: scroll;
            background-color: #0b0c10;
        }
        #documents div {
            margin-bottom: 10px;
            padding: 10px;
            border-bottom: 1px solid #c5c6c7;
            background-color: #1f2833;
            border-radius: 3px;
        }
    </style>
</head>
<body>
    <h1>MongoDB Insert Monitor</h1>
    <div id="documents">
        <!-- New documents will be appended here -->
    </div>
</body>
</html>

To modify the provided index.html file so that it only displays MongoDB documents when 'Election', 'error', and 'slow' events occur, you will need to update the server-side logic to filter the documents based on these criteria and send only the relevant events to the client.

Server-Side (Node.js) Update First, update your server.js to filter the relevant events:

javascript Copy code const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const { MongoClient } = require('mongodb');

const uri = "mongodb+srv://siteRootAdmin:b23258585@inLaneCatch.yushei.com.tw/syslog_ng_db?replicaSet=odroid01&authSource=admin&tls=false"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

const app = express(); const server = http.createServer(app); const io = socketIo(server);

const port = process.env.PORT || 3000;

app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html'); });

async function run() { try { await client.connect(); console.log("Connected to the database!");

    const db = client.db('syslog_ng_db');
    const collection = db.collection('Odroid01Replication');

    console.log("Watching for relevant events in the 'Odroid01Replication' collection...");

    // Open a change stream on the collection with a filter for relevant events
    const changeStream = collection.watch([
        { 
            $match: { 
                $or: [
                    { 'fullDocument.message': /Election/i },
                    { 'fullDocument.message': /error/i },
                    { 'fullDocument.message': /slow/i }
                ]
            }
        }
    ], { fullDocument: 'updateLookup' });

    // Listen for changes in the stream
    changeStream.on('change', (change) => {
        console.log('Relevant event detected:');
        console.log(change.fullDocument);
        io.emit('newDocument', change.fullDocument);
    });
} catch (err) {
    console.error(err);
}

}

run().catch(console.dir);

server.listen(port, () => { console.log(Server is running on port ${port}); }); Client-Side (HTML and JavaScript) Update Next, update your index.html to handle the filtered events from the server:

html Copy code

MongoDB Insert Monitor