mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-14 22:20:30 +03:00
207 lines
5.4 KiB
Nix
207 lines
5.4 KiB
Nix
![]() |
{ lib, pkgs, ... }:
|
||
|
|
||
|
{
|
||
|
name = "vector-caddy-clickhouse";
|
||
|
meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
|
||
|
|
||
|
nodes = {
|
||
|
caddy =
|
||
|
{ config, pkgs, ... }:
|
||
|
{
|
||
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
||
|
|
||
|
services.caddy = {
|
||
|
enable = true;
|
||
|
virtualHosts = {
|
||
|
"http://caddy" = {
|
||
|
extraConfig = ''
|
||
|
encode gzip
|
||
|
|
||
|
file_server
|
||
|
root /srv
|
||
|
'';
|
||
|
logFormat = "
|
||
|
output file ${config.services.caddy.logDir}/access-caddy.log {
|
||
|
mode 0640
|
||
|
}
|
||
|
";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
systemd.services.vector.serviceConfig = {
|
||
|
SupplementaryGroups = [ "caddy" ];
|
||
|
};
|
||
|
|
||
|
services.vector = {
|
||
|
enable = true;
|
||
|
|
||
|
settings = {
|
||
|
sources = {
|
||
|
caddy-log = {
|
||
|
type = "file";
|
||
|
include = [ "/var/log/caddy/*.log" ];
|
||
|
};
|
||
|
};
|
||
|
|
||
|
transforms = {
|
||
|
caddy_logs_timestamp = {
|
||
|
type = "remap";
|
||
|
inputs = [ "caddy-log" ];
|
||
|
source = ''
|
||
|
.tmp_timestamp, err = parse_json!(.message).ts * 1000000
|
||
|
|
||
|
if err != null {
|
||
|
log("Unable to parse ts value: " + err, level: "error")
|
||
|
} else {
|
||
|
.timestamp = from_unix_timestamp!(to_int!(.tmp_timestamp), unit: "microseconds")
|
||
|
}
|
||
|
|
||
|
del(.tmp_timestamp)
|
||
|
'';
|
||
|
};
|
||
|
};
|
||
|
|
||
|
sinks = {
|
||
|
vector_sink = {
|
||
|
type = "vector";
|
||
|
inputs = [ "caddy_logs_timestamp" ];
|
||
|
address = "clickhouse:6000";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
client =
|
||
|
{ config, pkgs, ... }:
|
||
|
{
|
||
|
environment.systemPackages = [ pkgs.curl ];
|
||
|
};
|
||
|
|
||
|
clickhouse =
|
||
|
{ config, pkgs, ... }:
|
||
|
{
|
||
|
virtualisation.memorySize = 4096;
|
||
|
|
||
|
networking.firewall.allowedTCPPorts = [ 6000 ];
|
||
|
|
||
|
services.vector = {
|
||
|
enable = true;
|
||
|
|
||
|
settings = {
|
||
|
sources = {
|
||
|
vector_source = {
|
||
|
type = "vector";
|
||
|
address = "[::]:6000";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
sinks = {
|
||
|
clickhouse = {
|
||
|
type = "clickhouse";
|
||
|
inputs = [
|
||
|
"vector_source"
|
||
|
];
|
||
|
endpoint = "http://localhost:8123";
|
||
|
database = "caddy";
|
||
|
table = "access_logs";
|
||
|
date_time_best_effort = true;
|
||
|
skip_unknown_fields = true;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
services.clickhouse = {
|
||
|
enable = true;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
testScript =
|
||
|
let
|
||
|
# work around quote/substitution complexity by Nix, Perl, bash and SQL.
|
||
|
databaseDDL = pkgs.writeText "database.sql" "CREATE DATABASE IF NOT EXISTS caddy";
|
||
|
|
||
|
tableDDL = pkgs.writeText "table.sql" ''
|
||
|
CREATE TABLE IF NOT EXISTS caddy.access_logs (
|
||
|
timestamp DateTime64(6),
|
||
|
host LowCardinality(String),
|
||
|
message String,
|
||
|
)
|
||
|
ENGINE = MergeTree()
|
||
|
ORDER BY timestamp
|
||
|
PARTITION BY toYYYYMM(timestamp)
|
||
|
'';
|
||
|
|
||
|
tableViewBase = pkgs.writeText "table-view-base.sql" ''
|
||
|
CREATE TABLE IF NOT EXISTS caddy.access_logs_view_base (
|
||
|
timestamp DateTime64(6),
|
||
|
host LowCardinality(String),
|
||
|
request JSON,
|
||
|
status UInt16,
|
||
|
)
|
||
|
ENGINE = MergeTree()
|
||
|
ORDER BY timestamp
|
||
|
PARTITION BY toYYYYMM(timestamp)
|
||
|
'';
|
||
|
|
||
|
tableView = pkgs.writeText "table-view.sql" ''
|
||
|
CREATE MATERIALIZED VIEW IF NOT EXISTS caddy.access_logs_view TO caddy.access_logs_view_base
|
||
|
AS SELECT
|
||
|
timestamp,
|
||
|
host,
|
||
|
simpleJSONExtractRaw(message, 'request') AS request,
|
||
|
simpleJSONExtractRaw(message, 'status') AS status
|
||
|
FROM caddy.access_logs;
|
||
|
'';
|
||
|
|
||
|
selectQuery = pkgs.writeText "select.sql" ''
|
||
|
SELECT
|
||
|
timestamp,
|
||
|
request.host,
|
||
|
request.remote_ip,
|
||
|
request.proto,
|
||
|
request.method,
|
||
|
request.uri,
|
||
|
status
|
||
|
FROM caddy.access_logs_view_base
|
||
|
WHERE request.uri LIKE '%test-uri%'
|
||
|
FORMAT Pretty
|
||
|
'';
|
||
|
in
|
||
|
''
|
||
|
clickhouse.wait_for_unit("clickhouse")
|
||
|
clickhouse.wait_for_unit("vector")
|
||
|
clickhouse.wait_for_open_port(6000)
|
||
|
clickhouse.wait_for_open_port(8123)
|
||
|
|
||
|
clickhouse.succeed(
|
||
|
"cat ${databaseDDL} | clickhouse-client",
|
||
|
"cat ${tableDDL} | clickhouse-client",
|
||
|
"cat ${tableViewBase} | clickhouse-client",
|
||
|
"cat ${tableView} | clickhouse-client",
|
||
|
)
|
||
|
|
||
|
caddy.wait_for_unit("caddy")
|
||
|
caddy.wait_for_open_port(80)
|
||
|
caddy.wait_for_unit("vector")
|
||
|
caddy.wait_until_succeeds(
|
||
|
"journalctl -o cat -u vector.service | grep 'Vector has started'"
|
||
|
)
|
||
|
|
||
|
client.systemctl("start network-online.target")
|
||
|
client.wait_until_succeeds("curl http://caddy/test-uri")
|
||
|
|
||
|
caddy.wait_until_succeeds(
|
||
|
"journalctl -o cat -u vector.service | grep 'Found new file to watch. file=/var/log/caddy/access-caddy.log'"
|
||
|
)
|
||
|
|
||
|
clickhouse.wait_until_succeeds(
|
||
|
"cat ${selectQuery} | clickhouse-client | grep test-uri"
|
||
|
)
|
||
|
'';
|
||
|
}
|