-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
feat: add RabbitMQ
monitor
#5199
Merged
CommanderStorm
merged 23 commits into
louislam:master
from
Suven-p:5066_add_rabbitmq_support
Oct 20, 2024
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
2879b53
Add Rabbitmq monitor
Suven-p eeb614e
Merge branch 'master' into 5066_add_rabbitmq_support
Suven-p 4c47d2f
Add translation string
Suven-p 1c02023
Add description and validation for nodes input field
Suven-p 74da7e5
Merge branch '5066_add_rabbitmq_support' of https://github.com/Suven-…
Suven-p 4fa640b
Update messages
Suven-p 44cd675
Replace input type password with HiddenInput
Suven-p 009b004
Make requested changes
Suven-p fd3dbff
Merge branch 'master' into 5066_add_rabbitmq_support
Suven-p 21a2d3c
Change monitor type to specify management plugin
Suven-p 0ba3773
Bugfix: Correct validation for rabbitmq nodes
Suven-p 685043e
Add test containers
Suven-p 7961ebb
Add translation for RabbitMQ monitor type
Suven-p bf32550
Fix linting error
Suven-p 73ee628
Bugfix: Add support for base url with path
Suven-p 444661e
Save message for 503 status code
Suven-p 6380df9
Fix relative path in test
Suven-p fc68042
Removed unnessesary comment
CommanderStorm 7ce46d6
Update src/lang/en.json
Suven-p 2a2b840
Add helptext
Suven-p 85f5552
Remove helptext from monitor type
Suven-p d1ad668
Apply suggestions from code review
CommanderStorm 9f23b5c
Merge branch 'master' into 5066_add_rabbitmq_support
Suven-p File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
exports.up = function (knex) { | ||
return knex.schema.alterTable("monitor", function (table) { | ||
table.text("rabbitmq_nodes"); | ||
table.string("rabbitmq_username"); | ||
table.string("rabbitmq_password"); | ||
}); | ||
|
||
}; | ||
|
||
exports.down = function (knex) { | ||
return knex.schema.alterTable("monitor", function (table) { | ||
table.dropColumn("rabbitmq_nodes"); | ||
table.dropColumn("rabbitmq_username"); | ||
table.dropColumn("rabbitmq_password"); | ||
}); | ||
|
||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
const { MonitorType } = require("./monitor-type"); | ||
const { log, UP, DOWN } = require("../../src/util"); | ||
const { axiosAbortSignal } = require("../util-server"); | ||
const axios = require("axios"); | ||
|
||
class RabbitMqMonitorType extends MonitorType { | ||
name = "rabbitmq"; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
async check(monitor, heartbeat, server) { | ||
let baseUrls = []; | ||
try { | ||
baseUrls = JSON.parse(monitor.rabbitmqNodes); | ||
} catch (error) { | ||
throw new Error("Invalid RabbitMQ Nodes"); | ||
} | ||
|
||
heartbeat.status = DOWN; | ||
for (let baseUrl of baseUrls) { | ||
try { | ||
// Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com | ||
if ( !baseUrl.endsWith("/") ) { | ||
baseUrl += "/"; | ||
} | ||
const options = { | ||
// Do not start with slash, it will strip the trailing slash from baseUrl | ||
url: new URL("api/health/checks/alarms/", baseUrl).href, | ||
method: "get", | ||
timeout: monitor.timeout * 1000, | ||
headers: { | ||
"Accept": "application/json", | ||
"Authorization": "Basic " + Buffer.from(`${monitor.rabbitmqUsername || ""}:${monitor.rabbitmqPassword || ""}`).toString("base64"), | ||
}, | ||
signal: axiosAbortSignal((monitor.timeout + 10) * 1000), | ||
// Capture reason for 503 status | ||
validateStatus: (status) => status === 200 || status === 503, | ||
}; | ||
log.debug("monitor", `[${monitor.name}] Axios Request: ${JSON.stringify(options)}`); | ||
const res = await axios.request(options); | ||
log.debug("monitor", `[${monitor.name}] Axios Response: status=${res.status} body=${JSON.stringify(res.data)}`); | ||
if (res.status === 200) { | ||
heartbeat.status = UP; | ||
heartbeat.msg = "OK"; | ||
break; | ||
} else if (res.status === 503) { | ||
heartbeat.msg = res.data.reason; | ||
} else { | ||
heartbeat.msg = `${res.status} - ${res.statusText}`; | ||
} | ||
} catch (error) { | ||
if (axios.isCancel(error)) { | ||
heartbeat.msg = "Request timed out"; | ||
log.debug("monitor", `[${monitor.name}] Request timed out`); | ||
} else { | ||
log.debug("monitor", `[${monitor.name}] Axios Error: ${JSON.stringify(error.message)}`); | ||
heartbeat.msg = error.message; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
module.exports = { | ||
RabbitMqMonitorType, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const { describe, test } = require("node:test"); | ||
const assert = require("node:assert"); | ||
const { RabbitMQContainer } = require("@testcontainers/rabbitmq"); | ||
const { RabbitMqMonitorType } = require("../../server/monitor-types/rabbitmq"); | ||
const { UP, DOWN, PENDING } = require("../../src/util"); | ||
|
||
describe("RabbitMQ Single Node", { | ||
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"), | ||
}, () => { | ||
test("RabbitMQ is running", async () => { | ||
// The default timeout of 30 seconds might not be enough for the container to start | ||
const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start(); | ||
const rabbitMQMonitor = new RabbitMqMonitorType(); | ||
const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`; | ||
|
||
const monitor = { | ||
rabbitmqNodes: JSON.stringify([ connectionString ]), | ||
rabbitmqUsername: "guest", | ||
|
||
rabbitmqPassword: "guest", | ||
|
||
}; | ||
|
||
const heartbeat = { | ||
msg: "", | ||
status: PENDING, | ||
}; | ||
|
||
try { | ||
await rabbitMQMonitor.check(monitor, heartbeat, {}); | ||
assert.strictEqual(heartbeat.status, UP); | ||
assert.strictEqual(heartbeat.msg, "OK"); | ||
} finally { | ||
rabbitMQContainer.stop(); | ||
} | ||
}); | ||
|
||
test("RabbitMQ is not running", async () => { | ||
const rabbitMQMonitor = new RabbitMqMonitorType(); | ||
const monitor = { | ||
rabbitmqNodes: JSON.stringify([ "http://localhost:15672" ]), | ||
rabbitmqUsername: "rabbitmqUser", | ||
rabbitmqPassword: "rabbitmqPass", | ||
}; | ||
|
||
const heartbeat = { | ||
msg: "", | ||
status: PENDING, | ||
}; | ||
|
||
await rabbitMQMonitor.check(monitor, heartbeat, {}); | ||
assert.strictEqual(heartbeat.status, DOWN); | ||
CommanderStorm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
|
||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that this test blocked local testing on my Windows machine. It is also not able to run on a self-hosted X64 debian actions runner. What is the prerequisite to run this actually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the platform support for running docker containers in GHA without additional steps.
=> This is not about the actual test case, but rather it's environment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It assumes that docker is running on the system. AFAIK by default it searches for a unix socket at
unix:///var/run/docker.sock
in linux or a named pipe atnpipe:////./pipe/docker_engine
in windows.On the debian machine, is the test skipped or does it throw an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full log:
https://github.com/louislam/uptime-kuma/actions/runs/11531916870/job/32103162510
Actually, I just realize the mqtt test has the same issue.
My actions runner on Debian indeed don't have Docker. Maybe that is the reason.