mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-21 22:59:07 +00:00
refactor: Add support for reportDataInDays and isReportEnabled in StatusPageSubscriberService
This commit is contained in:
parent
a145b346a4
commit
e654b65e71
@ -1,35 +1,47 @@
|
||||
|
||||
<%- include('cookie-banner') -%>
|
||||
<footer class="bg-white" aria-labelledby="footer-heading">
|
||||
<footer class="bg-white" aria-labelledby="footer-heading">
|
||||
<h2 id="footer-heading" class="sr-only">Footer</h2>
|
||||
<div class="mx-auto max-w-7xl px-6 pb-8 pt-16 sm:pt-24 lg:px-8 lg:pt-32">
|
||||
<div class="xl:grid xl:grid-cols-3 xl:gap-8">
|
||||
<div class="space-y-8">
|
||||
<img class="h-20 -ml-2 -mb-5 -mt-5" src="/img/logo-gray.svg" alt="OneUptime">
|
||||
<p class="text-sm leading-6 text-gray-600">OneUptime is the complete observability platform. OneUptime is open-source and always will be.</p>
|
||||
<p class="text-sm leading-6 text-gray-600">OneUptime is the complete observability platform. OneUptime is
|
||||
open-source and always will be.</p>
|
||||
<div class="flex space-x-6">
|
||||
|
||||
<a href="https://twitter.com/oneuptimehq" target="_blank" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">Twitter</span>
|
||||
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
|
||||
<a href="https://x.com/oneuptimehq" target="_blank" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">X</span>
|
||||
<svg class="h-5 w-5 mt-0.5" fill="currentColor" viewBox="0 0 220 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M173.263 0H206.998L133.297 84.718L220 200H152.112L98.9403 130.082L38.0995 200H4.34432L83.1743 109.385L0 0H69.6111L117.674 63.9077L173.263 0ZM161.423 179.692H180.116L59.4539 19.241H39.3946L161.423 179.692Z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/oneuptime" target="_blank" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">GitHub</span>
|
||||
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
<!-- <a href="#" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">YouTube</span>
|
||||
<a href="https://github.com/oneuptime" target="_blank" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">GitHub</span>
|
||||
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://www.reddit.com/r/oneuptimehq/" target="_blank" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">Reddit</span>
|
||||
<svg class="mt-0.5 h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M14.238 15.348c.085.084.085.221 0 .306-.465.462-1.194.687-2.231.687l-.008-.002-.008.002c-1.036 0-1.766-.225-2.231-.688-.085-.084-.085-.221 0-.305.084-.084.222-.084.307 0 .379.377 1.008.561 1.924.561l.008.002.008-.002c.915 0 1.544-.184 1.924-.561.085-.084.223-.084.307 0zm-3.44-2.418c0-.507-.414-.919-.922-.919-.509 0-.923.412-.923.919 0 .506.414.918.923.918.508.001.922-.411.922-.918zm13.202-.93c0 6.627-5.373 12-12 12s-12-5.373-12-12 5.373-12 12-12 12 5.373 12 12zm-5-.129c0-.851-.695-1.543-1.55-1.543-.417 0-.795.167-1.074.435-1.056-.695-2.485-1.137-4.066-1.194l.865-2.724 2.343.549-.003.034c0 .696.569 1.262 1.268 1.262.699 0 1.267-.566 1.267-1.262s-.568-1.262-1.267-1.262c-.537 0-.994.335-1.179.804l-2.525-.592c-.11-.027-.223.037-.257.145l-.965 3.038c-1.656.02-3.155.466-4.258 1.181-.277-.255-.644-.415-1.05-.415-.854.001-1.549.693-1.549 1.544 0 .566.311 1.056.768 1.325-.03.164-.05.331-.05.5 0 2.281 2.805 4.137 6.253 4.137s6.253-1.856 6.253-4.137c0-.16-.017-.317-.044-.472.486-.261.82-.766.82-1.353zm-4.872.141c-.509 0-.922.412-.922.919 0 .506.414.918.922.918s.922-.412.922-.918c0-.507-.413-.919-.922-.919z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://www.youtube.com/@OneUptimeHQ" class="text-gray-400 hover:text-gray-500">
|
||||
<span class="sr-only">YouTube</span>
|
||||
<svg class="h-7 w-7 -mt-0.5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M19.812 5.418c.861.23 1.538.907 1.768 1.768C21.998 8.746 22 12 22 12s0 3.255-.418 4.814a2.504 2.504 0 0 1-1.768 1.768c-1.56.419-7.814.419-7.814.419s-6.255 0-7.814-.419a2.505 2.505 0 0 1-1.768-1.768C2 15.255 2 12 2 12s0-3.255.417-4.814a2.507 2.507 0 0 1 1.768-1.768C5.744 5 11.998 5 11.998 5s6.255 0 7.814.418ZM15.194 12 10 15V9l5.194 3Z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a> -->
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-16 grid grid-cols-2 gap-8 xl:col-span-2 xl:mt-0">
|
||||
@ -38,19 +50,23 @@
|
||||
<h3 class="text-sm font-semibold leading-6 text-gray-900">Products</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li>
|
||||
<a href="/product/status-page" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Status Page</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/product/incident-management" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Incident Management</a>
|
||||
<a href="/product/status-page" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Status
|
||||
Page</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/product/monitoring" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Monitoring</a>
|
||||
<a href="/product/incident-management"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">Incident Management</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/product/on-call" class="text-sm leading-6 text-gray-600 hover:text-gray-900">On-Call and Alerts</a>
|
||||
<a href="/product/monitoring"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">Monitoring</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/product/on-call" class="text-sm leading-6 text-gray-600 hover:text-gray-900">On-Call and
|
||||
Alerts</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
@ -64,13 +80,15 @@
|
||||
<h3 class="text-sm font-semibold leading-6 text-gray-900">Enterprise</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li>
|
||||
<a href="/enterprise/overview" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Overview</a>
|
||||
<a href="/enterprise/overview"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">Overview</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="/enterprise/demo" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Request Demo</a>
|
||||
<a href="/enterprise/demo" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Request
|
||||
Demo</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -79,10 +97,12 @@
|
||||
<h3 class="text-sm font-semibold leading-6 text-gray-900">Compare</h3>
|
||||
<ul role="list" class="mt-6 space-y-4">
|
||||
<li>
|
||||
<a href="/compare/statuspage.io" class="text-sm leading-6 text-gray-600 hover:text-gray-900">StatusPage.io</a>
|
||||
<a href="/compare/statuspage.io"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">StatusPage.io</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/compare/incident.io" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Incident.io</a>
|
||||
<a href="/compare/incident.io"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">Incident.io</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/compare/pagerduty" class="text-sm leading-6 text-gray-600 hover:text-gray-900">PagerDuty</a>
|
||||
@ -108,13 +128,14 @@
|
||||
<li>
|
||||
<a href="/support" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Help and Support</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="/legal" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Legal Center</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="text-sm leading-6 text-gray-600 hover:text-gray-900">GitHub</a>
|
||||
<a href="https://github.com/oneuptime/oneuptime" target="_blank"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">GitHub</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
@ -122,12 +143,13 @@
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/OneUptime/interview" class="text-sm leading-6 text-gray-600 hover:text-gray-900">Careers</a>
|
||||
<a target="_blank" href="https://github.com/OneUptime/interview"
|
||||
class="text-sm leading-6 text-gray-600 hover:text-gray-900">Careers</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/about" class="text-sm leading-6 text-gray-600 hover:text-gray-900">About Us</a>
|
||||
</li>
|
||||
<a href="/about" class="text-sm leading-6 text-gray-600 hover:text-gray-900">About Us</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -141,13 +163,15 @@
|
||||
<div class="flex items-center gap-x-6 bg-gray-700 px-6 py-2.5 sm:px-3.5 sm:before:flex-1">
|
||||
<p class="text-sm leading-6 text-white">
|
||||
<a href="https://github.com/oneuptime/interview" target="blank">
|
||||
<strong class="font-semibold">We're hiring remotely, worldwide! </strong><svg viewBox="0 0 2 2" class="mx-2 inline h-0.5 w-0.5 fill-current" aria-hidden="true"><circle cx="1" cy="1" r="1" /></svg>See open roles <span aria-hidden="true">→</span>
|
||||
<strong class="font-semibold">We're hiring remotely, worldwide! </strong><svg viewBox="0 0 2 2"
|
||||
class="mx-2 inline h-0.5 w-0.5 fill-current" aria-hidden="true">
|
||||
<circle cx="1" cy="1" r="1" />
|
||||
</svg>See open roles <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
</p>
|
||||
<div class="flex flex-1 justify-end">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</footer>
|
||||
|
||||
|
||||
</footer>
|
@ -7,7 +7,6 @@ import IncidentStateTimelineService from "../Services/IncidentStateTimelineServi
|
||||
import MonitorGroupResourceService from "../Services/MonitorGroupResourceService";
|
||||
import MonitorGroupService from "../Services/MonitorGroupService";
|
||||
import MonitorStatusService from "../Services/MonitorStatusService";
|
||||
import MonitorStatusTimelineService from "../Services/MonitorStatusTimelineService";
|
||||
import ScheduledMaintenancePublicNoteService from "../Services/ScheduledMaintenancePublicNoteService";
|
||||
import ScheduledMaintenanceService from "../Services/ScheduledMaintenanceService";
|
||||
import ScheduledMaintenanceStateService from "../Services/ScheduledMaintenanceStateService";
|
||||
@ -40,7 +39,7 @@ import BaseModel from "Common/Models/BaseModel";
|
||||
import ArrayUtil from "Common/Types/ArrayUtil";
|
||||
import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
|
||||
import SortOrder from "Common/Types/BaseDatabase/SortOrder";
|
||||
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
|
||||
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
|
||||
import OneUptimeDate from "Common/Types/Date";
|
||||
import Dictionary from "Common/Types/Dictionary";
|
||||
import Email from "Common/Types/Email";
|
||||
@ -170,7 +169,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
);
|
||||
|
||||
await StatusPageService.sendEmailReport({
|
||||
emails: [email],
|
||||
email: email,
|
||||
statusPageId,
|
||||
});
|
||||
|
||||
@ -462,9 +461,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
?.toString()}/overview/:statusPageId`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
const startDate: Date = OneUptimeDate.getSomeDaysAgo(90);
|
||||
const endDate: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
try {
|
||||
const objectId: ObjectID = new ObjectID(
|
||||
req.params["statusPageId"] as string,
|
||||
@ -697,75 +693,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
monitorsInGroup[monitorGroupId.toString()] = monitorsInGroupIds;
|
||||
}
|
||||
|
||||
let monitorStatusTimelines: Array<MonitorStatusTimeline> = [];
|
||||
|
||||
if (monitorsOnStatusPageForTimeline.length > 0) {
|
||||
monitorStatusTimelines = await MonitorStatusTimelineService.findBy({
|
||||
query: {
|
||||
monitorId: QueryHelper.any(monitorsOnStatusPageForTimeline),
|
||||
endsAt: QueryHelper.inBetween(startDate, endDate),
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
createdAt: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
monitorStatus: {
|
||||
name: true,
|
||||
color: true,
|
||||
priority: true,
|
||||
} as any,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX, // This can be optimized.
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
const monitorStatusTimelines: Array<MonitorStatusTimeline> =
|
||||
await StatusPageService.getMonitorStatusTimelineForStatusPage({
|
||||
monitorIds: monitorsOnStatusPageForTimeline,
|
||||
historyDays: 90,
|
||||
});
|
||||
|
||||
monitorStatusTimelines = monitorStatusTimelines.concat(
|
||||
await MonitorStatusTimelineService.findBy({
|
||||
query: {
|
||||
monitorId: QueryHelper.any(monitorsOnStatusPageForTimeline),
|
||||
endsAt: QueryHelper.isNull(),
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
createdAt: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
monitorStatus: {
|
||||
name: true,
|
||||
color: true,
|
||||
priority: true,
|
||||
} as any,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX, // This can be optimized.
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// sort monitorStatusTimelines by createdAt.
|
||||
monitorStatusTimelines = monitorStatusTimelines.sort(
|
||||
(a: MonitorStatusTimeline, b: MonitorStatusTimeline) => {
|
||||
if (!a.createdAt || !b.createdAt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return b.createdAt!.getTime() - a.createdAt!.getTime();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// check if status page has active incident.
|
||||
let activeIncidents: Array<Incident> = [];
|
||||
if (monitorsOnStatusPage.length > 0) {
|
||||
@ -1114,7 +1047,9 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
incidentPublicNotes,
|
||||
IncidentPublicNote,
|
||||
),
|
||||
|
||||
activeIncidents: BaseModel.toJSONArray(activeIncidents, Incident),
|
||||
|
||||
monitorStatusTimelines: BaseModel.toJSONArray(
|
||||
monitorStatusTimelines,
|
||||
MonitorStatusTimeline,
|
||||
@ -1400,28 +1335,8 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
// get monitors on status page.
|
||||
const statusPageResources: Array<StatusPageResource> =
|
||||
await StatusPageResourceService.findBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
statusPageGroupId: true,
|
||||
monitorId: true,
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
monitorGroupId: true,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
await StatusPageService.getStatusPageResources({
|
||||
statusPageId: statusPageId,
|
||||
});
|
||||
|
||||
// check if status page has active scheduled events.
|
||||
@ -2062,91 +1977,17 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
// get monitors on status page.
|
||||
const statusPageResources: Array<StatusPageResource> =
|
||||
await StatusPageResourceService.findBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
statusPageGroupId: true,
|
||||
monitorId: true,
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
monitorGroupId: true,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
await StatusPageService.getStatusPageResources({
|
||||
statusPageId: statusPageId,
|
||||
});
|
||||
|
||||
const monitorGroupIds: Array<ObjectID> = statusPageResources
|
||||
.map((resource: StatusPageResource) => {
|
||||
return resource.monitorGroupId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
const { monitorsOnStatusPage, monitorsInGroup } =
|
||||
await StatusPageService.getMonitorIdsOnStatusPage({
|
||||
statusPageId: statusPageId,
|
||||
});
|
||||
|
||||
const monitorsInGroup: Dictionary<Array<ObjectID>> = {};
|
||||
|
||||
// get monitor status charts.
|
||||
const monitorsOnStatusPage: Array<ObjectID> = statusPageResources
|
||||
.map((monitor: StatusPageResource) => {
|
||||
return monitor.monitorId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
});
|
||||
|
||||
for (const monitorGroupId of monitorGroupIds) {
|
||||
// get current status of monitors in the group.
|
||||
|
||||
// get monitors in the group.
|
||||
|
||||
const groupResources: Array<MonitorGroupResource> =
|
||||
await MonitorGroupResourceService.findBy({
|
||||
query: {
|
||||
monitorGroupId: monitorGroupId,
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
});
|
||||
|
||||
const monitorsInGroupIds: Array<ObjectID> = groupResources
|
||||
.map((resource: MonitorGroupResource) => {
|
||||
return resource.monitorId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
});
|
||||
|
||||
for (const monitorId of monitorsInGroupIds) {
|
||||
if (
|
||||
!monitorsOnStatusPage.find((item: ObjectID) => {
|
||||
return item.toString() === monitorId.toString();
|
||||
})
|
||||
) {
|
||||
monitorsOnStatusPage.push(monitorId);
|
||||
}
|
||||
}
|
||||
|
||||
monitorsInGroup[monitorGroupId.toString()] = monitorsInGroupIds;
|
||||
}
|
||||
|
||||
const today: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
const historyDays: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
statusPage.showIncidentHistoryInDays || 14,
|
||||
);
|
||||
|
@ -34,6 +34,7 @@ import { MigrationName1721075917289 } from "./1721075917289-MigrationName";
|
||||
import { MigrationName1721152139648 } from "./1721152139648-MigrationName";
|
||||
import { MigrationName1721159743714 } from "./1721159743714-MigrationName";
|
||||
import { MigrationName1721754545771 } from "./1721754545771-MigrationName";
|
||||
import { MigrationName1721779190475 } from "./1721779190475-MigrationName";
|
||||
|
||||
export default [
|
||||
InitialMigration,
|
||||
@ -72,5 +73,5 @@ export default [
|
||||
MigrationName1721152139648,
|
||||
MigrationName1721159743714,
|
||||
MigrationName1721754545771,
|
||||
MigrationName1717839110671,
|
||||
MigrationName1721779190475,
|
||||
];
|
||||
|
@ -19,7 +19,7 @@ import Protocol from "Common/Types/API/Protocol";
|
||||
import URL from "Common/Types/API/URL";
|
||||
import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
|
||||
import { Green } from "Common/Types/BrandColors";
|
||||
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
|
||||
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
|
||||
import BadDataException from "Common/Types/Exception/BadDataException";
|
||||
import JSONWebTokenData from "Common/Types/JsonWebTokenData";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
@ -44,6 +44,32 @@ import MailService from "./MailService";
|
||||
import EmailTemplateType from "Common/Types/Email/EmailTemplateType";
|
||||
import { FileRoute } from "Common/ServiceRoute";
|
||||
import ProjectSMTPConfigService from "./ProjectSmtpConfigService";
|
||||
import StatusPageResource from "Model/Models/StatusPageResource";
|
||||
import StatusPageResourceService from "./StatusPageResourceService";
|
||||
import Dictionary from "Common/Types/Dictionary";
|
||||
import MonitorGroupResource from "Model/Models/MonitorGroupResource";
|
||||
import MonitorGroupResourceService from "./MonitorGroupResourceService";
|
||||
import QueryHelper from "../Types/Database/QueryHelper";
|
||||
import OneUptimeDate from "Common/Types/Date";
|
||||
import IncidentService from "./IncidentService";
|
||||
import MonitorStatusTimeline from "Model/Models/MonitorStatusTimeline";
|
||||
import MonitorStatusTimelineService from "./MonitorStatusTimelineService";
|
||||
import SortOrder from "Common/Types/BaseDatabase/SortOrder";
|
||||
|
||||
export interface StatusPageReportItem {
|
||||
resourceName: string;
|
||||
totalIncidents: number;
|
||||
uptimePercent: number;
|
||||
downtimeInMinutes: number;
|
||||
}
|
||||
|
||||
export interface StatusPageReport {
|
||||
totalResources: number;
|
||||
totalIncidents: number;
|
||||
averageUptimePercent: number;
|
||||
totalDowntimeInMinutes: number;
|
||||
resources: Array<StatusPageReportItem>;
|
||||
}
|
||||
|
||||
export class Service extends DatabaseService<StatusPage> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
@ -343,6 +369,87 @@ export class Service extends DatabaseService<StatusPage> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async getMonitorStatusTimelineForStatusPage(data: {
|
||||
monitorIds: Array<ObjectID>;
|
||||
historyDays: number;
|
||||
}): Promise<Array<MonitorStatusTimeline>> {
|
||||
const startDate: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
data.historyDays || 14,
|
||||
);
|
||||
const endDate: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
let monitorStatusTimelines: Array<MonitorStatusTimeline> = [];
|
||||
|
||||
if (data.monitorIds.length > 0) {
|
||||
monitorStatusTimelines = await MonitorStatusTimelineService.findBy({
|
||||
query: {
|
||||
monitorId: QueryHelper.any(data.monitorIds),
|
||||
endsAt: QueryHelper.inBetween(startDate, endDate),
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
createdAt: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
monitorStatus: {
|
||||
name: true,
|
||||
color: true,
|
||||
priority: true,
|
||||
} as any,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX, // This can be optimized.
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
monitorStatusTimelines = monitorStatusTimelines.concat(
|
||||
await MonitorStatusTimelineService.findBy({
|
||||
query: {
|
||||
monitorId: QueryHelper.any(data.monitorIds),
|
||||
endsAt: QueryHelper.isNull(),
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
createdAt: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
monitorStatus: {
|
||||
name: true,
|
||||
color: true,
|
||||
priority: true,
|
||||
} as any,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX, // This can be optimized.
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// sort monitorStatusTimelines by createdAt.
|
||||
monitorStatusTimelines = monitorStatusTimelines.sort(
|
||||
(a: MonitorStatusTimeline, b: MonitorStatusTimeline) => {
|
||||
if (!a.createdAt || !b.createdAt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return b.createdAt!.getTime() - a.createdAt!.getTime();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return monitorStatusTimelines;
|
||||
}
|
||||
|
||||
public async getStatusPageURL(statusPageId: ObjectID): Promise<string> {
|
||||
const domains: Array<StatusPageDomain> =
|
||||
await StatusPageDomainService.findBy({
|
||||
@ -614,5 +721,169 @@ export class Service extends DatabaseService<StatusPage> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async getReportByStatusPage(_data: {
|
||||
statusPageId: ObjectID;
|
||||
historyDays: number;
|
||||
}): Promise<StatusPageReport> {
|
||||
// const statusPageResources = await this.getStatusPageResources({
|
||||
// statusPageId: data.statusPageId,
|
||||
// });
|
||||
|
||||
// const incidentCount: number = await this.getIncidentCountOnStatusPage({
|
||||
// statusPageId: data.statusPageId,
|
||||
// historyDays: data.historyDays,
|
||||
// });
|
||||
|
||||
// const monitors = await this.getMonitorIdsOnStatusPage({
|
||||
// statusPageId: data.statusPageId,
|
||||
// });
|
||||
|
||||
// const _timeline: Array<MonitorStatusTimeline> = await this.getMonitorStatusTimelineForStatusPage({
|
||||
// monitorIds: monitors.monitorsOnStatusPage,
|
||||
// historyDays: data.historyDays,
|
||||
// });
|
||||
|
||||
throw new BadDataException("Not implemented");
|
||||
|
||||
// return {
|
||||
// totalResources: statusPageResources.length,
|
||||
// totalIncidents: incidentCount,
|
||||
// }
|
||||
}
|
||||
|
||||
public async getIncidentCountOnStatusPage(data: {
|
||||
statusPageId: ObjectID;
|
||||
historyDays: number;
|
||||
}): Promise<number> {
|
||||
const monitorsOnStatusPage = await this.getMonitorIdsOnStatusPage({
|
||||
statusPageId: data.statusPageId,
|
||||
});
|
||||
|
||||
const today: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
const historyDays: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
data.historyDays || 14,
|
||||
);
|
||||
|
||||
const incidentCount: PositiveNumber = await IncidentService.countBy({
|
||||
query: {
|
||||
monitors: monitorsOnStatusPage.monitorsOnStatusPage as any,
|
||||
createdAt: QueryHelper.inBetween(historyDays, today),
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return incidentCount.toNumber();
|
||||
}
|
||||
|
||||
public async getMonitorIdsOnStatusPage(data: {
|
||||
statusPageId: ObjectID;
|
||||
}): Promise<{
|
||||
monitorsOnStatusPage: Array<ObjectID>;
|
||||
monitorsInGroup: Dictionary<Array<ObjectID>>;
|
||||
}> {
|
||||
const statusPageResources: Array<StatusPageResource> =
|
||||
await this.getStatusPageResources(data);
|
||||
|
||||
const monitorGroupIds: Array<ObjectID> = statusPageResources
|
||||
.map((resource: StatusPageResource) => {
|
||||
return resource.monitorGroupId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
});
|
||||
|
||||
const monitorsInGroup: Dictionary<Array<ObjectID>> = {};
|
||||
|
||||
// get monitor status charts.
|
||||
const monitorsOnStatusPage: Array<ObjectID> = statusPageResources
|
||||
.map((monitor: StatusPageResource) => {
|
||||
return monitor.monitorId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
});
|
||||
|
||||
for (const monitorGroupId of monitorGroupIds) {
|
||||
// get current status of monitors in the group.
|
||||
|
||||
// get monitors in the group.
|
||||
|
||||
const groupResources: Array<MonitorGroupResource> =
|
||||
await MonitorGroupResourceService.findBy({
|
||||
query: {
|
||||
monitorGroupId: monitorGroupId,
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
});
|
||||
|
||||
const monitorsInGroupIds: Array<ObjectID> = groupResources
|
||||
.map((resource: MonitorGroupResource) => {
|
||||
return resource.monitorId!;
|
||||
})
|
||||
.filter((id: ObjectID) => {
|
||||
return Boolean(id); // remove nulls
|
||||
});
|
||||
|
||||
for (const monitorId of monitorsInGroupIds) {
|
||||
if (
|
||||
!monitorsOnStatusPage.find((item: ObjectID) => {
|
||||
return item.toString() === monitorId.toString();
|
||||
})
|
||||
) {
|
||||
monitorsOnStatusPage.push(monitorId);
|
||||
}
|
||||
}
|
||||
|
||||
monitorsInGroup[monitorGroupId.toString()] = monitorsInGroupIds;
|
||||
}
|
||||
|
||||
return {
|
||||
monitorsOnStatusPage: monitorsOnStatusPage,
|
||||
monitorsInGroup: monitorsInGroup,
|
||||
};
|
||||
}
|
||||
|
||||
public async getStatusPageResources(data: {
|
||||
statusPageId: ObjectID;
|
||||
}): Promise<Array<StatusPageResource>> {
|
||||
// get monitors on status page.
|
||||
const statusPageResources: Array<StatusPageResource> =
|
||||
await StatusPageResourceService.findBy({
|
||||
query: {
|
||||
statusPageId: data.statusPageId,
|
||||
},
|
||||
select: {
|
||||
statusPageGroupId: true,
|
||||
monitorId: true,
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
monitorGroupId: true,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return statusPageResources;
|
||||
}
|
||||
}
|
||||
export default new Service();
|
||||
|
@ -393,6 +393,8 @@ export class Service extends DatabaseService<Model> {
|
||||
twilioPhoneNumber: true,
|
||||
},
|
||||
subscriberTimezones: true,
|
||||
reportDataInDays: true,
|
||||
isReportEnabled: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -52,16 +52,16 @@ spec:
|
||||
path: /status/live
|
||||
port: {{ $.Values.port.ingestor }}
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 30
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 60
|
||||
# Readyness Probe
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /status/ready
|
||||
port: {{ $.Values.port.ingestor }}
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 30
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 60
|
||||
{{- if $.Values.containerSecurityContext }}
|
||||
securityContext: {{- $.Values.containerSecurityContext | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
|
Loading…
Reference in New Issue
Block a user