Feat: Add http/http keyword timeout option (#2142)
* feat: Add timeoutMs field
* chore: Update Languages (incl. ko-KR)
* Revert "chore: Update Languages (incl. ko-KR)"
This reverts commit 349331a00b
.
* chore: Update ko-KR selectively
* chore: Update en selectively
* Merge manually
* Reorder and show only if http related monitors
* fix: Update Korean translation
* fix: Rename timeoutMs to timeout, rename label, make DOUBLE
* fix: Change minimum step to 0.1, matching DOUBLE type
* Put the sql patch at the end
* Update EditMonitor.vue
* Colocate timeout with retry, fix clampTimeout logic, show default on 0
* Update src/pages/EditMonitor.vue to remove a comment
Co-authored-by: Frank Elsinga <frank@elsinga.de>
* Fix merge issue
* Update the timeout value while finished editing the interval value
---------
Co-authored-by: Louis Lam <louislam@users.noreply.github.com>
Co-authored-by: Frank Elsinga <frank@elsinga.de>
This commit is contained in:
parent
c6e68fac97
commit
439b6517d1
|
@ -0,0 +1,6 @@
|
|||
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE monitor
|
||||
ADD timeout DOUBLE default 0 not null;
|
||||
COMMIT;
|
|
@ -79,6 +79,7 @@ class Database {
|
|||
"patch-added-kafka-producer.sql": true,
|
||||
"patch-add-certificate-expiry-status-page.sql": true,
|
||||
"patch-monitor-oauth-cc.sql": true,
|
||||
"patch-add-timeout-monitor.sql": true,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -102,6 +102,7 @@ class Monitor extends BeanModel {
|
|||
active: await this.isActive(),
|
||||
forceInactive: !await Monitor.isParentActive(this.id),
|
||||
type: this.type,
|
||||
timeout: this.timeout,
|
||||
interval: this.interval,
|
||||
retryInterval: this.retryInterval,
|
||||
resendInterval: this.resendInterval,
|
||||
|
@ -428,7 +429,7 @@ class Monitor extends BeanModel {
|
|||
const options = {
|
||||
url: this.url,
|
||||
method: (this.method || "get").toLowerCase(),
|
||||
timeout: this.interval * 1000 * 0.8,
|
||||
timeout: this.timeout,
|
||||
headers: {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"User-Agent": "Uptime-Kuma/" + version,
|
||||
|
@ -648,7 +649,7 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
|
||||
let res = await axios.get(steamApiUrl, {
|
||||
timeout: this.interval * 1000 * 0.8,
|
||||
timeout: this.timeout,
|
||||
headers: {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": "Uptime-Kuma/" + version,
|
||||
|
|
|
@ -716,6 +716,7 @@ let needSetup = false;
|
|||
bean.headers = monitor.headers;
|
||||
bean.basic_auth_user = monitor.basic_auth_user;
|
||||
bean.basic_auth_pass = monitor.basic_auth_pass;
|
||||
bean.timeout = monitor.timeout;
|
||||
bean.oauth_client_id = monitor.oauth_client_id,
|
||||
bean.oauth_client_secret = monitor.oauth_client_secret,
|
||||
bean.oauth_auth_method = this.oauth_auth_method,
|
||||
|
@ -1372,6 +1373,7 @@ let needSetup = false;
|
|||
|
||||
// Define default values
|
||||
let retryInterval = 0;
|
||||
let timeout = monitorListData[i].timeout || (monitorListData[i].interval * 0.8); // fallback to old value
|
||||
|
||||
/*
|
||||
Only replace the default value with the backup file data for the specific version, where it appears the first time
|
||||
|
@ -1397,6 +1399,7 @@ let needSetup = false;
|
|||
basic_auth_pass: monitorListData[i].basic_auth_pass,
|
||||
authWorkstation: monitorListData[i].authWorkstation,
|
||||
authDomain: monitorListData[i].authDomain,
|
||||
timeout,
|
||||
interval: monitorListData[i].interval,
|
||||
retryInterval: retryInterval,
|
||||
resendInterval: monitorListData[i].resendInterval || 0,
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
"Hostname": "Hostname",
|
||||
"Port": "Port",
|
||||
"Heartbeat Interval": "Heartbeat Interval",
|
||||
"Request Timeout": "Request Timeout",
|
||||
"timeoutAfter": "Timeout after {0} seconds",
|
||||
"Retries": "Retries",
|
||||
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
||||
"Resend Notification if Down X times consecutively": "Resend Notification if Down X times consecutively",
|
||||
|
|
|
@ -589,6 +589,8 @@
|
|||
"RadiusCalledStationIdDescription": "접속 스테이션의 식별자",
|
||||
"RadiusCallingStationId": "접속 요청 스테이션의 Id",
|
||||
"RadiusCallingStationIdDescription": "접속 요청 스테이션의 식별자",
|
||||
"timeoutAfter": "{0}초 후 타임아웃",
|
||||
"Request Timeout": "요청 타임아웃",
|
||||
"Query": "쿼리",
|
||||
"settingsCertificateExpiry": "TLS 인증서 만료",
|
||||
"certificationExpiryDescription": "HTTPS 모니터링 TLS 인증서가 만료되면 알림을 활성화해요:",
|
||||
|
|
|
@ -393,7 +393,7 @@
|
|||
<!-- Interval -->
|
||||
<div class="my-3">
|
||||
<label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label>
|
||||
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required :min="minInterval" step="1" :max="maxInterval">
|
||||
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required :min="minInterval" step="1" :max="maxInterval" @blur="finishUpdateInterval">
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
|
@ -412,6 +412,12 @@
|
|||
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required :min="minInterval" step="1">
|
||||
</div>
|
||||
|
||||
<!-- Timeout: HTTP / Keyword only -->
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword'" class="my-3">
|
||||
<label for="timeout" class="form-label">{{ $t("Request Timeout") }} ({{ $t("timeoutAfter", [ monitor.timeout || clampTimeout(monitor.interval) ]) }})</label>
|
||||
<input id="timeout" v-model="monitor.timeout" type="number" class="form-control" required min="0" step="0.1">
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<label for="resend-interval" class="form-label">
|
||||
{{ $t("Resend Notification if Down X times consecutively") }}
|
||||
|
@ -840,6 +846,7 @@ const monitorDefaults = {
|
|||
retryInterval: 60,
|
||||
resendInterval: 0,
|
||||
maxretries: 1,
|
||||
timeout: 48,
|
||||
notificationIDList: {},
|
||||
ignoreTls: false,
|
||||
upsideDown: false,
|
||||
|
@ -1113,6 +1120,13 @@ message HealthCheckResponse {
|
|||
}
|
||||
},
|
||||
|
||||
"monitor.timeout"(value, oldValue) {
|
||||
// keep timeout within 80% range
|
||||
if (value && value !== oldValue) {
|
||||
this.monitor.timeout = this.clampTimeout(value);
|
||||
}
|
||||
},
|
||||
|
||||
"monitor.type"() {
|
||||
if (this.monitor.type === "push") {
|
||||
if (! this.monitor.pushToken) {
|
||||
|
@ -1274,6 +1288,10 @@ message HealthCheckResponse {
|
|||
if (this.monitor.retryInterval === 0) {
|
||||
this.monitor.retryInterval = this.monitor.interval;
|
||||
}
|
||||
// Handling for monitors that are missing/zeroed timeout
|
||||
if (!this.monitor.timeout) {
|
||||
this.monitor.timeout = ~~(this.monitor.interval * 8) / 10;
|
||||
}
|
||||
} else {
|
||||
toast.error(res.msg);
|
||||
}
|
||||
|
@ -1445,8 +1463,27 @@ message HealthCheckResponse {
|
|||
addedDraftGroup(draftGroupName) {
|
||||
this.draftGroupName = draftGroupName;
|
||||
this.monitor.parent = -1;
|
||||
},
|
||||
|
||||
// Clamp timeout
|
||||
clampTimeout(timeout) {
|
||||
// limit to 80% of interval, narrowly avoiding epsilon bug
|
||||
const maxTimeout = ~~(this.monitor.interval * 8 ) / 10;
|
||||
const clamped = Math.max(0, Math.min(timeout, maxTimeout));
|
||||
|
||||
// 0 will be treated as 80% of interval
|
||||
return Number.isFinite(clamped) ? clamped : maxTimeout;
|
||||
},
|
||||
|
||||
finishUpdateInterval() {
|
||||
// Update timeout if it is greater than the clamp timeout
|
||||
let clampedValue = this.clampTimeout(this.monitor.interval);
|
||||
if (this.monitor.timeout > clampedValue) {
|
||||
this.monitor.timeout = clampedValue;
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue