From 1ea821a6c35cc9a8057380f05ab6815d433c406b Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 10 Sep 2021 23:01:33 -0400 Subject: [PATCH 1/4] docs: document the vector-logs command --- docs/deployment/logs.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 50ba2bb76..69bdb6796 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -37,7 +37,7 @@ You can use these modifiers as follows: dokku logs node-js-app -t -p web ``` -will show logs continually from the web process. +The above command will show logs continually from the web process. ### Failed deploy logs @@ -127,6 +127,29 @@ dokku logs:vector-stop The `vector` container will be stopped and removed from the system. If the container is not running, this command will do nothing. +#### Checking Vector's Logs + +It may be necessary to check the vector container's logs to ensure that vector is operating as expected. This can be performed with the `logs:vector-logs` command. + +```shell +dokku logs:vector-logs +``` + +This command also supports the following modifiers: + +```shell +--num NUM # the number of lines to display +--tail # continually stream logs +``` + +You can use these modifiers as follows: + +```shell +dokku logs:vector-logs --tail --num 10 +``` + +The above command will show logs continually from the vector container, with an initial history of 10 log lines + #### Configuring a log sink Vector uses the concept of log "sinks" to send logs to a given endpoint. Log sinks may be configured globally or on a per-app basis by specifying a `vector-sink` in DSN form with the `logs:set` command. Specifying a sink value will reload any running vector container. From 2a04ed70b6778e79342fc1b54ba394dde5c8cf94 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 10 Sep 2021 23:02:21 -0400 Subject: [PATCH 2/4] fix: do not attempt to sprintf properties Previously, any properties with a % would be formatted using sprintf, causing issues when consuming those values later on. --- plugins/common/properties.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/common/properties.go b/plugins/common/properties.go index 8b7b58b41..1b687b276 100644 --- a/plugins/common/properties.go +++ b/plugins/common/properties.go @@ -434,7 +434,7 @@ func PropertyWrite(pluginName string, appName string, property string, value str } defer file.Close() - fmt.Fprintf(file, value) + fmt.Fprint(file, value) file.Chmod(0600) SetPermissions(propertyPath, 0600) return nil From 2c4fec77bb463014c3ba5e6ed0130c39ee130b2f Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 10 Sep 2021 23:03:29 -0400 Subject: [PATCH 3/4] refactor: force-set the type and inputs for a vector sink Previously, a user could inadvertently override the type or the inputs value by specifying those in their config. Instead, we force-set these so that users do not have potentially invalid config. --- plugins/logs/functions.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index 85fcac236..f1d146fbd 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -128,23 +128,9 @@ func sinkValueToConfig(appName string, sinkValue string) (vectorSink, error) { u.Scheme = strings.ReplaceAll(u.Scheme, "-", "_") - t := fmt.Sprintf("type=%s", u.Scheme) - i := fmt.Sprintf("inputs[]=docker-source:%s", appName) - if appName == "--global" { - i = "inputs[]=docker-global-source" - } - if appName == "--null" { - i = "inputs[]=docker-null-source" - } - - initialQuery := fmt.Sprintf("%s&%s", t, i) query := u.RawQuery - if query == "" { - query = initialQuery - } else if strings.HasPrefix(query, "&") { - query = fmt.Sprintf("%s%s", initialQuery, query) - } else { - query = fmt.Sprintf("%s&%s", initialQuery, query) + if strings.HasPrefix(query, "&") { + query = strings.TrimPrefix(query, "&") } b, err := qson.ToJSON(query) @@ -156,6 +142,15 @@ func sinkValueToConfig(appName string, sinkValue string) (vectorSink, error) { return data, err } + data["type"] = u.Scheme + data["inputs"] = []string{"docker-source:" + appName} + if appName == "--global" { + data["inputs"] = []string{"docker-global-source"} + } + if appName == "--null" { + data["inputs"] = []string{"docker-null-source"} + } + return data, nil } From 0997fd33471c3cab8bf989c37eb9713fbeeb031d Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Fri, 10 Sep 2021 23:04:41 -0400 Subject: [PATCH 4/4] fix: add support for url-encoded vector-sink config values We additionally force-replace \u0026 with an ampersand to ensure we properly support & in config values (such as for URIs). --- docs/deployment/logs.md | 9 +++++++++ plugins/logs/functions.go | 3 +++ tests/unit/logs.bats | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 69bdb6796..887ecf0ba 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -197,4 +197,13 @@ Valid values for `SINK_TYPE` include all log vector log sinks, while `SINK_OPTIO - `[int]`: form: `key[]=int` - `table`: form: `option[key]=value` +For some sinks - such as the `http` sink - it may be useful to use special characters such as `&`. These characters must be url escaped as per [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986.html). + +```shell +# the following command will set the `http` sink with a uri config value +# for a uri config value: https://loggerservice.com:1234/?token=abc1234&type=vector +# the url quoted version: https%3A//loggerservice.com%3A1234/%3Ftoken%3Dabc1234%26type%3Dvector +dokku logs:set test vector-sink "http://?uri=https%3A//loggerservice.com%3A1234/%3Ftoken%3Dabc1234%26type%3Dvector" +``` + Please read the [sink documentation](https://vector.dev/docs/reference/sinks/) for your sink of choice to configure the sink as desired. diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index f1d146fbd..74f2b5146 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -1,6 +1,7 @@ package logs import ( + "bytes" "encoding/json" "errors" "fmt" @@ -217,6 +218,8 @@ func writeVectorConfig() error { return err } + b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1) + vectorConfig := filepath.Join(common.MustGetEnv("DOKKU_LIB_ROOT"), "data", "logs", "vector.json") if err := common.WriteSliceToFile(vectorConfig, []string{string(b)}); err != nil { return err diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats index 9ad5ed65a..e1b640ff7 100644 --- a/tests/unit/logs.bats +++ b/tests/unit/logs.bats @@ -238,6 +238,32 @@ teardown() { assert_output "" } +@test "(logs) logs:set escaped uri" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:set $TEST_APP vector-sink http://?uri=https%3A//loggerservice.com%3A1234/%3Ftoken%3Dabc1234%26type%3Dvector" 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:report $TEST_APP --logs-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "http://?uri=https%3A//loggerservice.com%3A1234/%3Ftoken%3Dabc1234%26type%3Dvector" + + run /bin/bash -c "jq -r '.sinks[\"docker-sink:$TEST_APP\"].uri' /var/lib/dokku/data/logs/vector.json" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "https://loggerservice.com:1234/?token=abc1234&type=vector" +} + @test "(logs) logs:set global" { run create_app echo "output: $output"