diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index cc8c0a707f9..3fd7e2048ae 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -233,3 +233,33 @@ dokku logs:set test vector-sink "http://?uri=https%3A//loggerservice.com%3A1234/ ``` Please read the [sink documentation](https://vector.dev/docs/reference/configuration/sinks/) for your sink of choice to configure the sink as desired. + +##### Configuring the app label + +Logs shipped by vector include the label `com.dokku.app-name`, which is an alias for the app name. This can be changed via the `app-label-alias` logs property with the `logs:set` command. Specifying a new alias will reload any running vector container. + +```shell +# setting the sink value in quotes is encouraged to avoid +# issues with ampersand encoding in shell commands +dokku logs:set node-js-app app-label-alias "app-name" +``` + +An alias may be removed by setting an empty value, which will also reload the running vector container. + +```shell +dokku logs:set node-js-app app-label-alias +``` + +Only one alias may be specified on a per-app basis at a given time. + +App label aliases can also be specified globally by specifying the `--global` flag to `logs:set` with no app name specified: + +```shell +dokku logs:set --global app-label-alias "app-name" +``` + +As with app-specific label alias settings, the global value may also be cleared by setting no value. + +```shell +dokku logs:set --global app-label-alias +``` diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index d1acb75fc25..fa9fbf2c322 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -257,7 +257,7 @@ func writeVectorConfig() error { data.Sources[fmt.Sprintf("docker-source:%s", inflectedAppName)] = vectorSource{ Type: "docker_logs", - IncludeLabels: []string{fmt.Sprintf("com.dokku.app-name=%s", appName)}, + IncludeLabels: []string{fmt.Sprintf("%s=%s", reportComputedAppLabelAlias(appName), appName)}, } data.Sinks[fmt.Sprintf("docker-sink:%s", inflectedAppName)] = sink @@ -272,7 +272,7 @@ func writeVectorConfig() error { data.Sources["docker-global-source"] = vectorSource{ Type: "docker_logs", - IncludeLabels: []string{"com.dokku.app-name"}, + IncludeLabels: []string{reportGlobalAppLabelAlias("global")}, } data.Sinks["docker-global-sink"] = sink diff --git a/plugins/logs/logs.go b/plugins/logs/logs.go index 6d24d8755cd..7e0f67fbbd5 100644 --- a/plugins/logs/logs.go +++ b/plugins/logs/logs.go @@ -10,18 +10,23 @@ import ( // MaxSize is the default max retention size for docker logs const MaxSize = "10m" +// AppLabelAlias is the property key for the app label alias +const AppLabelAlias = "com.dokku.app-name" + var ( // DefaultProperties is a map of all valid logs properties with corresponding default property values DefaultProperties = map[string]string{ - "max-size": "", - "vector-sink": "", + "app-label-alias": AppLabelAlias, + "max-size": MaxSize, + "vector-sink": "", } // GlobalProperties is a map of all valid global logs properties GlobalProperties = map[string]bool{ - "max-size": true, - "vector-image": true, - "vector-sink": true, + "app-label-alias": true, + "max-size": true, + "vector-image": true, + "vector-sink": true, } ) diff --git a/plugins/logs/report.go b/plugins/logs/report.go index ed3d7d227b0..781ea486f69 100644 --- a/plugins/logs/report.go +++ b/plugins/logs/report.go @@ -11,12 +11,15 @@ func ReportSingleApp(appName string, format string, infoFlag string) error { } flags := map[string]common.ReportFunc{ - "--logs-computed-max-size": reportComputedMaxSize, - "--logs-global-max-size": reportGlobalMaxSize, - "--logs-global-vector-sink": reportGlobalVectorSink, - "--logs-max-size": reportMaxSize, - "--logs-vector-global-image": reportVectorGlobalImage, - "--logs-vector-sink": reportVectorSink, + "--logs-computed-app-label-alias": reportComputedAppLabelAlias, + "--logs-computed-max-size": reportComputedMaxSize, + "--logs-global-app-label-alias": reportGlobalAppLabelAlias, + "--logs-global-max-size": reportGlobalMaxSize, + "--logs-global-vector-sink": reportGlobalVectorSink, + "--logs-app-label-alias": reportAppLabelAlias, + "--logs-max-size": reportMaxSize, + "--logs-vector-global-image": reportVectorGlobalImage, + "--logs-vector-sink": reportVectorSink, } flagKeys := []string{} @@ -30,6 +33,23 @@ func ReportSingleApp(appName string, format string, infoFlag string) error { return common.ReportSingleApp("logs", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter) } +func reportComputedAppLabelAlias(appName string) string { + value := reportAppLabelAlias(appName) + if value == "" { + value = reportGlobalAppLabelAlias(appName) + } + + return value +} + +func reportGlobalAppLabelAlias(appName string) string { + return common.PropertyGetDefault("logs", "--global", "app-label-alias", AppLabelAlias) +} + +func reportAppLabelAlias(appName string) string { + return common.PropertyGet("logs", appName, "app-label-alias") +} + func reportComputedMaxSize(appName string) string { value := reportMaxSize(appName) if value == "" { diff --git a/plugins/logs/subcommands.go b/plugins/logs/subcommands.go index 9924fde7dd8..9ea758b3284 100644 --- a/plugins/logs/subcommands.go +++ b/plugins/logs/subcommands.go @@ -72,7 +72,13 @@ func CommandSet(appName string, property string, value string) error { } common.CommandPropertySet("logs", appName, property, value, DefaultProperties, GlobalProperties) - if property == "vector-sink" { + + vectorProperties := map[string]bool{ + "app-label-alias": true, + "vector-sink": true, + } + + if _, ok := vectorProperties[property]; ok { common.LogVerboseQuiet(fmt.Sprintf("Writing updated vector config to %s", filepath.Join(common.GetDataDirectory("logs"), "vector.json"))) return writeVectorConfig() } diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats index 9f5e2192d21..274f477ec92 100644 --- a/tests/unit/logs.bats +++ b/tests/unit/logs.bats @@ -3,6 +3,7 @@ load test_helper setup() { + rm "${BATS_PARENT_TMPNAME}.skip" || true global_setup } @@ -53,7 +54,7 @@ teardown() { echo "status: $status" assert_failure assert_output_contains "$TEST_APP logs information" 0 - assert_output_contains "Invalid flag passed, valid flags: --logs-computed-max-size, --logs-global-max-size, --logs-global-vector-sink, --logs-max-size, --logs-vector-global-image, --logs-vector-sink" + assert_output_contains "Invalid flag passed, valid flags: --logs-app-label-alias, --logs-computed-app-label-alias, --logs-computed-max-size, --logs-global-app-label-alias, --logs-global-max-size, --logs-global-vector-sink, --logs-max-size, --logs-vector-global-image, --logs-vector-sink" run /bin/bash -c "dokku logs:report $TEST_APP --logs-vector-sink 2>&1" echo "output: $output" @@ -98,13 +99,13 @@ teardown() { echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "Invalid property specified, valid properties include: max-size, vector-image, vector-sink" + assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-sink" run /bin/bash -c "dokku logs:set $TEST_APP invalid value" 2>&1 echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "Invalid property specified, valid properties include: max-size, vector-image, vector-sink" + assert_output_contains "Invalid property specified, valid properties include: app-label-alias, max-size, vector-image, vector-sink" } @test "(logs) logs:set app" { @@ -281,7 +282,6 @@ teardown() { echo "status: $status" assert_success assert_output "2932JSDJ+KSDSDJ" - } @test "(logs) logs:set global" { @@ -415,7 +415,75 @@ teardown() { assert_output "10m" } -@test "(logs) logs:set max-size with alternate log-driver daemon " { +@test "(logs) logs:set app-label-alias" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:set $TEST_APP vector-sink console://?encoding[codec]=json" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Setting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:set --global app-label-alias" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Unsetting app-label-alias" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "jq -r '.sources[\"docker-source:$TEST_APP\"].include_labels[0]' /var/lib/dokku/data/logs/vector.json" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "com.dokku.app-name=$TEST_APP" + + run /bin/bash -c "dokku logs:set --global app-label-alias global-alt-name" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-computed-app-label-alias" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "global-alt-name" + + run /bin/bash -c "cat /var/lib/dokku/data/logs/vector.json" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "jq -r '.sources[\"docker-source:$TEST_APP\"].include_labels[0]' /var/lib/dokku/data/logs/vector.json" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "global-alt-name=$TEST_APP" + + run /bin/bash -c "dokku logs:set --global app-label-alias alt-name" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-computed-app-label-alias" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "alt-name" + + run /bin/bash -c "jq -r '.sources[\"docker-source:$TEST_APP\"].include_labels[0]' /var/lib/dokku/data/logs/vector.json" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "alt-name=$TEST_APP" +} + +@test "(logs) logs:set max-size with alternate log-driver daemon" { if [[ "$REMOTE_CONTAINERS" == "true" ]]; then skip "skipping due non-existent docker service in remote dev container" fi diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index 60b4e522c35..34ce53bcbc7 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -31,6 +31,7 @@ global_setup() { global_teardown() { [[ -n "$BATS_TEST_COMPLETED" ]] || touch "${BATS_PARENT_TMPNAME}.skip" + rm "${BATS_PARENT_TMPNAME}.skip" || true cleanup_apps cleanup_containers }