Skip to content

itest: separate tapd instance logs into per-node files#1988

Draft
darioAnongba wants to merge 5 commits intomainfrom
test/separate-tapd-logs
Draft

itest: separate tapd instance logs into per-node files#1988
darioAnongba wants to merge 5 commits intomainfrom
test/separate-tapd-logs

Conversation

@darioAnongba
Copy link
Contributor

@darioAnongba darioAnongba commented Feb 11, 2026

When debugging multi-node integration test failures, all tapd logs were intermingled in console output, making it very difficult to trace which instance produced which log line. With this change, each tapd instance writes to its own log file in the test log directory.

  • Run each tapd instance as a separate OS process (tapd-itest binary) during integration tests, enabling per-instance log files (e.g., tapd-Alice.log, tapd-Bob.log)
  • Go's global package-level loggers make in-process log separation impossible — calling SetupLoggers for one instance overwrites all others. This matches the approach used by lnd and lightning-terminal itests.
  • Add setBoolFlag, setCliFlag, and updateLndNode helpers for test-time config changes between stop/start cycles.

Fixes #1987

Add a build step for the tapd-itest binary in the build-itest target.
This binary is needed because tapd instances are now started as separate
OS processes during integration tests, enabling per-instance log files.
Refactor tapdHarness to start each tapd instance as a separate OS
process (exec.Command) instead of running in-process. This enables
per-instance log separation.

Each tapd instance now writes to its own log file (e.g., tapd-Alice.log,
tapd-Bob.log) in the test log directory, matching the pattern used by
lnd and lightning-terminal integration tests.

Key changes:
- Replace in-process config structs with CLI argument construction
- Add start()/stop() using exec.Command with process lifecycle management
- Add addLogFile() for per-instance log file creation
- Add setCliFlag(), setBoolFlag(), updateLndNode() helper methods
- Expose rpcHost(), tlsCertPath, restListenAddr, backoff configs
  for test access
Remove tap.SetupLoggers call from setupLogging since tapd instances now
run as separate OS processes with their own loggers. Aperture logger
setup is retained since aperture still runs in-process.
Update test files to use the new tapdHarness accessors instead of the
removed clientCfg struct fields.
Add tapd-itest to the artifact upload and chmod steps so the binary is
available in CI integration test jobs.
@gemini-code-assist
Copy link

Summary of Changes

Hello @darioAnongba, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the debugging experience for multi-node integration tests by isolating the log output of each tapd instance into its own dedicated file. This change addresses the previous difficulty of tracing specific tapd instance behavior due to intermingled logs. The core implementation involves running each tapd instance as a separate operating system process, mirroring approaches used in other projects like lnd and lightning-terminal to overcome limitations with Go's global package-level loggers. Additionally, new utility functions have been added to streamline the modification of tapd configurations during test execution.

Highlights

  • Per-Node Log Files for tapd Instances: Each tapd instance in integration tests now writes its logs to a separate file (e.g., tapd-Alice.log, tapd-Bob.log), resolving the issue of intermingled logs in console output for multi-node debugging.
  • tapd Instances as Separate OS Processes: To enable per-instance log separation, tapd instances are now run as distinct OS processes using the tapd-itest binary during integration tests.
  • New Test-Time Configuration Helpers: Introduced setBoolFlag, setCliFlag, and updateLndNode helper functions within the tapdHarness to facilitate dynamic configuration changes for tapd instances between stop/start cycles in tests.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • Makefile
    • Added a build target for the tapd-itest binary.
    • Included itest/tapd-itest in the clean target.
  • itest/macaroon_test.go
    • Updated dialServer calls to reference t.tapd.tlsCertPath instead of t.tapd.clientCfg.RpcConf.TLSCertPath.
  • itest/send_test.go
    • Refactored access to Hashmail and Universe RPC courier backoff configurations to use new fields on the tapdHarness.
    • Replaced the global updateConfigWithNode function call with the new bob.updateLndNode method.
  • itest/tapd_harness.go
    • Modified the tapdHarness struct to manage tapd as an external process, adding fields for CLI arguments, RPC/REST addresses, TLS/macaroon paths, process command, and log file.
    • Removed the tapcfg import and the in-process tap.Server field.
    • Rewrote newTapdHarness to construct CLI arguments for an external tapd process instead of an in-process configuration.
    • Added setCliFlag, setBoolFlag, and updateLndNode helper methods for dynamic configuration of the external tapd process.
    • Rewrote the start method to execute tapd-itest as a separate process, redirecting its output to a per-instance log file, and waiting for RPC readiness.
    • Implemented addLogFile to create and manage dedicated log files for each tapd instance.
    • Rewrote the stop method to gracefully shut down the external tapd process, including force-killing if necessary, and closing the associated log file.
  • itest/test_harness.go
    • Removed the global tap.SetupLoggers call, aligning with the new per-instance logging approach for tapd.
  • itest/universe_test.go
    • Updated the REST API URL construction to use t.tapd.restListenAddr instead of t.tapd.clientCfg.RpcConf.RawRESTListeners[0].
  • itest/zero_value_anchor_test.go
    • Modified the SweepOrphanUtxos test configuration to utilize the new setBoolFlag helper for dynamic flag setting.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/main.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a significant and well-executed refactoring of the integration test harness. Running tapd as a separate process will greatly improve log clarity and make debugging multi-node test failures much easier. The switch from an in-process configuration to building CLI arguments is handled cleanly, and the new helper functions for modifying flags between test runs are a great addition for flexibility. I have a few suggestions to enhance maintainability and address a minor issue in the new logging setup.

