Add log drain settings for New Relic,Highlight.io, and Axiom
This commit is contained in:
parent
6c7e091e1b
commit
88c5d87084
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -2,45 +2,62 @@
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
<h2>Log Drains</h2>
|
||||
<div class="pb-4">Sends resource logs to external services.</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border border-coolgray-500">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("newrelic")' id="server.settings.is_logdrain_newrelic_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit.prevent='submit("newrelic")' class="flex flex-col">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("newrelic")'
|
||||
id="server.settings.is_logdrain_newrelic_enabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_newrelic_base_uri" placeholder="https://log-api.eu.newrelic.com/log/v1" label="Endpoint (EU / US)" />
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_newrelic_license_key"
|
||||
label="License Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1" label="Endpoint (EU / US)" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
<x-forms.button wire:click="configureLogDrain('newrelic')">
|
||||
Configure On Server
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
<h3>Highlight.io</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("highlight")' id="server.settings.is_logdrain_highlight_enabled" label="Enabled" />
|
||||
<x-forms.checkbox instantSave='instantSave("highlight")'
|
||||
id="server.settings.is_logdrain_highlight_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit.prevent='submit("highlight")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_highlight_project_id" label="Project Id" />
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_highlight_project_id"
|
||||
label="Project Id" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
<x-forms.button wire:click="configureLogDrain('highlight')">
|
||||
Configure On Server
|
||||
</div>
|
||||
</form>
|
||||
<h3>Axiom</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("axiom")' id="server.settings.is_logdrain_axiom_enabled"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit.prevent='submit("axiom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_axiom_api_key"
|
||||
label="API Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_axiom_dataset_name" label="Dataset Name" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
Loading…
Reference in New Issue
Block a user