forked from Deuxfleurs/tricot
Add basic support for metrics
This commit is contained in:
parent
43a0fe14b2
commit
5d38f2cf7f
7 changed files with 655 additions and 28 deletions
172
Cargo.lock
generated
172
Cargo.lock
generated
|
@ -108,6 +108,17 @@ dependencies = [
|
|||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -311,6 +322,25 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.83"
|
||||
|
@ -355,6 +385,16 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dhat"
|
||||
version = "0.3.2"
|
||||
|
@ -979,6 +1019,38 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"crossbeam-channel",
|
||||
"dashmap",
|
||||
"fnv",
|
||||
"futures-channel",
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"rand",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-prometheus"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9328977e479cebe12ce0d3fcecdaea4721d234895a9440c5b5dfd113f0594ac6"
|
||||
dependencies = [
|
||||
"opentelemetry",
|
||||
"prometheus",
|
||||
"protobuf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
@ -1017,6 +1089,26 @@ version = "2.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
|
@ -1035,6 +1127,12 @@ version = "0.3.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_env_logger"
|
||||
version = "0.4.0"
|
||||
|
@ -1084,6 +1182,27 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prometheus"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fnv",
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"parking_lot",
|
||||
"protobuf",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "2.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
|
||||
|
||||
[[package]]
|
||||
name = "publicsuffix"
|
||||
version = "1.5.6"
|
||||
|
@ -1118,6 +1237,36 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcgen"
|
||||
version = "0.10.0"
|
||||
|
@ -1599,6 +1748,26 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thousands"
|
||||
version = "0.2.0"
|
||||
|
@ -1785,7 +1954,10 @@ dependencies = [
|
|||
"hyper",
|
||||
"hyper-rustls",
|
||||
"log",
|
||||
"opentelemetry",
|
||||
"opentelemetry-prometheus",
|
||||
"pretty_env_logger",
|
||||
"prometheus",
|
||||
"rcgen",
|
||||
"regex",
|
||||
"reqwest",
|
||||
|
|
268
Cargo.nix
268
Cargo.nix
|
@ -23,7 +23,7 @@ args@{
|
|||
ignoreLockHash,
|
||||
}:
|
||||
let
|
||||
nixifiedLockHash = "8b9764c8874557f30d0d72cb4e6453209d5ab90c71cfe15c3367a366506066d2";
|
||||
nixifiedLockHash = "ba43baa059b58c2c0ae0bf86c8d8dc3663b7bd3ecb95274246a3d7123238271a";
|
||||
workspaceSrc = if args.workspaceSrc == null then ./. else args.workspaceSrc;
|
||||
currentLockHash = builtins.hashFile "sha256" (workspaceSrc + /Cargo.lock);
|
||||
lockHashIgnored = if ignoreLockHash
|
||||
|
@ -184,6 +184,18 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.59" = overridableMkRustCrate (profileName: rec {
|
||||
name = "async-trait";
|
||||
version = "0.1.59";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"; };
|
||||
dependencies = {
|
||||
proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.47" { inherit profileName; }).out;
|
||||
quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.21" { inherit profileName; }).out;
|
||||
syn = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."1.0.105" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".atty."0.2.14" = overridableMkRustCrate (profileName: rec {
|
||||
name = "atty";
|
||||
version = "0.2.14";
|
||||
|
@ -480,6 +492,35 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".crossbeam-channel."0.5.6" = overridableMkRustCrate (profileName: rec {
|
||||
name = "crossbeam-channel";
|
||||
version = "0.5.6";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"; };
|
||||
features = builtins.concatLists [
|
||||
[ "crossbeam-utils" ]
|
||||
[ "default" ]
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
crossbeam_utils = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".crossbeam-utils."0.8.14" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".crossbeam-utils."0.8.14" = overridableMkRustCrate (profileName: rec {
|
||||
name = "crossbeam-utils";
|
||||
version = "0.8.14";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"; };
|
||||
features = builtins.concatLists [
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".cxx."1.0.83" = overridableMkRustCrate (profileName: rec {
|
||||
name = "cxx";
|
||||
version = "1.0.83";
|
||||
|
@ -538,6 +579,20 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".dashmap."4.0.2" = overridableMkRustCrate (profileName: rec {
|
||||
name = "dashmap";
|
||||
version = "4.0.2";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"; };
|
||||
features = builtins.concatLists [
|
||||
[ "default" ]
|
||||
];
|
||||
dependencies = {
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
num_cpus = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".num_cpus."1.14.0" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".dhat."0.3.2" = overridableMkRustCrate (profileName: rec {
|
||||
name = "dhat";
|
||||
version = "0.3.2";
|
||||
|
@ -752,6 +807,7 @@ in
|
|||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"; };
|
||||
features = builtins.concatLists [
|
||||
[ "default" ]
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
|
@ -846,6 +902,9 @@ in
|
|||
version = "0.2.8";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"; };
|
||||
features = builtins.concatLists [
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
${ if hostPlatform.isUnix then "libc" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.138" { inherit profileName; }).out;
|
||||
|
@ -1184,10 +1243,10 @@ in
|
|||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"; };
|
||||
dependencies = {
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "scopeguard" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".scopeguard."1.1.0" { inherit profileName; }).out;
|
||||
scopeguard = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".scopeguard."1.1.0" { inherit profileName; }).out;
|
||||
};
|
||||
buildDependencies = {
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "autocfg" else null } = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".autocfg."1.1.0" { profileName = "__noProfile"; }).out;
|
||||
autocfg = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".autocfg."1.1.0" { profileName = "__noProfile"; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1402,17 +1461,63 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "opentelemetry";
|
||||
version = "0.17.0";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8"; };
|
||||
features = builtins.concatLists [
|
||||
[ "async-trait" ]
|
||||
[ "crossbeam-channel" ]
|
||||
[ "dashmap" ]
|
||||
[ "default" ]
|
||||
[ "fnv" ]
|
||||
[ "metrics" ]
|
||||
[ "percent-encoding" ]
|
||||
[ "pin-project" ]
|
||||
[ "rand" ]
|
||||
[ "trace" ]
|
||||
];
|
||||
dependencies = {
|
||||
async_trait = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".async-trait."0.1.59" { profileName = "__noProfile"; }).out;
|
||||
crossbeam_channel = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".crossbeam-channel."0.5.6" { inherit profileName; }).out;
|
||||
dashmap = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".dashmap."4.0.2" { inherit profileName; }).out;
|
||||
fnv = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".fnv."1.0.7" { inherit profileName; }).out;
|
||||
futures_channel = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-channel."0.3.25" { inherit profileName; }).out;
|
||||
futures_executor = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-executor."0.3.25" { inherit profileName; }).out;
|
||||
futures_util = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".futures-util."0.3.25" { inherit profileName; }).out;
|
||||
${ if hostPlatform.parsed.cpu.name == "wasm32" then "js_sys" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".js-sys."0.3.60" { inherit profileName; }).out;
|
||||
lazy_static = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".lazy_static."1.4.0" { inherit profileName; }).out;
|
||||
percent_encoding = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".percent-encoding."2.2.0" { inherit profileName; }).out;
|
||||
pin_project = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.12" { inherit profileName; }).out;
|
||||
rand = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" { inherit profileName; }).out;
|
||||
thiserror = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.37" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".opentelemetry-prometheus."0.10.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "opentelemetry-prometheus";
|
||||
version = "0.10.0";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "9328977e479cebe12ce0d3fcecdaea4721d234895a9440c5b5dfd113f0594ac6"; };
|
||||
dependencies = {
|
||||
opentelemetry = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; }).out;
|
||||
prometheus = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".prometheus."0.13.3" { inherit profileName; }).out;
|
||||
protobuf = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".protobuf."2.28.0" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.12.1" = overridableMkRustCrate (profileName: rec {
|
||||
name = "parking_lot";
|
||||
version = "0.12.1";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"; };
|
||||
features = builtins.concatLists [
|
||||
(lib.optional (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") "default")
|
||||
[ "default" ]
|
||||
];
|
||||
dependencies = {
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "lock_api" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".lock_api."0.4.9" { inherit profileName; }).out;
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "parking_lot_core" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.9.5" { inherit profileName; }).out;
|
||||
lock_api = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".lock_api."0.4.9" { inherit profileName; }).out;
|
||||
parking_lot_core = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot_core."0.9.5" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1422,11 +1527,11 @@ in
|
|||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"; };
|
||||
dependencies = {
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "cfg_if" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
${ if (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") && hostPlatform.isUnix then "libc" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.138" { inherit profileName; }).out;
|
||||
${ if (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") && hostPlatform.parsed.kernel.name == "redox" then "syscall" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".redox_syscall."0.2.16" { inherit profileName; }).out;
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "smallvec" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".smallvec."1.10.0" { inherit profileName; }).out;
|
||||
${ if (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") && hostPlatform.isWindows then "windows_sys" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows-sys."0.42.0" { inherit profileName; }).out;
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
${ if hostPlatform.isUnix then "libc" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.138" { inherit profileName; }).out;
|
||||
${ if hostPlatform.parsed.kernel.name == "redox" then "syscall" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".redox_syscall."0.2.16" { inherit profileName; }).out;
|
||||
smallvec = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".smallvec."1.10.0" { inherit profileName; }).out;
|
||||
${ if hostPlatform.isWindows then "windows_sys" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows-sys."0.42.0" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1451,6 +1556,28 @@ in
|
|||
];
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".pin-project."1.0.12" = overridableMkRustCrate (profileName: rec {
|
||||
name = "pin-project";
|
||||
version = "1.0.12";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"; };
|
||||
dependencies = {
|
||||
pin_project_internal = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".pin-project-internal."1.0.12" { profileName = "__noProfile"; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".pin-project-internal."1.0.12" = overridableMkRustCrate (profileName: rec {
|
||||
name = "pin-project-internal";
|
||||
version = "1.0.12";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"; };
|
||||
dependencies = {
|
||||
proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.47" { inherit profileName; }).out;
|
||||
quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.21" { inherit profileName; }).out;
|
||||
syn = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."1.0.105" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".pin-project-lite."0.2.9" = overridableMkRustCrate (profileName: rec {
|
||||
name = "pin-project-lite";
|
||||
version = "0.2.9";
|
||||
|
@ -1472,6 +1599,17 @@ in
|
|||
src = fetchCratesIo { inherit name version; sha256 = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"; };
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".ppv-lite86."0.2.17" = overridableMkRustCrate (profileName: rec {
|
||||
name = "ppv-lite86";
|
||||
version = "0.2.17";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"; };
|
||||
features = builtins.concatLists [
|
||||
[ "simd" ]
|
||||
[ "std" ]
|
||||
];
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".pretty_env_logger."0.4.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "pretty_env_logger";
|
||||
version = "0.4.0";
|
||||
|
@ -1540,6 +1678,33 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".prometheus."0.13.3" = overridableMkRustCrate (profileName: rec {
|
||||
name = "prometheus";
|
||||
version = "0.13.3";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"; };
|
||||
features = builtins.concatLists [
|
||||
[ "default" ]
|
||||
[ "protobuf" ]
|
||||
];
|
||||
dependencies = {
|
||||
cfg_if = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".cfg-if."1.0.0" { inherit profileName; }).out;
|
||||
fnv = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".fnv."1.0.7" { inherit profileName; }).out;
|
||||
lazy_static = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".lazy_static."1.4.0" { inherit profileName; }).out;
|
||||
memchr = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".memchr."2.5.0" { inherit profileName; }).out;
|
||||
parking_lot = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".parking_lot."0.12.1" { inherit profileName; }).out;
|
||||
protobuf = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".protobuf."2.28.0" { inherit profileName; }).out;
|
||||
thiserror = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.37" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".protobuf."2.28.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "protobuf";
|
||||
version = "2.28.0";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"; };
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".publicsuffix."1.5.6" = overridableMkRustCrate (profileName: rec {
|
||||
name = "publicsuffix";
|
||||
version = "1.5.6";
|
||||
|
@ -1582,6 +1747,55 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".rand."0.8.5" = overridableMkRustCrate (profileName: rec {
|
||||
name = "rand";
|
||||
version = "0.8.5";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"; };
|
||||
features = builtins.concatLists [
|
||||
[ "alloc" ]
|
||||
[ "getrandom" ]
|
||||
[ "libc" ]
|
||||
[ "rand_chacha" ]
|
||||
[ "std" ]
|
||||
[ "std_rng" ]
|
||||
];
|
||||
dependencies = {
|
||||
${ if hostPlatform.isUnix then "libc" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libc."0.2.138" { inherit profileName; }).out;
|
||||
rand_chacha = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand_chacha."0.3.1" { inherit profileName; }).out;
|
||||
rand_core = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand_core."0.6.4" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".rand_chacha."0.3.1" = overridableMkRustCrate (profileName: rec {
|
||||
name = "rand_chacha";
|
||||
version = "0.3.1";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"; };
|
||||
features = builtins.concatLists [
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
ppv_lite86 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".ppv-lite86."0.2.17" { inherit profileName; }).out;
|
||||
rand_core = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".rand_core."0.6.4" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".rand_core."0.6.4" = overridableMkRustCrate (profileName: rec {
|
||||
name = "rand_core";
|
||||
version = "0.6.4";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"; };
|
||||
features = builtins.concatLists [
|
||||
[ "alloc" ]
|
||||
[ "getrandom" ]
|
||||
[ "std" ]
|
||||
];
|
||||
dependencies = {
|
||||
getrandom = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".getrandom."0.2.8" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".rcgen."0.10.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "rcgen";
|
||||
version = "0.10.0";
|
||||
|
@ -1605,7 +1819,7 @@ in
|
|||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"; };
|
||||
dependencies = {
|
||||
${ if rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap" then "bitflags" else null } = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; }).out;
|
||||
bitflags = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitflags."1.3.2" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -2181,6 +2395,7 @@ in
|
|||
[ "proc-macro" ]
|
||||
[ "quote" ]
|
||||
[ "visit" ]
|
||||
[ "visit-mut" ]
|
||||
];
|
||||
dependencies = {
|
||||
proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.47" { inherit profileName; }).out;
|
||||
|
@ -2239,6 +2454,28 @@ in
|
|||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".thiserror."1.0.37" = overridableMkRustCrate (profileName: rec {
|
||||
name = "thiserror";
|
||||
version = "1.0.37";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"; };
|
||||
dependencies = {
|
||||
thiserror_impl = (buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".thiserror-impl."1.0.37" { profileName = "__noProfile"; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".thiserror-impl."1.0.37" = overridableMkRustCrate (profileName: rec {
|
||||
name = "thiserror-impl";
|
||||
version = "1.0.37";
|
||||
registry = "registry+https://github.com/rust-lang/crates.io-index";
|
||||
src = fetchCratesIo { inherit name version; sha256 = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"; };
|
||||
dependencies = {
|
||||
proc_macro2 = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.47" { inherit profileName; }).out;
|
||||
quote = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.21" { inherit profileName; }).out;
|
||||
syn = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."1.0.105" { inherit profileName; }).out;
|
||||
};
|
||||
});
|
||||
|
||||
"registry+https://github.com/rust-lang/crates.io-index".thousands."0.2.0" = overridableMkRustCrate (profileName: rec {
|
||||
name = "thousands";
|
||||
version = "0.2.0";
|
||||
|
@ -2507,7 +2744,10 @@ in
|
|||
hyper = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper."0.14.23" { inherit profileName; }).out;
|
||||
hyper_rustls = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".hyper-rustls."0.23.1" { inherit profileName; }).out;
|
||||
log = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".log."0.4.17" { inherit profileName; }).out;
|
||||
opentelemetry = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry."0.17.0" { inherit profileName; }).out;
|
||||
opentelemetry_prometheus = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".opentelemetry-prometheus."0.10.0" { inherit profileName; }).out;
|
||||
pretty_env_logger = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".pretty_env_logger."0.4.0" { inherit profileName; }).out;
|
||||
prometheus = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".prometheus."0.13.3" { inherit profileName; }).out;
|
||||
rcgen = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".rcgen."0.10.0" { inherit profileName; }).out;
|
||||
regex = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".regex."1.7.0" { inherit profileName; }).out;
|
||||
reqwest = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".reqwest."0.11.13" { inherit profileName; }).out;
|
||||
|
@ -2980,9 +3220,9 @@ in
|
|||
[ "Win32_Storage_FileSystem" ]
|
||||
[ "Win32_System" ]
|
||||
[ "Win32_System_IO" ]
|
||||
(lib.optional (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") "Win32_System_LibraryLoader")
|
||||
[ "Win32_System_LibraryLoader" ]
|
||||
[ "Win32_System_Pipes" ]
|
||||
(lib.optional (rootFeatures' ? "tricot/dhat" || rootFeatures' ? "tricot/dhat-heap") "Win32_System_SystemServices")
|
||||
[ "Win32_System_SystemServices" ]
|
||||
[ "Win32_System_WindowsProgramming" ]
|
||||
[ "default" ]
|
||||
];
|
||||
|
|
|
@ -34,6 +34,9 @@ accept-encoding-fork = "0.2.0-alpha.3"
|
|||
async-compression = { version = "0.3", features = ["tokio", "gzip", "zstd", "deflate", "brotli"] }
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
uuid = { version = "1.2", features = ["v4"] }
|
||||
opentelemetry = "0.17"
|
||||
opentelemetry-prometheus = "0.10"
|
||||
prometheus = "0.13"
|
||||
|
||||
dhat = { version = "0.3", optional = true }
|
||||
|
||||
|
|
72
src/https.rs
72
src/https.rs
|
@ -21,6 +21,8 @@ use tokio::sync::watch;
|
|||
use tokio_rustls::TlsAcceptor;
|
||||
use tokio_util::io::{ReaderStream, StreamReader};
|
||||
|
||||
use opentelemetry::{metrics, KeyValue};
|
||||
|
||||
use crate::cert_store::{CertStore, StoreResolver};
|
||||
use crate::proxy_config::ProxyConfig;
|
||||
use crate::reverse_proxy;
|
||||
|
@ -33,6 +35,11 @@ pub struct HttpsConfig {
|
|||
pub compress_mime_types: Vec<String>,
|
||||
}
|
||||
|
||||
struct HttpsMetrics {
|
||||
requests_received: metrics::Counter<u64>,
|
||||
requests_served: metrics::Counter<u64>,
|
||||
}
|
||||
|
||||
pub async fn serve_https(
|
||||
config: HttpsConfig,
|
||||
cert_store: Arc<CertStore>,
|
||||
|
@ -41,6 +48,18 @@ pub async fn serve_https(
|
|||
) -> Result<()> {
|
||||
let config = Arc::new(config);
|
||||
|
||||
let meter = opentelemetry::global::meter("tricot");
|
||||
let metrics = Arc::new(HttpsMetrics {
|
||||
requests_received: meter
|
||||
.u64_counter("https_requests_received")
|
||||
.with_description("Total number of requests received over HTTPS")
|
||||
.init(),
|
||||
requests_served: meter
|
||||
.u64_counter("https_requests_served")
|
||||
.with_description("Total number of requests served over HTTPS")
|
||||
.init(),
|
||||
});
|
||||
|
||||
let mut tls_cfg = rustls::ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
|
@ -71,6 +90,7 @@ pub async fn serve_https(
|
|||
let rx_proxy_config = rx_proxy_config.clone();
|
||||
let tls_acceptor = tls_acceptor.clone();
|
||||
let config = config.clone();
|
||||
let metrics = metrics.clone();
|
||||
|
||||
let mut must_exit_2 = must_exit.clone();
|
||||
let conn = tokio::spawn(async move {
|
||||
|
@ -84,7 +104,8 @@ pub async fn serve_https(
|
|||
let https_config = config.clone();
|
||||
let proxy_config: Arc<ProxyConfig> =
|
||||
rx_proxy_config.borrow().clone();
|
||||
handle_outer(remote_addr, req, https_config, proxy_config)
|
||||
let metrics = metrics.clone();
|
||||
handle_outer(remote_addr, req, https_config, proxy_config, metrics)
|
||||
}),
|
||||
)
|
||||
.with_upgrades();
|
||||
|
@ -124,17 +145,43 @@ async fn handle_outer(
|
|||
req: Request<Body>,
|
||||
https_config: Arc<HttpsConfig>,
|
||||
proxy_config: Arc<ProxyConfig>,
|
||||
metrics: Arc<HttpsMetrics>,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
match handle(remote_addr, req, https_config, proxy_config).await {
|
||||
let mut tags = vec![
|
||||
KeyValue::new("method", req.method().to_string()),
|
||||
KeyValue::new(
|
||||
"host",
|
||||
req.uri()
|
||||
.authority()
|
||||
.map(|auth| auth.to_string())
|
||||
.or_else(|| {
|
||||
req.headers()
|
||||
.get("host")
|
||||
.map(|host| host.to_str().unwrap_or_default().to_string())
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
];
|
||||
metrics.requests_received.add(1, &tags);
|
||||
|
||||
let resp = match handle(remote_addr, req, https_config, proxy_config, &mut tags).await {
|
||||
Err(e) => {
|
||||
warn!("Handler error: {}", e);
|
||||
Ok(Response::builder()
|
||||
Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!("{}", e)))
|
||||
.unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
Ok(r) => Ok(r),
|
||||
}
|
||||
Ok(r) => r,
|
||||
};
|
||||
|
||||
tags.push(KeyValue::new(
|
||||
"response_code",
|
||||
resp.status().as_u16().to_string(),
|
||||
));
|
||||
metrics.requests_served.add(1, &tags);
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
// Custom echo service, handling two different routes and a
|
||||
|
@ -144,6 +191,7 @@ async fn handle(
|
|||
req: Request<Body>,
|
||||
https_config: Arc<HttpsConfig>,
|
||||
proxy_config: Arc<ProxyConfig>,
|
||||
tags: &mut Vec<KeyValue>,
|
||||
) -> Result<Response<Body>, anyhow::Error> {
|
||||
let method = req.method().clone();
|
||||
let uri = req.uri().to_string();
|
||||
|
@ -184,6 +232,18 @@ async fn handle(
|
|||
});
|
||||
|
||||
if let Some(proxy_to) = best_match {
|
||||
tags.push(KeyValue::new("service_name", proxy_to.service_name.clone()));
|
||||
tags.push(KeyValue::new(
|
||||
"target_addr",
|
||||
proxy_to.target_addr.to_string(),
|
||||
));
|
||||
tags.push(KeyValue::new(
|
||||
"https_target",
|
||||
proxy_to.https_target.to_string(),
|
||||
));
|
||||
tags.push(KeyValue::new("same_node", proxy_to.same_node.to_string()));
|
||||
tags.push(KeyValue::new("same_site", proxy_to.same_site.to_string()));
|
||||
|
||||
proxy_to.calls.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
debug!("{}{} -> {}", host, path, proxy_to);
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -15,6 +15,7 @@ mod cert_store;
|
|||
mod consul;
|
||||
mod http;
|
||||
mod https;
|
||||
mod metrics;
|
||||
mod proxy_config;
|
||||
mod reverse_proxy;
|
||||
mod tls_util;
|
||||
|
@ -80,6 +81,10 @@ struct Opt {
|
|||
)]
|
||||
pub https_bind_addr: SocketAddr,
|
||||
|
||||
/// Bind address for metrics server (Prometheus format over HTTP)
|
||||
#[structopt(long = "metrics-bind-addr", env = "TRICOT_METRICS_BIND_ADDR")]
|
||||
pub metrics_bind_addr: Option<SocketAddr>,
|
||||
|
||||
/// E-mail address for Let's Encrypt certificate requests
|
||||
#[structopt(long = "letsencrypt-email", env = "TRICOT_LETSENCRYPT_EMAIL")]
|
||||
pub letsencrypt_email: String,
|
||||
|
@ -123,6 +128,8 @@ async fn main() {
|
|||
let _ = provoke_exit.send(true);
|
||||
};
|
||||
|
||||
let metrics_server = metrics::MetricsServer::init(opt.metrics_bind_addr);
|
||||
|
||||
let consul_config = consul::ConsulConfig {
|
||||
addr: opt.consul_addr.clone(),
|
||||
ca_cert: opt.consul_ca_cert.clone(),
|
||||
|
@ -143,6 +150,13 @@ async fn main() {
|
|||
exit_on_err.clone(),
|
||||
);
|
||||
|
||||
let metrics_task = tokio::spawn(
|
||||
metrics_server
|
||||
.run(wait_from(exit_signal.clone()))
|
||||
.map_err(exit_on_err.clone())
|
||||
.then(|_| async { info!("Metrics server exited") }),
|
||||
);
|
||||
|
||||
let http_task = tokio::spawn(
|
||||
http::serve_http(
|
||||
opt.http_bind_addr,
|
||||
|
@ -176,6 +190,7 @@ async fn main() {
|
|||
|
||||
let dump_task = tokio::spawn(dump_config_on_change(rx_proxy_config, exit_signal.clone()));
|
||||
|
||||
let _ = metrics_task.await.expect("Tokio task await failure");
|
||||
let _ = http_task.await.expect("Tokio task await failure");
|
||||
let _ = https_task.await.expect("Tokio task await failure");
|
||||
let _ = dump_task.await.expect("Tokio task await failure");
|
||||
|
|
83
src/metrics.rs
Normal file
83
src/metrics.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use futures::future::*;
|
||||
use log::*;
|
||||
|
||||
use hyper::{
|
||||
header::CONTENT_TYPE,
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Method, Request, Response, Server,
|
||||
};
|
||||
use opentelemetry_prometheus::PrometheusExporter;
|
||||
use prometheus::{Encoder, TextEncoder};
|
||||
|
||||
pub struct MetricsServer {
|
||||
bind_addr: Option<SocketAddr>,
|
||||
exporter: PrometheusExporter,
|
||||
}
|
||||
|
||||
impl MetricsServer {
|
||||
pub fn init(bind_addr: Option<SocketAddr>) -> MetricsServer {
|
||||
let exporter = opentelemetry_prometheus::exporter().init();
|
||||
Self {
|
||||
bind_addr,
|
||||
exporter,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(self, shutdown_signal: impl Future<Output = ()>) -> Result<()> {
|
||||
if let Some(addr) = self.bind_addr {
|
||||
let metrics_server = Arc::new(self);
|
||||
|
||||
let make_svc = make_service_fn(move |_conn| {
|
||||
let metrics_server = metrics_server.clone();
|
||||
async move {
|
||||
Ok::<_, Infallible>(service_fn(move |req| {
|
||||
metrics_server.clone().serve_req(req)
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
let server = Server::bind(&addr).serve(make_svc);
|
||||
let graceful = server.with_graceful_shutdown(shutdown_signal);
|
||||
info!("Metrics server listening on http://{}", addr);
|
||||
|
||||
graceful.await?;
|
||||
} else {
|
||||
info!("Metrics server is disabled");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn serve_req(
|
||||
self: Arc<MetricsServer>,
|
||||
req: Request<Body>,
|
||||
) -> Result<Response<Body>, hyper::Error> {
|
||||
debug!("{} {}", req.method(), req.uri());
|
||||
|
||||
let response = match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, "/metrics") => {
|
||||
let mut buffer = vec![];
|
||||
let encoder = TextEncoder::new();
|
||||
let metric_families = self.exporter.registry().gather();
|
||||
encoder.encode(&metric_families, &mut buffer).unwrap();
|
||||
|
||||
Response::builder()
|
||||
.status(200)
|
||||
.header(CONTENT_TYPE, encoder.format_type())
|
||||
.body(Body::from(buffer))
|
||||
.unwrap()
|
||||
}
|
||||
_ => Response::builder()
|
||||
.status(404)
|
||||
.body(Body::from("Not implemented"))
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ use std::sync::{atomic, Arc};
|
|||
use std::{cmp, time::Duration};
|
||||
|
||||
use anyhow::Result;
|
||||
use opentelemetry::{metrics, KeyValue};
|
||||
|
||||
use futures::future::BoxFuture;
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
|
@ -38,6 +39,15 @@ impl HostDescription {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for HostDescription {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
HostDescription::Hostname(h) => write!(f, "{}", h),
|
||||
HostDescription::Pattern(p) => write!(f, "Pattern('{}')", p.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProxyEntry {
|
||||
/// Publicly exposed TLS hostnames for matching this rule
|
||||
|
@ -47,6 +57,8 @@ pub struct ProxyEntry {
|
|||
/// Priority with which this rule is considered (highest first)
|
||||
pub priority: u32,
|
||||
|
||||
/// Consul service name
|
||||
pub service_name: String,
|
||||
/// Node address (ip+port) to handle requests that match this entry
|
||||
pub target_addr: SocketAddr,
|
||||
/// Is the target serving HTTPS instead of HTTP?
|
||||
|
@ -75,14 +87,11 @@ impl std::fmt::Display for ProxyEntry {
|
|||
write!(f, "https://")?;
|
||||
}
|
||||
write!(f, "{} ", self.target_addr)?;
|
||||
match &self.host {
|
||||
HostDescription::Hostname(h) => write!(f, "{}", h)?,
|
||||
HostDescription::Pattern(p) => write!(f, "Pattern('{}')", p.as_str())?,
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{} {}",
|
||||
self.path_prefix.as_ref().unwrap_or(&String::new()),
|
||||
"{}{} {}",
|
||||
self.host,
|
||||
self.path_prefix.as_deref().unwrap_or_default(),
|
||||
self.priority
|
||||
)?;
|
||||
if self.same_node {
|
||||
|
@ -113,6 +122,7 @@ fn retry_to_time(retries: u32, max_time: Duration) -> Duration {
|
|||
}
|
||||
|
||||
fn parse_tricot_tag(
|
||||
service_name: String,
|
||||
tag: &str,
|
||||
target_addr: SocketAddr,
|
||||
add_headers: &[(String, String)],
|
||||
|
@ -148,6 +158,7 @@ fn parse_tricot_tag(
|
|||
};
|
||||
|
||||
Some(ProxyEntry {
|
||||
service_name,
|
||||
target_addr,
|
||||
https_target: (splits[0] == "tricot-https"),
|
||||
host,
|
||||
|
@ -178,7 +189,7 @@ fn parse_consul_catalog(
|
|||
|
||||
let mut entries = vec![];
|
||||
|
||||
for (_, svc) in catalog.services.iter() {
|
||||
for (service_name, svc) in catalog.services.iter() {
|
||||
let ip_addr = match svc.address.parse() {
|
||||
Ok(ip) => ip,
|
||||
_ => match catalog.node.address.parse() {
|
||||
|
@ -210,7 +221,14 @@ fn parse_consul_catalog(
|
|||
}
|
||||
|
||||
for tag in svc.tags.iter() {
|
||||
if let Some(ent) = parse_tricot_tag(tag, addr, &add_headers[..], same_node, same_site) {
|
||||
if let Some(ent) = parse_tricot_tag(
|
||||
service_name.clone(),
|
||||
tag,
|
||||
addr,
|
||||
&add_headers[..],
|
||||
same_node,
|
||||
same_site,
|
||||
) {
|
||||
entries.push(ent);
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +257,7 @@ pub fn spawn_proxy_config_task(
|
|||
entries: Vec::new(),
|
||||
}));
|
||||
|
||||
let metrics = ProxyConfigMetrics::new(rx.clone());
|
||||
let consul = Arc::new(consul);
|
||||
|
||||
tokio::spawn(async move {
|
||||
|
@ -348,11 +367,46 @@ pub fn spawn_proxy_config_task(
|
|||
|
||||
tx.send(Arc::new(config)).expect("Internal error");
|
||||
}
|
||||
|
||||
drop(metrics); // ensure Metrics lives up to here
|
||||
});
|
||||
|
||||
rx
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
struct ProxyConfigMetrics {
|
||||
_proxy_config_entries: metrics::ValueObserver<u64>,
|
||||
}
|
||||
|
||||
impl ProxyConfigMetrics {
|
||||
fn new(rx: watch::Receiver<Arc<ProxyConfig>>) -> Self {
|
||||
let meter = opentelemetry::global::meter("tricot");
|
||||
Self {
|
||||
_proxy_config_entries: meter
|
||||
.u64_value_observer("proxy_config_entries", move |observer| {
|
||||
let mut patterns = HashMap::new();
|
||||
for ent in rx.borrow().entries.iter() {
|
||||
let pat = format!(
|
||||
"{}{}",
|
||||
ent.host,
|
||||
ent.path_prefix.as_deref().unwrap_or_default()
|
||||
);
|
||||
*patterns.entry(pat).or_default() += 1;
|
||||
}
|
||||
for (pat, num) in patterns {
|
||||
observer.observe(num, &[KeyValue::new("host", pat)]);
|
||||
}
|
||||
})
|
||||
.with_description("Number of proxy entries (back-ends) configured in Tricot")
|
||||
.init(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in a new issue