Skip to content
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 uptime of system #12

Merged
merged 4 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ let package = Package(
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "AppHealthChecks",
targets: ["AppHealthChecks"])
name: "HealthChecks",
targets: ["HealthChecks"])
],
dependencies: [
// 💧 A server-side Swift web framework.
Expand All @@ -26,15 +26,15 @@ let package = Package(
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "AppHealthChecks",
name: "HealthChecks",
dependencies: [
.product(name: "Vapor", package: "vapor"),
.product(name: "Fluent", package: "fluent"),
.product(name: "FluentPostgresDriver", package: "fluent-postgres-driver")
]
),
.testTarget(
name: "AppHealthChecksTests",
dependencies: ["AppHealthChecks"])
name: "HealthChecksTests",
dependencies: ["HealthChecks"])
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// FS App Health Checks
// Copyright (C) 2024 FREEDOM SPACE, LLC

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// ApplicationChecksProtocol.swift
//
//
// Created by Mykola Buhaiov on 10.02.2024.
//

import Vapor

/// Groups func for get application health check
public protocol ApplicationChecksProtocol {
/// Get uptime of application
/// - Returns: `HealthCheckItem`
func uptime() -> HealthCheckItem
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// FS App Health Checks
// Copyright (C) 2024 FREEDOM SPACE, LLC

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// ApplicationHealthChecks.swift
//
//
// Created by Mykola Buhaiov on 10.02.2024.
//

import Vapor

/// Service that provides app health check functionality
public struct ApplicationHealthChecks: ApplicationHealthChecksProtocol {
/// Instance of app as `Application`
public let app: Application

/// Get uptime of system
/// - Returns: `HealthCheckItem`
public func uptime() -> HealthCheckItem {
let uptime = Date().timeIntervalSinceReferenceDate - app.launchTime
return HealthCheckItem(
componentType: .system,
observedValue: uptime,
observedUnit: "s",
status: .pass,
time: app.dateTimeISOFormat.string(from: Date())
)
}

Check warning on line 43 in Sources/HealthChecks/ApplicationHealthChecks/ApplicationHealthChecks.swift

View check run for this annotation

Codecov / codecov/patch

Sources/HealthChecks/ApplicationHealthChecks/ApplicationHealthChecks.swift#L34-L43

Added lines #L34 - L43 were not covered by tests

/// Check with setup options
/// - Parameter options: array of `MeasurementType`
/// - Returns: dictionary `[String: HealthCheckItem]`
public func checkHealth(for options: [MeasurementType]) async -> [String: HealthCheckItem] {
var result = ["": HealthCheckItem()]
let measurementTypes = Array(Set(options))
for type in measurementTypes {
switch type {
case .uptime:
result["\(MeasurementType.uptime)"] = uptime()
default:
break
}
}
return result
}

Check warning on line 60 in Sources/HealthChecks/ApplicationHealthChecks/ApplicationHealthChecks.swift

View check run for this annotation

Codecov / codecov/patch

Sources/HealthChecks/ApplicationHealthChecks/ApplicationHealthChecks.swift#L48-L60

Added lines #L48 - L60 were not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// FS App Health Checks
// Copyright (C) 2024 FREEDOM SPACE, LLC

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// ApplicationHealthChecksProtocol.swift
//
//
// Created by Mykola Buhaiov on 10.02.2024.
//

import Vapor

/// Groups func for get application health check
public protocol ApplicationHealthChecksProtocol: ApplicationChecksProtocol, ChecksProtocol {}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@
get { storage[PsqlIdKey.self] }
set { storage[PsqlIdKey.self] = newValue }
}

/// A `launchTimeKey` conform to StorageKey protocol
private struct LaunchTimeKey: StorageKey {
/// Less verbose typealias for `Double`.
typealias Value = Double
}

/// Setup `launchTimeKey` in application storage
public var launchTime: Double {
get { storage[LaunchTimeKey.self] ?? Date().timeIntervalSinceReferenceDate }

Check warning on line 73 in Sources/HealthChecks/Extensions/Application+Extensions.swift

View check run for this annotation

Codecov / codecov/patch

Sources/HealthChecks/Extensions/Application+Extensions.swift#L73

Added line #L73 was not covered by tests
set { storage[LaunchTimeKey.self] = newValue }
}
}

extension Application {
Expand Down Expand Up @@ -101,6 +113,18 @@
get { storage[ConsulHealthChecksKey.self] }
set { storage[ConsulHealthChecksKey.self] = newValue }
}

/// A `ApplicationHealthChecksKey` conform to StorageKey protocol
public struct ApplicationHealthChecksKey: StorageKey {
/// Less verbose typealias for `ApplicationHealthChecksProtocol`.
public typealias Value = ApplicationHealthChecksProtocol
}

/// Setup `applicationHealthChecks` in application storage
public var applicationHealthChecks: ApplicationHealthChecksProtocol? {
get { storage[ApplicationHealthChecksKey.self] }
set { storage[ApplicationHealthChecksKey.self] = newValue }
}
}

