fix(log-drain): send Coolify labels to Fluent Bit drains

Containers without the Coolify default variables sent no project,
environment, or service to the drain. The fluentd driver now also sends
the Coolify container labels; the built-in configs use them as a
fallback and add coolify.service_name.

Closes #8415

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-11-03 22:42:37 +01:00
co-authored by Claude Opus 5.5
parent b83b97f7e6
commit 8d07d178f0
7 changed files with 99 additions and 21 deletions
@@ -175,5 +175,5 @@ it('changes the configuration version when the generated files change', function
});
expect([StartLogDrain::CONFIG_VERSION, hash('sha256', $hashes->implode("\0"))])
->toBe(['1', '11916cd1142514c158a6fbe812ce468e3fe80fc79428cef6ba2654c86aa384ba']);
->toBe(['2', '4f4ceaf642f0de8009e256b54f2bbe2f842190297bbf2da92f2b31dd0a9baf3d']);
});
@@ -75,3 +75,30 @@ test('a server name with spaces is written as a single fluent-bit value', functi
'new relic' => [['is_logdrain_newrelic_enabled' => true, 'logdrain_newrelic_license_key' => 'key', 'logdrain_newrelic_base_uri' => 'https://log-api.newrelic.com/log/v1']],
'axiom' => [['is_logdrain_axiom_enabled' => true, 'logdrain_axiom_dataset_name' => 'dataset', 'logdrain_axiom_api_key' => 'key']],
]);
test('the built-in fluent-bit config uses the container labels only when the default variables are missing', function (array $settings) {
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
'private_key_id' => PrivateKey::factory()->create(['team_id' => $team->id])->id,
]);
$server->settings()->update($settings);
$commands = new Collection;
Process::fake(function ($process) use ($commands) {
$commands->push(remoteProcessScript($process));
return Process::result();
});
StartLogDrain::run($server->fresh());
preg_match("/echo '([A-Za-z0-9+\\/=]+)' \\| base64 -d \\| tee \\S+\\/fluent-bit\\.conf/", $commands->implode("\n"), $matches);
$config = base64_decode($matches[1]);
expect($config)->toMatch('/Rename\s+COOLIFY_PROJECT_NAME coolify\.project_name\n(.*\n)*\s+Rename\s+coolify\.projectName coolify\.project_name\n(.*\n)*\s+Remove\s+coolify\.projectName\n/')
->and($config)->toMatch('/Rename\s+coolify\.serviceName coolify\.service_name\n/');
})->with([
'new relic' => [['is_logdrain_newrelic_enabled' => true, 'logdrain_newrelic_license_key' => 'key', 'logdrain_newrelic_base_uri' => 'https://log-api.newrelic.com/log/v1']],
'axiom' => [['is_logdrain_axiom_enabled' => true, 'logdrain_axiom_dataset_name' => 'dataset', 'logdrain_axiom_api_key' => 'key']],
]);
@@ -180,6 +180,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
image: 'referenceapplication0001_web:abcdef0123456789abcdef0123456789abcdef01'
@@ -265,6 +266,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
my-app:
@@ -336,6 +338,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
api.v2:
@@ -390,6 +393,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
admin:
@@ -462,6 +466,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
blog:
@@ -537,6 +542,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
db:
@@ -602,6 +608,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
sidecar:
@@ -656,6 +663,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
worker:
@@ -718,6 +726,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
volumes:
@@ -949,6 +958,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
image: 'referenceapplication0001_web:abcdef0123456789abcdef0123456789abcdef01'
@@ -1048,6 +1058,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
my-app:
@@ -1128,6 +1139,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
api.v2:
@@ -1203,6 +1215,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
admin:
@@ -1284,6 +1297,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
blog:
@@ -1366,6 +1380,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
db:
@@ -1433,6 +1448,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
sidecar:
@@ -1489,6 +1505,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
worker:
@@ -1553,6 +1570,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
volumes:
@@ -1812,6 +1830,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
image: 'referenceapplication0001_web:pr-7'
@@ -1911,6 +1930,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
my-app-pr-7:
@@ -1996,6 +2016,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
api.v2-pr-7:
@@ -2076,6 +2097,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
admin-pr-7:
@@ -2162,6 +2184,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
blog-pr-7:
@@ -2248,6 +2271,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
db-pr-7:
@@ -2317,6 +2341,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
sidecar-pr-7:
@@ -2373,6 +2398,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
worker-pr-7:
@@ -2439,6 +2465,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
volumes:
@@ -2658,6 +2685,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
image: 'referenceapplication0001_web:pr-8'
@@ -2719,6 +2747,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
my-app-pr-8:
@@ -2766,6 +2795,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
api.v2-pr-8:
@@ -2812,6 +2842,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
admin-pr-8:
@@ -2860,6 +2891,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
blog-pr-8:
@@ -2907,6 +2939,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
db-pr-8:
@@ -2964,6 +2997,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
sidecar-pr-8:
@@ -3008,6 +3042,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
worker-pr-8:
@@ -3062,6 +3097,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
env_file:
- .env
volumes:
@@ -270,6 +270,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
api:
image: 'node:22-alpine'
build:
@@ -1149,6 +1150,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
api:
image: 'node:22-alpine'
build:
@@ -2071,6 +2073,7 @@
fluentd-async: 'true'
fluentd-sub-second-precision: 'true'
env: 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME'
labels: 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName'
api:
image: 'node:22-alpine'
build:
@@ -75,3 +75,11 @@ it('reports CloudWatch as an enabled drain that does not use Fluent Bit', functi
->and($axiom->isLogDrainEnabled())->toBeTrue()
->and($axiom->isFluentBitLogDrainEnabled())->toBeTrue();
});
it('sends the Coolify labels with fluentd, so containers without the default variables are identified', function () {
$server = serverWithLogDrainSettings(['is_logdrain_custom_enabled' => true]);
expect(generate_log_drain_configuration($server)['options'])
->toHaveKey('env', 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME')
->toHaveKey('labels', 'coolify.projectName,coolify.environmentName,coolify.resourceName,coolify.serviceName');
});