// configuration.
// configuration. The tapd instance will be started as a separate OS process
// with its own log file.
func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig,

Choose a reason for hiding this comment

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

medium

The newTapdHarness function has grown quite large (over 200 lines) due to the refactoring to build CLI arguments. To improve readability and maintainability, consider breaking it down into smaller helper functions. Each helper could be responsible for a specific group of arguments, for example:

  • buildBaseCliArgs(...)
  • appendProofCourierArgs(args, ...)
  • appendRfqArgs(args, ...)
  • appendDbArgs(args, ...)

This would make the main function a more readable sequence of calls to these helpers.

Comment on lines +532 to +535
// setCliFlag sets or updates a CLI flag in the harness's argument list.
// This can be used between stop() and start() to modify configuration before
// restarting. The flag name should not include the "--" prefix.
func (hs *tapdHarness) setCliFlag(flag, value string) {

Choose a reason for hiding this comment

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

medium

According to the repository's style guide (rule 18), function comments must begin with the function name, and the examples show it capitalized for exported functions. This comment should start with SetCliFlag. This also applies to SetBoolFlag, UpdateLndNode, and AddLogFile in this file.

Suggested change
// setCliFlag sets or updates a CLI flag in the harness's argument list.
// This can be used between stop() and start() to modify configuration before
// restarting. The flag name should not include the "--" prefix.
func (hs *tapdHarness) setCliFlag(flag, value string) {
// SetCliFlag sets or updates a CLI flag in the harness's argument list.
// This can be used between stop() and start() to modify configuration before
// restarting. The flag name should not include the "--" prefix.
func (hs *tapdHarness) setCliFlag(flag, value string) {
References
  1. Function comments must begin with the function name. (link)

Comment on lines +680 to +684
// Pass the node's stderr to both a buffer and the file, so we can
// capture errors and also persist them.
var errb bytes.Buffer
w := io.MultiWriter(&errb, file)
hs.cmd.Stderr = w

Choose a reason for hiding this comment

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

medium

The errb buffer is initialized and written to via io.MultiWriter, but its content is never read. This makes the buffer and the multi-writer seem like dead code. If capturing stderr in a buffer isn't needed, this could be simplified to just redirect stderr to the log file.

Suggested change
// Pass the node's stderr to both a buffer and the file, so we can
// capture errors and also persist them.
var errb bytes.Buffer
w := io.MultiWriter(&errb, file)
hs.cmd.Stderr = w
// Pass stderr to the file.
hs.cmd.Stderr = file

@coveralls
Copy link

Pull Request Test Coverage Report for Build 21921677537

Details

  • 0 of 318 (0.0%) changed or added relevant lines in 1 file are covered.
  • 29498 unchanged lines in 211 files lost coverage.
  • Overall coverage decreased (-22.1%) to 34.389%

Changes Missing Coverage Covered Lines Changed/Added Lines %
itest/tapd_harness.go 0 318 0.0%
Files with Coverage Reduction New Missed Lines %
universe/supplyverifier/util.go 1 98.75%
proof/util.go 2 81.63%
proof/verified.go 2 86.54%
tapdb/cache_logger.go 2 94.44%
tapdb/migrations.go 2 76.82%
tapdb/mssmt.go 2 88.64%
address/log.go 3 0.0%
commitment/log.go 3 0.0%
internal/pedersen/commitment.go 3 95.31%
lndservices/log.go 3 0.0%
Totals Coverage Status
Change from base Build 21826730512: -22.1%
Covered Lines: 31844
Relevant Lines: 92599

💛 - Coveralls

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

Projects

Status: 🆕 New

Development

Successfully merging this pull request may close these issues.

itest: separate tapd instance logs into per-node files

2 participants