extension Application {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// AppHealthChecks.swift
// HealthChecks.swift
//
//
// Created by Mykola Buhaiov on 30.01.2024.
Expand All @@ -25,7 +25,7 @@
import Vapor

/// Service that provides app health check functionality
public struct AppHealthChecks {
public struct HealthChecks {
/// Get app major version
/// - Parameter serverVersion: `String`
/// - Returns: `Int`
Expand Down
47 changes: 47 additions & 0 deletions Tests/HealthChecksTests/ApplicationHealthChecksTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// FS App Health Checks
// Copyright (C) 2024 FREEDOM SPACE, LLC

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// ApplicationHealthChecksTests.swift
//
//
// Created by Mykola Buhaiov on 10.02.2024.
//

import Vapor
import XCTest
@testable import HealthChecks

final class ApplicationHealthChecksTests: XCTestCase {
func testUptime() {
let app = Application(.testing)
defer { app.shutdown() }
app.applicationHealthChecks = ApplicationHealthChecksMock()
let response = app.applicationHealthChecks?.uptime()
XCTAssertEqual(response, ApplicationHealthChecksMock.healthCheckItem)
}

func testGetHealth() async {
let app = Application(.testing)
defer { app.shutdown() }
app.launchTime = Date().timeIntervalSinceReferenceDate
app.applicationHealthChecks = ApplicationHealthChecksMock()
let result = await app.applicationHealthChecks?.checkHealth(for: [MeasurementType.uptime])
let uptime = result?[MeasurementType.uptime.rawValue]
XCTAssertEqual(uptime, ApplicationHealthChecksMock.healthCheckItem)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import Vapor
import XCTest
@testable import AppHealthChecks
@testable import HealthChecks

final class ConsulHealthChecksTests: XCTestCase {
func testCheckHealth() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

import Vapor
import XCTest
@testable import AppHealthChecks
@testable import HealthChecks

final class HealthCheckItemTests: XCTestCase {
func testPublicKeyEquatable() {
func testHealthCheckItemEquatable() {
let firstHealthCheckItem = HealthCheckItem(
componentId: "adca7c3d-55f4-4ab3-a842-18b35f50cb0f",
componentType: .datastore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@

import Vapor
import XCTest
@testable import AppHealthChecks
@testable import HealthChecks

final class AppHealthChecksTests: XCTestCase {
final class HealthChecksTests: XCTestCase {
let serviceId = UUID()
let releaseId = "1.0.0"

func testGetMajorVersion() {
let app = Application(.testing)
defer { app.shutdown() }
let version = AppHealthChecks().getPublicVersion(from: releaseId)
let version = HealthChecks().getPublicVersion(from: releaseId)
XCTAssertEqual(version, "1")
}

Expand All @@ -42,7 +42,7 @@ final class AppHealthChecksTests: XCTestCase {
defer { app.shutdown() }
app.serviceId = serviceId
app.releaseId = releaseId
let response = AppHealthChecks().getHealth(from: app)
let response = HealthChecks().getHealth(from: app)
XCTAssertEqual(response.version, "1")
XCTAssertEqual(response.releaseId, releaseId)
XCTAssertEqual(response.serviceId, serviceId)
Expand Down
47 changes: 47 additions & 0 deletions Tests/HealthChecksTests/Mocks/ApplicationHealthChecksMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// FS App Health Checks
// Copyright (C) 2024 FREEDOM SPACE, LLC

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//
// ApplicationHealthChecksMock.swift
//
//
// Created by Mykola Buhaiov on 10.02.2024.
//

import Vapor
@testable import HealthChecks

public struct ApplicationHealthChecksMock: ApplicationHealthChecksProtocol {
static let healthCheckItem = HealthCheckItem(
componentType: .system,
observedValue: 1,
observedUnit: "s",
status: .pass,
time: "2024-02-01T11:11:59.364"
)

public func uptime() -> HealthCheckItem {
ApplicationHealthChecksMock.healthCheckItem
}

public func checkHealth(for options: [MeasurementType]) async -> [String: HealthCheckItem] {
let result = [
MeasurementType.uptime.rawValue: ApplicationHealthChecksMock.healthCheckItem
]
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
//

import Vapor
@testable import AppHealthChecks
@testable import HealthChecks

public struct ConsulHealthChecksMock: ConsulHealthChecksProtocol {
static let consulId = "adca7c3d-55f4-4ab3-a842-18b35f50cb0f"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
//

import Vapor
import FluentPostgresDriver
@testable import AppHealthChecks
@testable import HealthChecks

public struct PostgresHealthChecksMock: PostgresHealthChecksProtocol {
static let psqlId = "adca7c3d-55f4-4ab3-a842-18b35f50cb0f"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import Vapor
import XCTest
@testable import AppHealthChecks
@testable import HealthChecks

final class PostgresHealthChecksTests: XCTestCase {
func testConnection() async throws {
Expand Down
Loading