diff --git a/app/Actions/Server/InstallLogDrain.php b/app/Actions/Server/InstallLogDrain.php
index 79acda8e7..e4e43dc1b 100644
--- a/app/Actions/Server/InstallLogDrain.php
+++ b/app/Actions/Server/InstallLogDrain.php
@@ -10,11 +10,18 @@ class InstallLogDrain
use AsAction;
public function handle(Server $server, string $type)
{
- if ($type === 'newrelic') {
- if (!$server->settings->is_logdrain_newrelic_enabled) {
- throw new \Exception('New Relic log drain is not enabled.');
- }
- $config = base64_encode("
+ try {
+ if ($type === 'none') {
+ $command = [
+ "echo 'Stopping old Fluent Bit'",
+ "docker rm -f coolify-log-drain || true",
+ ];
+ return instant_remote_process($command, $server);
+ } else if ($type === 'newrelic') {
+ if (!$server->settings->is_logdrain_newrelic_enabled) {
+ throw new \Exception('New Relic log drain is not enabled.');
+ }
+ $config = base64_encode("
[SERVICE]
Flush 5
Daemon off
@@ -40,18 +47,36 @@ public function handle(Server $server, string $type)
# https://log-api.newrelic.com/log/v1 - US
base_uri \${BASE_URI}
");
- } else if ($type === 'highlight') {
- if (!$server->settings->is_logdrain_highlight_enabled) {
- throw new \Exception('Highlight log drain is not enabled.');
- }
- $config = base64_encode('
+ } else if ($type === 'highlight') {
+ if (!$server->settings->is_logdrain_highlight_enabled) {
+ throw new \Exception('Highlight log drain is not enabled.');
+ }
+ $config = base64_encode("
+[SERVICE]
+ Flush 1
+ Daemon off
+ Log_Level debug
+[INPUT]
+ Name forward
+ tag \${HIGHLIGHT_PROJECT_ID}
+ Buffer_Chunk_Size 1M
+ Buffer_Max_Size 6M
+[OUTPUT]
+ Name forward
+ Match *
+ Host otel.highlight.io
+ Port 24224
+");
+ } else if ($type === 'axiom') {
+ if (!$server->settings->is_logdrain_axiom_enabled) {
+ throw new \Exception('Axiom log drain is not enabled.');
+ }
+ $config = base64_encode("
[SERVICE]
Flush 5
Daemon off
- Tag container_logs
[INPUT]
Name forward
- tag ${HIGHLIGHT_PROJECT_ID}
Buffer_Chunk_Size 1M
Buffer_Max_Size 6M
[FILTER]
@@ -63,14 +88,24 @@ public function handle(Server $server, string $type)
Match *
Set server_name {$server->name}
[OUTPUT]
- Name forward
- Match *
- Host otel.highlight.io
- Port 24224
-');
- }
+ Name http
+ Match *
+ Host api.axiom.co
+ Port 443
+ URI /v1/datasets/\${AXIOM_DATASET_NAME}/ingest
+ # Authorization Bearer should be an API token
+ Header Authorization Bearer \${AXIOM_API_KEY}
+ compress gzip
+ format json
+ json_date_key _time
+ json_date_format iso8601
+ tls On
+");
+ } else {
+ throw new \Exception('Unknown log drain type.');
+ }
- $compose = base64_encode("
+ $compose = base64_encode("
services:
coolify-log-drain:
image: cr.fluentbit.io/fluent/fluent-bit:2.0
@@ -83,7 +118,7 @@ public function handle(Server $server, string $type)
ports:
- 127.0.0.1:24224:24224
");
- $readme = base64_encode('# New Relic Log Drain
+ $readme = base64_encode('# New Relic Log Drain
This log drain is based on [Fluent Bit](https://fluentbit.io/) and New Relic Log Forwarder.
Files:
@@ -91,40 +126,48 @@ public function handle(Server $server, string $type)
- `docker-compose.yml` - docker-compose file to run Fluent Bit
- `.env` - environment variables for Fluent Bit
');
- $license_key = $server->settings->logdrain_newrelic_license_key;
- $base_uri = $server->settings->logdrain_newrelic_base_uri;
- $base_path = config('coolify.base_config_path');
+ $license_key = $server->settings->logdrain_newrelic_license_key;
+ $base_uri = $server->settings->logdrain_newrelic_base_uri;
+ $base_path = config('coolify.base_config_path');
- $config_path = $base_path . '/log-drains';
- $fluent_bit_config = $config_path . '/fluent-bit.conf';
- $compose_path = $config_path . '/docker-compose.yml';
- $readme_path = $config_path . '/README.md';
- $command = [
- "echo 'Saving configuration'",
- "mkdir -p $config_path",
- "echo '{$config}' | base64 -d > $fluent_bit_config",
- "echo '{$compose}' | base64 -d > $compose_path",
- "echo '{$readme}' | base64 -d > $readme_path",
- "rm $config_path/.env || true",
+ $config_path = $base_path . '/log-drains';
+ $fluent_bit_config = $config_path . '/fluent-bit.conf';
+ $compose_path = $config_path . '/docker-compose.yml';
+ $readme_path = $config_path . '/README.md';
+ $command = [
+ "echo 'Saving configuration'",
+ "mkdir -p $config_path",
+ "echo '{$config}' | base64 -d > $fluent_bit_config",
+ "echo '{$compose}' | base64 -d > $compose_path",
+ "echo '{$readme}' | base64 -d > $readme_path",
+ "test -f $config_path/.env && rm $config_path/.env",
- ];
- if ($type === 'newrelic') {
- $add_envs_command = [
- "echo LICENSE_KEY=$license_key >> $config_path/.env",
- "echo BASE_URI=$base_uri >> $config_path/.env",
];
- } else if ($type === 'highlight') {
- $add_envs_command = [
- "echo HIGHLIGHT_PROJECT_ID={$server->settings->logdrain_highlight_project_id} >> $config_path/.env",
+ if ($type === 'newrelic') {
+ $add_envs_command = [
+ "echo LICENSE_KEY=$license_key >> $config_path/.env",
+ "echo BASE_URI=$base_uri >> $config_path/.env",
+ ];
+ } else if ($type === 'highlight') {
+ $add_envs_command = [
+ "echo HIGHLIGHT_PROJECT_ID={$server->settings->logdrain_highlight_project_id} >> $config_path/.env",
+ ];
+ } else if ($type === 'axiom') {
+ $add_envs_command = [
+ "echo AXIOM_DATASET_NAME={$server->settings->logdrain_axiom_dataset_name} >> $config_path/.env",
+ "echo AXIOM_API_KEY={$server->settings->logdrain_axiom_api_key} >> $config_path/.env",
+ ];
+ }
+ $restart_command = [
+ "echo 'Stopping old Fluent Bit'",
+ "cd $config_path && docker rm -f coolify-log-drain || true",
+ "echo 'Starting Fluent Bit'",
+ "cd $config_path && docker compose up -d --remove-orphans",
];
+ $command = array_merge($command, $add_envs_command, $restart_command);
+ return instant_remote_process($command, $server);
+ } catch (\Throwable $e) {
+ return handleError($e);
}
- $restart_command = [
- "echo 'Stopping old Fluent Bit'",
- "cd $config_path && docker rm -f coolify-log-drain || true",
- "echo 'Starting Fluent Bit'",
- "cd $config_path && docker compose up -d --remove-orphans",
- ];
- $command = array_merge($command, $add_envs_command, $restart_command);
- return instant_remote_process($command, $server);
}
}
diff --git a/app/Http/Livewire/Server/LogDrains.php b/app/Http/Livewire/Server/LogDrains.php
index 823886b3f..4545e205f 100644
--- a/app/Http/Livewire/Server/LogDrains.php
+++ b/app/Http/Livewire/Server/LogDrains.php
@@ -15,32 +15,70 @@ class LogDrains extends Component
'server.settings.logdrain_newrelic_base_uri' => 'required|string',
'server.settings.is_logdrain_highlight_enabled' => 'required|boolean',
'server.settings.logdrain_highlight_project_id' => 'required|string',
+ 'server.settings.is_logdrain_axiom_enabled' => 'required|boolean',
+ 'server.settings.logdrain_axiom_dataset_name' => 'required|string',
+ 'server.settings.logdrain_axiom_api_key' => 'required|string',
+ ];
+ protected $validationAttributes = [
+ 'server.settings.is_logdrain_newrelic_enabled' => 'New Relic log drain',
+ 'server.settings.logdrain_newrelic_license_key' => 'New Relic license key',
+ 'server.settings.logdrain_newrelic_base_uri' => 'New Relic base URI',
+ 'server.settings.is_logdrain_highlight_enabled' => 'Highlight log drain',
+ 'server.settings.logdrain_highlight_project_id' => 'Highlight project ID',
+ 'server.settings.is_logdrain_axiom_enabled' => 'Axiom log drain',
+ 'server.settings.logdrain_axiom_dataset_name' => 'Axiom dataset name',
+ 'server.settings.logdrain_axiom_api_key' => 'Axiom API key',
];
- public function mount() {
+ public function mount()
+ {
$this->parameters = get_route_parameters();
try {
- $this->server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->first();
- if (is_null($this->server)) {
+ $server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->first();
+ if (is_null($server)) {
return redirect()->route('server.all');
}
+ $this->server = $server;
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
- public function configureLogDrain(string $type) {
+ public function configureLogDrain()
+ {
try {
- $this->server->logDrain($type);
+ if ($this->server->settings->is_logdrain_newrelic_enabled) {
+ $this->server->logDrain('newrelic');
+ } else if ($this->server->settings->is_logdrain_highlight_enabled) {
+ $this->server->logDrain('highlight');
+ } else if ($this->server->settings->is_logdrain_axiom_enabled) {
+ $this->server->logDrain('axiom');
+ } else {
+ $this->server->logDrain('none');
+ $this->emit('serverRefresh');
+ $this->emit('success', 'Log drain service stopped.');
+ return;
+ }
$this->emit('serverRefresh');
- $this->emit('success', 'Log drain configured successfully.');
+ $this->emit('success', 'Log drain service started successfully.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
- public function instantSave(string $type) {
- $this->submit($type);
+ public function instantSave(string $type)
+ {
+ try {
+ $ok = $this->submit($type);
+ ray($ok);
+ if (!$ok) {
+ return;
+ }
+ $this->configureLogDrain();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
}
- public function submit(string $type) {
+ public function submit(string $type)
+ {
try {
$this->resetErrorBag();
if ($type === 'newrelic') {
@@ -51,6 +89,7 @@ public function submit(string $type) {
]);
$this->server->settings->update([
'is_logdrain_highlight_enabled' => false,
+ 'is_logdrain_axiom_enabled' => false,
]);
} else if ($type === 'highlight') {
$this->validate([
@@ -59,12 +98,38 @@ public function submit(string $type) {
]);
$this->server->settings->update([
'is_logdrain_newrelic_enabled' => false,
+ 'is_logdrain_axiom_enabled' => false,
+ ]);
+ } else if ($type === 'axiom') {
+ $this->validate([
+ 'server.settings.is_logdrain_axiom_enabled' => 'required|boolean',
+ 'server.settings.logdrain_axiom_dataset_name' => 'required|string',
+ 'server.settings.logdrain_axiom_api_key' => 'required|string',
+ ]);
+ $this->server->settings->update([
+ 'is_logdrain_newrelic_enabled' => false,
+ 'is_logdrain_highlight_enabled' => false,
]);
}
$this->server->settings->save();
$this->emit('success', 'Settings saved successfully.');
+ return true;
} catch (\Throwable $e) {
- return handleError($e, $this);
+ if ($type === 'newrelic') {
+ $this->server->settings->update([
+ 'is_logdrain_newrelic_enabled' => false,
+ ]);
+ } else if ($type === 'highlight') {
+ $this->server->settings->update([
+ 'is_logdrain_highlight_enabled' => false,
+ ]);
+ } else if ($type === 'axiom') {
+ $this->server->settings->update([
+ 'is_logdrain_axiom_enabled' => false,
+ ]);
+ }
+ handleError($e, $this);
+ return false;
}
}
public function render()
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index c74c973f9..e67a43e46 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -843,7 +843,6 @@ private function generate_compose_file()
'fluentd-address' => "tcp://127.0.0.1:24224",
'fluentd-async' => "true",
'fluentd-sub-second-precision' => "true",
-
]
],
'healthcheck' => [
@@ -1021,6 +1020,10 @@ private function build_image()
listen [::]:80;
server_name localhost;
+ // real_ip_header X-Forwarded-For;
+ // proxy_set_header X-Real-IP \$remote_addr;
+ // proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+
location / {
root /usr/share/nginx/html;
index index.html;
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 6fa5bda7b..83df8d61a 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -61,6 +61,8 @@ protected static function booted()
public $casts = [
'proxy' => SchemalessAttributes::class,
+ 'logdrain_axiom_api_key' => 'encrypted',
+ 'logdrain_newrelic_license_key' => 'encrypted',
];
protected $schemalessAttributes = [
'proxy',
diff --git a/database/migrations/2023_11_16_220647_add_log_drains.php b/database/migrations/2023_11_16_220647_add_log_drains.php
index 82274a999..05b1ed054 100644
--- a/database/migrations/2023_11_16_220647_add_log_drains.php
+++ b/database/migrations/2023_11_16_220647_add_log_drains.php
@@ -18,6 +18,11 @@ public function up(): void
$table->boolean('is_logdrain_highlight_enabled')->default(false);
$table->string('logdrain_highlight_project_id')->nullable();
+
+ $table->boolean('is_logdrain_axiom_enabled')->default(false);
+ $table->string('logdrain_axiom_dataset_name')->nullable();
+ $table->string('logdrain_axiom_api_key')->nullable();
+
});
}
@@ -33,6 +38,10 @@ public function down(): void
$table->dropColumn('is_logdrain_highlight_enabled');
$table->dropColumn('logdrain_highlight_project_id');
+
+ $table->dropColumn('is_logdrain_axiom_enabled');
+ $table->dropColumn('logdrain_axiom_dataset_name');
+ $table->dropColumn('logdrain_axiom_api_key');
});
}
};
diff --git a/resources/views/livewire/server/log-drains.blade.php b/resources/views/livewire/server/log-drains.blade.php
index 38c5b0cc4..6a2a48349 100644
--- a/resources/views/livewire/server/log-drains.blade.php
+++ b/resources/views/livewire/server/log-drains.blade.php
@@ -2,45 +2,62 @@