Skip to content

Commit 7e01b2b

Browse files
fix(core): Add stderr log output option (#2989)
### Proposed Changes - Adds log output to composite workflows for service - Adds support for `stderr` as output stream for logs - Adds `log-type` and `log-level` input params to composite workflows - Adds output `log-file` for path to the logs output for use with `tail` or similar checks downstream to mimic log capturing tools ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions
1 parent cc8337a commit 7e01b2b

File tree

14 files changed

+264
-59
lines changed

14 files changed

+264
-59
lines changed

.github/scripts/watch.sh

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,101 @@
11
#!/usr/bin/env bash
2-
# Usage: watch.sh [cfg file] [app and command....]
2+
# Usage: watch.sh [options] [cfg file] [app and command....]
33
#
4+
# Options:
5+
# --tee-out-to FILE Tee stdout to FILE
6+
# --tee-err-to FILE Tee stderr to FILE
7+
#
8+
9+
# Kill a process, if it is still running.
10+
# Use:
11+
# silent_kill $PID
12+
silent_kill() {
13+
local pid=$1
14+
if kill -0 "$pid" 2>/dev/null && ! kill "$pid" 2>/dev/null; then
15+
echo "[WARN] Failed to kill process $pid" >&2
16+
fi
17+
}
418

519
quitter() {
6-
kill "$PID"
7-
exit
20+
silent_kill "$PID"
21+
exit
822
}
923
trap quitter SIGINT
1024

25+
# Parse optional tee arguments
26+
tee_stdout=""
27+
tee_stderr=""
28+
29+
while [[ $# -gt 0 ]]; do
30+
case $1 in
31+
--tee-out-to)
32+
if [[ -z "$2" || "$2" == --* ]]; then
33+
echo "Error: --tee-out-to requires a file path argument." >&2
34+
exit 1
35+
fi
36+
tee_stdout="$2"
37+
shift 2
38+
;;
39+
--tee-err-to)
40+
if [[ -z "$2" || "$2" == --* ]]; then
41+
echo "Error: --tee-err-to requires a file path argument." >&2
42+
exit 1
43+
fi
44+
tee_stderr="$2"
45+
shift 2
46+
;;
47+
*)
48+
break
49+
;;
50+
esac
51+
done
52+
1153
file_to_watch="$1"
1254
shift
1355

1456
wait_for_change_to() {
15-
if which inotifywait; then
16-
echo "[INFO] inotifywaiting to [${file_to_watch}]"
17-
inotifywait -e modify -e move -e create -e delete -e attrib -r "${file_to_watch}"
18-
else
19-
m=$(date -r "${file_to_watch}" +%s)
20-
echo "[INFO] stat checking [${file_to_watch}] from [${m}]"
21-
while true; do
22-
sleep 1
23-
n=$(date -r "${file_to_watch}" +%s)
24-
echo "[INFO] stat checking [${file_to_watch}] from [${m} < ${n}]"
25-
if [[ $m < $n ]]; then
26-
return
27-
fi
28-
done
29-
fi
57+
if which inotifywait; then
58+
echo "[INFO] inotifywaiting to [${file_to_watch}]"
59+
inotifywait -e modify -e move -e create -e delete -e attrib -r "${file_to_watch}"
60+
else
61+
m=$(date -r "${file_to_watch}" +%s)
62+
echo "[INFO] stat checking [${file_to_watch}] from [${m}]"
63+
while true; do
64+
sleep 1
65+
n=$(date -r "${file_to_watch}" +%s)
66+
echo "[INFO] stat checking [${file_to_watch}] from [${m} < ${n}]"
67+
if [[ $m < $n ]]; then
68+
return
69+
fi
70+
done
71+
fi
3072
}
3173

3274
while true; do
33-
"$@" &
34-
PID=$!
35-
wait_for_change_to "${file_to_watch}"
36-
kill $PID
37-
echo "[INFO] restarting [${PID}] due to modified file"
75+
# Build command with optional tee for stdout/stderr
76+
if [[ -n "$tee_stdout" ]] || [[ -n "$tee_stderr" ]]; then
77+
# Ensure log directories exist
78+
[[ -n "$tee_stdout" ]] && mkdir -p "$(dirname "$tee_stdout")"
79+
[[ -n "$tee_stderr" ]] && mkdir -p "$(dirname "$tee_stderr")"
80+
81+
# Run command with tee for stdout and/or stderr
82+
if [[ -n "$tee_stdout" ]] && [[ -n "$tee_stderr" ]]; then
83+
# Both stdout and stderr tee
84+
"$@" > >(tee -a "$tee_stdout") 2> >(tee -a "$tee_stderr" >&2) &
85+
elif [[ -n "$tee_stdout" ]]; then
86+
# Only stdout tee
87+
"$@" > >(tee -a "$tee_stdout") &
88+
else
89+
# Only stderr tee
90+
"$@" 2> >(tee -a "$tee_stderr" >&2) &
91+
fi
92+
else
93+
# No tee, run normally
94+
"$@" &
95+
fi
96+
97+
PID=$!
98+
wait_for_change_to "${file_to_watch}"
99+
silent_kill "$PID"
100+
echo "[INFO] restarting [${PID}] due to modified file"
38101
done

