Skip to content

Log API queries at DEBUG level - #2456

Merged
kushti merged 3 commits into
ergoplatform:v6.0.5from
Ergologica:feature/log-api-queries-1909
Aug 10, 2026
Merged

Log API queries at DEBUG level#2456
kushti merged 3 commits into
ergoplatform:v6.0.5from
Ergologica:feature/log-api-queries-1909

Conversation

@Ergologica

Copy link
Copy Markdown

Closes #1909.

Relation to #1911

@pragmaxim opened #1911 for this in 2022. @kushti's review question there was:

Is the new dependency needed for purposes of this PR?

That PR needed akka-slf4j plus akka.loglevel = "DEBUG" in application.conf because it logged through DebuggingDirectives.logRequest, which goes via akka's LoggingAdapter and its event stream.

Both of those have since landed in master for other reasons — build.sbt:332 and the akka { ... } block in application.conf. So the question is moot on the dependency side, but the mechanism is still worth avoiding: logging through the akka event stream means the verbosity of the node's HTTP log is coupled to akka's global log level, and turning it up brings along everything else akka has to say at DEBUG.

This PR logs through ScorexLogging, like the rest of the codebase, so nothing new is added to build.sbt and no global akka setting changes.

The change

A single Directive0 wrapping the composite route in ErgoHttpService:

GET /wallet/boxes/unspent?minInclusionHeight=100 - 200 in 7 ms

method, relative URI (path and query string), response status, elapsed time.

Notes on the choices:

  • It wraps the route outside handleRejections, so rejected and failed requests are logged too, with the status they were finally answered with. Inside the rejection handler they would never reach mapResponse.
  • Bodies are not logged, request or response. Requests to this API carry secrets — a mnemonic on /wallet/restore, a password on /wallet/unlock, a seed on /wallet/init — and responses can be large. Method, URI, status and duration are what makes API access diagnosable.
  • It costs nothing when disabled. ScorexLogging extends StrictLogging, whose log.debug is a macro guarded by isDebugEnabled, so the interpolated string is not built unless the logger is actually at DEBUG.
  • It is off by default, since the root logger in logback.xml is at INFO. A commented-out <logger> element is added there so the switch is discoverable:
<logger name="org.ergoplatform.http.ErgoHttpService" level="DEBUG"/>

That also means verbosity is per-logger and under the operator's control, rather than tied to akka's level.

Tests

New ErgoHttpServiceSpec attaches a logback ListAppender to the service's logger and asserts on what is actually emitted:

  • a served query is logged exactly once, matching GET /emission/at/100 - 200 in <n> ms;
  • the query string is included, and an unmatched path is logged with the status the rejection handler answered with;
  • nothing at all is logged when the logger is not at DEBUG;
  • the response body is byte-identical with logging on and off.

sbt "testOnly org.ergoplatform.http.routes.ErgoHttpServiceSpec" — 4 tests, green.

Log method, relative URI, response status and elapsed time for every query served by the node's HTTP interface. Bodies are not logged: requests to this API carry secrets (mnemonic on /wallet/restore, password on /wallet/unlock).

Logging goes through ScorexLogging rather than akka's LoggingAdapter, so no dependency is added and the node's HTTP verbosity is not tied to akka's global log level. It is off by default, as the root logger is at INFO, and costs nothing when off since log.debug is a macro guarded by isDebugEnabled.

The directive wraps the route outside handleRejections, so rejected requests are logged too, with the status they were answered with.

Closes ergoplatform#1909
Commented-out logger element so the switch is discoverable.
Attaches a logback ListAppender to the service logger and asserts on what is emitted: one line per served query with method, URI, status and duration; the query string included and unmatched paths logged with the status they were answered with; nothing logged below DEBUG; and the response body unchanged with logging on and off.
@Ergologica

Copy link
Copy Markdown
Author

On the red CI — it is not this PR.

Run node tests fails on DigestStateSpecification: applyModifier() - valid block, with IllegalArgumentException: requirement failed thrown during property evaluation on BoxHolder(2000 boxes inside).

The same CI round on #2455 — a different branch, touching only ErgoNodeTransactionSpec.scala — fails identically in UtxoStateSpecification: applyModifier() - valid full block. Both properties reduce to forAll(boxesHolderGen) { bh => ... validFullBlock(parentOpt = None, us, bh) }, so the failure is in the shared block generator, which neither branch touches. This one changes ErgoHttpService.scala, logback.xml (a commented-out logger) and adds one spec.

I worked the failure through in #2455 (comment there) — short version: a bare require(inputSum >= minValue) at ErgoNodeTransactionGenerators.scala:138, reachable whenever the last boxes validTransactionsFromBoxes has left are together worth less than BoxUtils.sufficientAmount.

@Ergologica

Copy link
Copy Markdown
Author

Correction: the cause I pointed at above — require(inputSum >= minValue) at ErgoNodeTransactionGenerators.scala:138 — is wrong. I went to fix it, could not reproduce it in 300 generator runs or 500 full property runs, and the arithmetic agrees it should be a ~1e-8 event rather than a per-CI-run one. Full write-up and what I measured instead (an ~8 file descriptor leak per createUtxoState, never closed anywhere in the test tree) is in #2455.

What still holds here is only the observable part: Run node tests fails in DigestStateSpecification: applyModifier() - valid block, a forAll(boxesHolderGen) property in a suite this branch does not touch, and the same CI round failed the equivalent property in UtxoStateSpecification on an unrelated branch. This PR changes ErgoHttpService.scala, a commented-out logger in logback.xml, and adds one spec.

@kushti
kushti changed the base branch from master to v6.0.5 August 10, 2026 16:49
@kushti
kushti merged commit ea00db7 into ergoplatform:v6.0.5 Aug 10, 2026
7 of 8 checks passed
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.

Log API queries (@DEBUG level)

2 participants