SwiftBox

SwiftBox 是一个基于 SwiftNIO 的包,它有助于构建基于 Swift/NIO 的微服务。

Build Status Swift 5.3 Linux MacOS

包含什么?

使用 Swift 运行微服务需要:

即将推出:与 https://github.com/apple/swift-log 集成。

SwiftBox 配置

SwiftBox 配置允许通过声明一个简单的结构体来传递类型安全的配置,例如命令行、环境变量和外部提供程序(例如 Vault)。配置可以同时从多个来源继承。

通过以下方式提供配置:

SwiftBox 配置支持:

用法

1. 导入

导入模块

import SwiftBoxConfig

2. 配置结构

创建配置时,请记住,为了正确解码,它必须符合 Configuration 协议。

struct Conf: Configuration {
    let simple: String
    let int: Int
    let double: Double
    let nested: NestedConf // nested configuration
    let array: [String?] // array of optionals
    let arraynested: [NestedConf] // nested array

    struct NestedConf: Configuration {
        let value: String? // optional
    }
}

3. 引导

配置在使用前必须进行引导。 为此,您需要首先符合 ConfigManager 协议

extension Conf: ConfigManager {
    public static var configuration: Conf? = nil
}

接下来,在您的 ConfigManager 上调用 bootstrap 方法,并传递您想要使用的来源

try Conf.bootstrap(from: [EnvSource()])

请记住,引导必须在使用配置之前调用,并且不能多次调用。 否则,将抛出 fatalError

4. 用法

完成所有之前的步骤后,您最终可以在您的应用程序中使用配置。您可以通过 global 属性访问配置实例

Conf.global.simple
Conf.global.int
Conf.global.double
Conf.global.array[0] // Optional[String]
Conf.global.nested.value // Optional[String]
Conf.global.arraynested[0].value // Optional[String]

来源

配置可以从多个来源提供。来源被传递到引导函数中。

如果您使用多个来源,输出将被合并(结构体被递归合并,其他值被覆盖)

try Conf.bootstrap(from: [
    DictionarySource(dataSource: [
        "int": 1,
        "string": "some",
        "array": [1, 2],
        "nested": ["value1": 1]
    ]),
    DictionarySource(dataSource: [
        "string": "test",
        "array": [2, 3],
        "nested": ["value2": 2]
    ]),
])

// Output config:
[
    "int": 1,
    "string": "test",
    "array": [2, 3],
    "nested": [
        "value1": 1,
        "value2": 2
    ]
]

字典来源

允许从字典读取配置,可用于指定配置的内联代码默认值。

示例
try Conf.bootstrap(from: [
    DictionarySource(dataSource: [
        "int": 1,
        "string": "some",
        "array": [1, 2],
        "nested": ["value1": 1]
    ])
])

JSON 来源

允许从 JSON 数据读取配置。

示例
try Conf.bootstrap(from: [
    JSONSource(dataSource: "{\"test\": \"sample\"}")
])

环境来源

允许从环境变量读取配置数据。

示例
try Conf.bootstrap(from: [
    EnvSource(prefix: "SAMPLE")
])

可以为 EnvSource 设置前缀,因此它只读取键以给定值开头的变量。

示例配置
struct Conf: Configuration {
    let simple: String
    let int: Int
    let double: Double
    let nested: NestedConf
    let array: [String?]
    let arraynested: [NestedConf]

    struct NestedConf: Configuration {
        let value: String?
    }
}

可以使用以下环境变量填充以上示例

SIMPLE="test"
INT="1"
DOUBLE="1.0"
NULL="null"
NESTED_VALUE="test"
ARRAY_0="test0"
ARRAY_1="test1"
ARRAY_2="null"
ARRAYNESTED_0_VALUE="test0"
ARRAYNESTED_1_VALUE="test1"
ARRAYNESTED_2_VALUE="null"

值 "null" 被强制转换为内部 nil 值

命令行来源

允许从环境变量读取配置数据。