docs/Configuring.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,19 @@ The logger configuration is used to define how the application logs its output.
9494

9595
Root level key `logger`
9696

97-
| Field | Description | Default | Environment Variable |
98-
| -------- | -------------------------------- | -------- | --------------------- |
99-
| `level` | The logging level. | `info` | OPENTDF_LOGGER_LEVEL |
100-
| `type` | The format of the log output. | `json` | OPENTDF_LOGGER_TYPE |
101-
| `output` | The output destination for logs. | `stdout` | OPENTDF_LOGGER_OUTPUT |
97+
| Field | Description | Default | Environment Variable |
98+
| -------- | ---------------------------------------- | -------- | --------------------- |
99+
| `level` | The logging level. | `info` | OPENTDF_LOGGER_LEVEL |
100+
| `type` | The format of the log output. | `json` | OPENTDF_LOGGER_TYPE |
101+
| `output` | Stream output for logs, stderr or stdout | `stdout` | OPENTDF_LOGGER_OUTPUT |
102102

103103
Example:
104104

105105
```yaml
106106
logger:
107107
level: debug
108108
type: text
109-
output: stdout
109+
output: stderr
110110
```
111111

112112
## Server Configuration

docs/Contributing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ For end-users/consumers, see [here](./Consuming.md).
1313
1414
1. Configure KAS and Keycloak keys: `.github/scripts/init-temp-keys.sh`. Creates temporary keys for the local KAS and Keycloak Certificate Exchange.
1515
2. `docker compose up`. Starts both the local Postgres database (contains the ABAC policy configuration data) and Keycloak (the local IdP).
16-
1. Note: You will have to add the ``localhost.crt`` as a trusted certificate to do TLS authentication at ``localhost:8443``.
16+
1. Note: You will have to add the ``localhost.crt`` as a trusted certificate to do TLS authentication at ``localhost:8443``. On a mac, this is `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./keys/localhost.crt`
1717
3. Create an OpenTDF config file: `opentdf.yaml`
1818
1. The `opentdf-dev.yaml` file is the more secure starting point, but you will likely need to modify it to match your environment. This configuration is recommended as it is more secure but it does require valid development keypairs.
1919
2. The `opentdf-core-mode.yaml` file is simpler to run but less secure. This file configures the platform to startup without a KAS instances, without a built-in ERS instance, and without endpoint authentication.

opentdf-core-mode.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ sdk_config:
1010
logger:
1111
level: debug
1212
type: text
13-
output: stdout
13+
output: stderr
1414
# DB and Server configurations are defaulted for local development
1515
# db:
1616
# host: localhost

opentdf-dev.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
logger:
22
level: debug
33
type: text
4-
output: stdout
4+
output: stderr
55
# DB and Server configurations are defaulted for local development
66
# db:
77
# host: localhost

opentdf-ers-mode.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mode: entityresolution
44
logger:
55
level: debug
66
type: text
7-
output: stdout
7+
output: stderr
88
services:
99
entityresolution:
1010
log_level: info

opentdf-example.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
logger:
22
level: debug
33
type: text
4-
output: stdout
4+
output: stderr
55
# DB and Server configurations are defaulted for local development
66
db:
77
host: opentdfdb

opentdf-kas-mode.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ sdk_config:
1010
logger:
1111
level: debug
1212
type: text
13-
output: stdout
13+
output: stderr
1414
security:
1515
unsafe:
1616
# Increase only when diagnosing clock drift issues; default is 1m

service/logger/logger.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ func (l *Logger) With(key string, value string) *Logger {
101101

102102
func getWriter(config Config) (io.Writer, error) {
103103
switch config.Output {
104+
case "stderr":
105+
return os.Stderr, nil
104106
case "stdout":
105107
return os.Stdout, nil
106108
default:

service/pkg/config/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func TestLoadConfig_Success(t *testing.T) {
258258
logger:
259259
level: debug
260260
type: text
261-
output: stdout
261+
output: stderr
262262
mode: core
263263
db:
264264
host: opentdf

0 commit comments

Comments
 (0)