Skip to content

Add support for customizing log file directory (logsDir) in Multi-App… - #1653

Open
codevisionary-omer wants to merge 1 commit into
dapr:masterfrom
codevisionary-omer:feature/customizable-logs-dir
Open

Add support for customizing log file directory (logsDir) in Multi-App…#1653
codevisionary-omer wants to merge 1 commit into
dapr:masterfrom
codevisionary-omer:feature/customizable-logs-dir

Conversation

@codevisionary-omer

Copy link
Copy Markdown

Description

When using Multi-App Run (dapr run -f), app and daprd log files are always written to <appDirPath>/.dapr/logs, with no way to change the location. This causes two problems:

  1. File watchers in dev workflows. Dev servers that recursively watch the project tree (e.g. uvicorn --reload, which uses watchfiles) receive constant filesystem events from log writes inside appDirPath, causing churn and a performance penalty. Watcher exclusion filters don't help, because the OS-level recursive watch still delivers the events — the fix is for logs to live outside the watched tree.
  2. No centralized logging. Logs cannot be collected into a single directory across apps.

Setting appLogDestination/daprdLogDestination: console avoids the file writes but loses persisted logs, so it is a workaround rather than a solution.

This PR adds an optional logsDir field to the Multi-App Run template, available under common and per app:

version: 1
common:
  logsDir: ./central-logs        # optional
apps:
  - appID: myapp
    appDirPath: ./myapp
    logsDir: /tmp/myapp-logs     # optional per-app override

Behavior:

  • Precedence: apps[i].logsDir > common.logsDir > default (<appDirPath>/.dapr/logs).
  • Relative per-app paths resolve against appDirPath; relative common paths resolve against the run file's directory (consistent with other paths in the template). ~ is expanded.
  • The directory is created on first use; it is not required to exist when the run file is parsed.
  • Fully backward compatible: when logsDir is not set, behavior is unchanged.

Changes:

  • pkg/runfileconfig/run_file_config.go — added LogsDir field on App and Common; GetLogsDir() honors it.
  • pkg/runfileconfig/run_file_config_parser.go — resolves logsDir to absolute paths (new resolvePathToAbs helper that does not require the path to exist) and applies precedence.
  • pkg/runfileconfig/run_file_config_parser_test.go — tests for precedence, relative/absolute resolution, directory creation, and unchanged default behavior.
  • pkg/runfileconfig/testdata/test_run_config_logs_dir.yaml — test fixture.

Issue reference

We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.

Please reference the issue this PR will close: #1652

Checklist

Please make sure you've completed the relevant tasks for this PR, out of the following list:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

@codevisionary-omer

Copy link
Copy Markdown
Author

bump

@codevisionary-omer
codevisionary-omer force-pushed the feature/customizable-logs-dir branch from 1e0d44a to ac790f6 Compare July 14, 2026 13:23
@acroca

acroca commented Jul 15, 2026

Copy link
Copy Markdown
Member

Hey @codevisionary-omer Can you fix git in this branch? There're lots of commits that don't seem right. I'd expect only 2995f1c in this PR.

@codevisionary-omer
codevisionary-omer force-pushed the feature/customizable-logs-dir branch 2 times, most recently from ac790f6 to 82b5482 Compare July 19, 2026 13:52
@codevisionary-omer

Copy link
Copy Markdown
Author

@acroca Sorry about that fixed

… Run template

Log files for app and daprd were always written to <appDirPath>/.dapr/logs
with no way to change the location. This writes constant filesystem events
into the project tree, which degrades dev servers that recursively watch it
(e.g. uvicorn --reload via watchfiles), and prevents centralizing logs.

This change adds an optional 'logsDir' field to the Multi-App Run template,
available under 'common' and per app.

Precedence: apps[i].logsDir > common.logsDir > default (<appDirPath>/.dapr/logs).
Relative paths are resolved against the app directory (per-app) or the run
file directory (common); '~' is expanded. The directory is created on use.
Default behavior is unchanged when the field is not set.

Signed-off-by: YOUR NAME <YOUR_EMAIL>
Signed-off-by: Omer Spalter <omer@codevisionary.ai>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable logsDir support to the Multi-App Run (dapr run -f) template so app/daprd log files can be written outside <appDirPath> (helping dev file watchers and enabling centralized log collection), while preserving the current default behavior when unset.

Changes:

  • Introduces logsDir fields in common and per-app config, with precedence app.logsDir > common.logsDir > default (<appDirPath>/.dapr/logs).
  • Resolves logsDir values to absolute paths (including ~ expansion) without requiring the directory to exist at parse time.
  • Adds tests and a runfile fixture covering precedence and path resolution behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
pkg/runfileconfig/testdata/test_run_config_logs_dir.yaml Adds a runfile fixture exercising common/app override behavior for logsDir.
pkg/runfileconfig/run_file_config.go Adds LogsDir fields and updates GetLogsDir() to honor configured log directories.
pkg/runfileconfig/run_file_config_parser.go Resolves logsDir to absolute paths and applies common→app inheritance during validation.
pkg/runfileconfig/run_file_config_parser_test.go Adds tests for logsDir precedence, resolution, and creation behavior.
Comments suppressed due to low confidence (1)

pkg/runfileconfig/run_file_config_parser_test.go:450

  • t.Cleanup removes a hard-coded absolute path ("/tmp/dapr-abs-logs"). If that directory already exists on a developer/CI machine, this test will delete unrelated files. Cleanup should only remove directories created under the test’s control.
	t.Cleanup(func() {
		os.RemoveAll(expectedCommonLogsDir)
		os.RemoveAll(expectedApp2LogsDir)
		os.RemoveAll("/tmp/dapr-abs-logs")
	})

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +434 to +437
t.Run("app's absolute logsDir is used as is", func(t *testing.T) {
assert.Equal(t, "/tmp/dapr-abs-logs", apps[2].LogsDir)
assert.Equal(t, "/tmp/dapr-abs-logs", apps[2].GetLogsDir())
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is legit, but the suggested fix doesn't fully solve it: the hard-coded /tmp/... path isn't absolute on Windows (filepath.IsAbs is false without a volume), so the parser joins it onto appDirPath and the LogsDir assertion fails at parse time even without calling GetLogsDir(). Since CI runs unit tests on windows-latest, this would fail there.

I'd generate the run file in the test with an absolute path from t.TempDir() instead and cleanup comes for free.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow to configure logs directory

3 participants