示例
Conf.bootstrap(from: [
    CommandLineSource(prefix: "--config:my-prefix-")
])

如果设置了前缀,则只会读取以给定值开头的参数。 默认为 --config:

示例配置
struct Conf: Configuration {
    let simple: String
    let int: Int
    let double: Double
    let null: String?
    let nested: NestedConf
    let array: [String?]
    let arraynested: [NestedConf]

    struct NestedConf: Configuration {
        let value: String?
    }
}

可以使用以下命令行参数填充以上示例

--config:simple=test
--config:int=1
--config:double=1.0
--config:null=null
--config:nested.value=test
--config:array.0=test0
--config:array.1=test1
--config:array.2=null
--config:arraynested.0.value=test0
--config:arraynested.1.value=test1
--config:arraynested.2.value=null

值 "null" 被强制转换为内部 nil 值

自定义来源

要创建自定义来源,您需要创建一个符合 ConfigSource 的类。 DictionarySource 是最简单的工作来源,可以用作示例

public typealias Storage = [String: Any?]

public class DictionarySource: ConfigSource {
    let dataSource: Storage

    public init(dataSource: Storage) {
        self.dataSource = dataSource
    }

    public func getConfig() throws -> Storage {
        return self.dataSource
    }
}

SwiftBoxLogging

Swift 的日志记录系统。

用法

1. 导入

import SwiftBoxLogging

2. 引导

日志记录应在使用前进行引导(默认为 PrintLogger)。 引导需要一个参数,即日志记录器工厂。

日志记录器工厂必须从 swift-log 包返回 LogHandler

Logging.bootstrap { label in ElasticsearchLogHandler(label: name) }

2. 用法

创建一个日志记录器实例

fileprivate var logger = Logging.make(#file)

使用可用的协议方法之一记录消息

func trace(_ message: String)
func info(_ message: String)
func debug(_ message: String)
func notice(_ message: String)
func warning(_ message: String)
func error(_ message: String)
func critical(_ message: String)

自定义日志记录器

要创建自定义日志记录器,您的类必须符合 LoggerProtocol

Vapor

您可以通过覆盖 Vapor 的默认日志处理程序来使用相同的日志记录

import Logging

LoggingSystem.bootstrap { label in
    ElasticsearchLogHandler(label: label)
}

SwiftBoxMetrics

官方 swift-metrics API 的 StatsD 和 Logger 处理程序。

支持的指标类型

用法

1. 导入

import Metrics
import SwiftBoxMetrics

2. 引导

指标必须使用符合 MetricsHandler 协议的 Handler 进行引导

// StatsD Handler initialization
MetricsSystem.bootstrap(
    try! StatsDMetricsHandler(
        baseMetricPath: AppConfig.global.statsd.basePath!,
        client: UDPStatsDClient(
            config: UDPConnectionConfig(
                host: AppConfig.global.statsd.host!,
                port: AppConfig.global.statsd.port!
            )
        )
    )
)

// Logger Handler initialization
MetricsSystem.bootstrap(LoggerMetricsHandler())

3. 用法

用法详情可以在官方 swift-metrics GitHub 存储库中找到。

处理程序

LoggerMetricsHandler

默认指标处理程序,将收集的指标发送到其日志记录器。

StatsDMetricsHandler

StatsD 指标处理程序负责将收集的日志发送到 StatsD 服务器。 支持 TCP 和 UDP 协议。 指标在单独的线程中发送,因此操作对于应用程序是非阻塞的。

try StatsDMetricsHandler(
    baseMetricPath: AppConfig.global.statsd.basePath!,
    client: UDPStatsDClient(
        config: UDPConnectionConfig(
            host: AppConfig.global.statsd.host!,
            port: AppConfig.global.statsd.port!
        )
    )
)

baseMetricPath 是一个路径,它将附加到通过处理程序发送的每个指标。 client 是一个 TCPStatsDClientUDPStatsDClient 实例。

自定义处理程序

要创建自定义处理程序,请符合 MetricsHandler 类。