diff --git a/Boka/Package.swift b/Boka/Package.swift index 079d85bd..1cdd988c 100644 --- a/Boka/Package.swift +++ b/Boka/Package.swift @@ -12,6 +12,8 @@ let package = Package( .package(path: "../Node"), .package(path: "../TracingUtils"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.4.0"), + .package(url: "https://github.com/slashmo/swift-otel.git", from: "0.9.0"), + .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.6.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. @@ -22,6 +24,9 @@ let package = Package( "Node", "TracingUtils", .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "ServiceLifecycle", package: "swift-service-lifecycle"), + .product(name: "OTel", package: "swift-otel"), + .product(name: "OTLPGRPC", package: "swift-otel"), ] ), .testTarget( diff --git a/Boka/Sources/Boka.swift b/Boka/Sources/Boka.swift index e4d55bfb..aea94e87 100644 --- a/Boka/Sources/Boka.swift +++ b/Boka/Sources/Boka.swift @@ -6,6 +6,7 @@ import ArgumentParser import Node +import ServiceLifecycle import TracingUtils @main diff --git a/Boka/Sources/Tracing.swift b/Boka/Sources/Tracing.swift new file mode 100644 index 00000000..43e165e7 --- /dev/null +++ b/Boka/Sources/Tracing.swift @@ -0,0 +1,61 @@ +import OTel +import OTLPGRPC +import ServiceLifecycle +import TracingUtils + +public enum Tracing { + public static func bootstrap(_ serviceName: String) async throws -> [Service] { + // Bootstrap the logging backend with the OTel metadata provider which includes span IDs in logging messages. + LoggingSystem.bootstrap { label in + var handler = StreamLogHandler.standardError(label: label, metadataProvider: .otel) + handler.logLevel = .trace + return handler + } + + // Configure OTel resource detection to automatically apply helpful attributes to events. + let environment = OTelEnvironment.detected() + let resourceDetection = OTelResourceDetection(detectors: [ + OTelProcessResourceDetector(), + OTelEnvironmentResourceDetector(environment: environment), + .manual( + OTelResource( + attributes: SpanAttributes(["service.name": serviceName.toSpanAttribute()]) + ) + ), + ]) + let resource = await resourceDetection.resource(environment: environment, logLevel: .trace) + + // Bootstrap the metrics backend to export metrics periodically in OTLP/gRPC. + let registry = OTelMetricRegistry() + let metricsExporter = try OTLPGRPCMetricExporter( + configuration: .init(environment: environment) + ) + let metrics = OTelPeriodicExportingMetricsReader( + resource: resource, + producer: registry, + exporter: metricsExporter, + configuration: .init( + environment: environment, + exportInterval: .seconds(5) // NOTE: This is overridden for the example; the default is 60 seconds. + ) + ) + MetricsSystem.bootstrap(OTLPMetricsFactory(registry: registry)) + + // Bootstrap the tracing backend to export traces periodically in OTLP/gRPC. + let exporter = try OTLPGRPCSpanExporter(configuration: .init(environment: environment)) + let processor = OTelBatchSpanProcessor( + exporter: exporter, configuration: .init(environment: environment) + ) + let tracer = OTelTracer( + idGenerator: OTelRandomIDGenerator(), + sampler: OTelConstantSampler(isOn: true), + propagator: OTelW3CPropagator(), + processor: processor, + environment: environment, + resource: resource + ) + InstrumentationSystem.bootstrap(tracer) + + return [tracer, metrics] + } +} diff --git a/JAMTests/Package.resolved b/JAMTests/Package.resolved index ffc01582..5d1cffcb 100644 --- a/JAMTests/Package.resolved +++ b/JAMTests/Package.resolved @@ -10,6 +10,15 @@ "version" : "0.2.0" } }, + { + "identity" : "grpc-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-swift.git", + "state" : { + "revision" : "6a90b7e77e29f9bda6c2b3a4165a40d6c02cfda1", + "version" : "1.23.0" + } + }, { "identity" : "scalecodec.swift", "kind" : "remoteSourceControl", @@ -19,6 +28,15 @@ "revision" : "dac3e7161de34c60c82794d031de0231b5a5746e" } }, + { + "identity" : "swift-async-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-async-algorithms.git", + "state" : { + "revision" : "6ae9a051f76b81cc668305ceed5b0e0a7fd93d20", + "version" : "1.0.1" + } + }, { "identity" : "swift-atomics", "kind" : "remoteSourceControl", @@ -28,6 +46,15 @@ "version" : "1.2.0" } }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d", + "version" : "1.1.2" + } + }, { "identity" : "swift-crypto", "kind" : "remoteSourceControl", @@ -37,6 +64,24 @@ "version" : "3.5.0" } }, + { + "identity" : "swift-distributed-tracing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-distributed-tracing.git", + "state" : { + "revision" : "11c756c5c4d7de0eeed8595695cadd7fa107aa19", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types", + "state" : { + "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", + "version" : "1.3.0" + } + }, { "identity" : "swift-log", "kind" : "remoteSourceControl", @@ -46,6 +91,96 @@ "version" : "1.6.1" } }, + { + "identity" : "swift-metrics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-metrics.git", + "state" : { + "revision" : "e0165b53d49b413dd987526b641e05e246782685", + "version" : "2.5.0" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "4c4453b489cf76e6b3b0f300aba663eb78182fad", + "version" : "2.70.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "05c36b57453d23ea63785d58a7dbc7b70ba1745e", + "version" : "1.23.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94", + "version" : "1.34.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "a9fa5efd86e7ce2e5c1b6de113262e58035ca251", + "version" : "2.27.1" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "38ac8221dd20674682148d6451367f89c2652980", + "version" : "1.21.0" + } + }, + { + "identity" : "swift-otel", + "kind" : "remoteSourceControl", + "location" : "https://github.com/slashmo/swift-otel.git", + "state" : { + "revision" : "8c271c7fed34a39f29c728598b3358fbdddf8ff4", + "version" : "0.9.0" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "e17d61f26df0f0e06f58f6977ba05a097a720106", + "version" : "1.27.1" + } + }, + { + "identity" : "swift-service-context", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-service-context.git", + "state" : { + "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", + "version" : "1.1.0" + } + }, + { + "identity" : "swift-service-lifecycle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swift-server/swift-service-lifecycle.git", + "state" : { + "revision" : "24c800fb494fbee6e42bc156dc94232dc08971af", + "version" : "2.6.1" + } + }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", @@ -55,6 +190,15 @@ "version" : "600.0.0-prerelease-2024-06-12" } }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", + "version" : "1.3.2" + } + }, { "identity" : "swift-testing", "kind" : "remoteSourceControl", diff --git a/Makefile b/Makefile index 0a951eef..8635761b 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ deps: .lib/libblst.a .lib/libbandersnatch_vrfs.a .lib/librocksdb.a .PHONY: test test: githooks deps - ./scripts/run.sh test + ./scripts/runTests.sh test .PHONY: build build: githooks deps diff --git a/TracingUtils/Package.resolved b/TracingUtils/Package.resolved index 80a93bd9..a75092e4 100644 --- a/TracingUtils/Package.resolved +++ b/TracingUtils/Package.resolved @@ -1,42 +1,6 @@ { - "originHash" : "98937709a5af5e7b41f593f54283c39e3801824399b2f5f67196702dded80298", + "originHash" : "dafdfe8c8a201d8118f12ef271e841774867a4498bc06527ccf8cea1b522a154", "pins" : [ - { - "identity" : "grpc-swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift.git", - "state" : { - "revision" : "6a90b7e77e29f9bda6c2b3a4165a40d6c02cfda1", - "version" : "1.23.0" - } - }, - { - "identity" : "swift-async-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-async-algorithms.git", - "state" : { - "revision" : "6ae9a051f76b81cc668305ceed5b0e0a7fd93d20", - "version" : "1.0.1" - } - }, - { - "identity" : "swift-atomics", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-atomics.git", - "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d", - "version" : "1.1.2" - } - }, { "identity" : "swift-distributed-tracing", "kind" : "remoteSourceControl", @@ -46,15 +10,6 @@ "version" : "1.1.1" } }, - { - "identity" : "swift-http-types", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-http-types", - "state" : { - "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", - "version" : "1.3.0" - } - }, { "identity" : "swift-log", "kind" : "remoteSourceControl", @@ -73,69 +28,6 @@ "version" : "2.5.0" } }, - { - "identity" : "swift-nio", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio.git", - "state" : { - "revision" : "4c4453b489cf76e6b3b0f300aba663eb78182fad", - "version" : "2.70.0" - } - }, - { - "identity" : "swift-nio-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-extras.git", - "state" : { - "revision" : "05c36b57453d23ea63785d58a7dbc7b70ba1745e", - "version" : "1.23.0" - } - }, - { - "identity" : "swift-nio-http2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-http2.git", - "state" : { - "revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94", - "version" : "1.34.0" - } - }, - { - "identity" : "swift-nio-ssl", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-ssl.git", - "state" : { - "revision" : "a9fa5efd86e7ce2e5c1b6de113262e58035ca251", - "version" : "2.27.1" - } - }, - { - "identity" : "swift-nio-transport-services", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-nio-transport-services.git", - "state" : { - "revision" : "38ac8221dd20674682148d6451367f89c2652980", - "version" : "1.21.0" - } - }, - { - "identity" : "swift-otel", - "kind" : "remoteSourceControl", - "location" : "https://github.com/slashmo/swift-otel.git", - "state" : { - "revision" : "8c271c7fed34a39f29c728598b3358fbdddf8ff4", - "version" : "0.9.0" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "e17d61f26df0f0e06f58f6977ba05a097a720106", - "version" : "1.27.1" - } - }, { "identity" : "swift-service-context", "kind" : "remoteSourceControl", @@ -144,24 +36,6 @@ "revision" : "0c62c5b4601d6c125050b5c3a97f20cce881d32b", "version" : "1.1.0" } - }, - { - "identity" : "swift-service-lifecycle", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swift-server/swift-service-lifecycle.git", - "state" : { - "revision" : "24c800fb494fbee6e42bc156dc94232dc08971af", - "version" : "2.6.1" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system.git", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } } ], "version" : 3 diff --git a/TracingUtils/Package.swift b/TracingUtils/Package.swift index 6d186edf..3c6f123a 100644 --- a/TracingUtils/Package.swift +++ b/TracingUtils/Package.swift @@ -17,10 +17,8 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"), - .package(url: "https://github.com/slashmo/swift-otel.git", from: "0.9.0"), .package(url: "https://github.com/apple/swift-metrics.git", from: "2.5.0"), .package(url: "https://github.com/apple/swift-distributed-tracing.git", from: "1.1.0"), - .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.6.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. @@ -28,12 +26,9 @@ let package = Package( .target( name: "TracingUtils", dependencies: [ - .product(name: "OTel", package: "swift-otel"), - .product(name: "OTLPGRPC", package: "swift-otel"), .product(name: "Logging", package: "swift-log"), .product(name: "Metrics", package: "swift-metrics"), .product(name: "Tracing", package: "swift-distributed-tracing"), - .product(name: "ServiceLifecycle", package: "swift-service-lifecycle"), ] ), ] diff --git a/TracingUtils/Sources/TracingUtils/Tracing.swift b/TracingUtils/Sources/TracingUtils/Tracing.swift index 05c72cbd..77648802 100644 --- a/TracingUtils/Sources/TracingUtils/Tracing.swift +++ b/TracingUtils/Sources/TracingUtils/Tracing.swift @@ -1,63 +1,3 @@ @_exported import Logging @_exported import Metrics -import OTel -import OTLPGRPC -@_exported import ServiceLifecycle @_exported import Tracing - -public enum Tracing { - public static func bootstrap(_ serviceName: String) async throws -> [Service] { - // Bootstrap the logging backend with the OTel metadata provider which includes span IDs in logging messages. - LoggingSystem.bootstrap { label in - var handler = StreamLogHandler.standardError(label: label, metadataProvider: .otel) - handler.logLevel = .trace - return handler - } - - // Configure OTel resource detection to automatically apply helpful attributes to events. - let environment = OTelEnvironment.detected() - let resourceDetection = OTelResourceDetection(detectors: [ - OTelProcessResourceDetector(), - OTelEnvironmentResourceDetector(environment: environment), - .manual( - OTelResource( - attributes: SpanAttributes(["service.name": serviceName.toSpanAttribute()]) - ) - ), - ]) - let resource = await resourceDetection.resource(environment: environment, logLevel: .trace) - - // Bootstrap the metrics backend to export metrics periodically in OTLP/gRPC. - let registry = OTelMetricRegistry() - let metricsExporter = try OTLPGRPCMetricExporter( - configuration: .init(environment: environment) - ) - let metrics = OTelPeriodicExportingMetricsReader( - resource: resource, - producer: registry, - exporter: metricsExporter, - configuration: .init( - environment: environment, - exportInterval: .seconds(5) // NOTE: This is overridden for the example; the default is 60 seconds. - ) - ) - MetricsSystem.bootstrap(OTLPMetricsFactory(registry: registry)) - - // Bootstrap the tracing backend to export traces periodically in OTLP/gRPC. - let exporter = try OTLPGRPCSpanExporter(configuration: .init(environment: environment)) - let processor = OTelBatchSpanProcessor( - exporter: exporter, configuration: .init(environment: environment) - ) - let tracer = OTelTracer( - idGenerator: OTelRandomIDGenerator(), - sampler: OTelConstantSampler(isOn: true), - propagator: OTelW3CPropagator(), - processor: processor, - environment: environment, - resource: resource - ) - InstrumentationSystem.bootstrap(tracer) - - return [tracer, metrics] - } -} diff --git a/scripts/runTests.sh b/scripts/runTests.sh new file mode 100755 index 00000000..ebdfd1f3 --- /dev/null +++ b/scripts/runTests.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +COMMAND=$1 + +shift + +set -x + +for file in **/Tests; do + swift $COMMAND $@ --package-path "$(dirname "$file")"; +done