Skip to content

Conversation

SgtPooki
Copy link
Member

@SgtPooki SgtPooki commented Jul 24, 2025

Modifies the /api/v0/log/level endpoint to query current logging levels when a new level is not specified.

This depends on github.com/ipfs/go-log v2.8.0

Related ipfs/ipfs-webui#1925

Closes #10882

Updated command arguments

Examples getting log level:

  • ipfs log level → Show default level only
  • ipfs log level '*' → Show log level for every subsystem, including default level
  • ipfs log level foo → Show log level for "foo" subsystem only

Examples setting log level:

  • ipfs log level '*' debug → Set all subsystems and default to "debug" level
  • ipfs log level '*' default → Set all subsystems to current default level
  • ipfs log level foo debug → Set level of "foo" subsystem to "debug"
  • ipfs log level foo default → Set level of "foo" subsystem to current default level

Example updated command use

On Command Line

Get default log level

> ipfs log level
error

Get all log levels

> ipfs log level '*'
(default): error
autonat: error
autonatv2: error
autorelay: error
autotls: error
badger: error
basichost: error
# ...
webrtc-udpmux: error
websocket-transport: error
webtransport: error

Get log level for a specific subsystem

> ipfs log level autonatv2
autonatv2: error

Set log level for a specific subsystem

> ipfs log level autonatv2 info
Changed log level of 'autonatv2' to 'info'

Set log level for all subsystems including default

> ipfs log level '*' info
Changed log level of '*' to 'info'

Using HTTP endpoint

Get default log level

> curl -X POST http://0.0.0.0:5001/api/v0/log/level
{"Levels":{"":"error"}}

Get all log levels with HTTP endpoint

> curl -X POST http://0.0.0.0:5001/api/v0/log/level\?arg\=\*
{"Levels":{"(default)":"error","autonat":"error","autonatv2":"error","autorelay":"error","autotls":"error","badger":"error","basichost":"error","bitswap":"error","bitswap/bsnet":"error","bitswap/client":"error","bitswap/client/getter":"error","bitswap/client/msgq":"error","bitswap/client/peermgr":"error","bitswap/client/sesspeermgr":"error","bitswap/connevtman":"error","bitswap/server":"error","bitswap/server/decision":"error","bitswap/session":"error","blankhost":"error","blockservice":"error","blockstore":"error","bootstrap":"error","boxo/gateway":"error","canonical-log":"error","chunk":"error","cmd/ipfs":"error","cmds":"error","cmds/cli":"error","cmds/files":"error","cmds/http":"error","command":"error","connmgr":"error","core":"error","core/commands":"error","core/commands/cmdenv":"error","core/commands/ipns":"error","core/server":"error","core:constructor":"error","corerepo":"error","coreunix":"error","dht":"error","dht-crawler":"error","dht.pb":"error","dht/RtDiversityFilter":"error","dht/RtRefreshManager":"error","dht/netsize":"error","discovery-backoff":"error","diversityFilter":"error","doh":"error","eventbus":"error","filestore":"error","flatfs":"error","fsrepo":"error","fullrtdht":"error","fuse/ipfs":"error","fuse/ipns":"error","fxtestplugin":"error","gc":"error","http-peer-id-auth":"error","httpnet":"error","internal/nat":"error","ipns":"error","ipns/repub":"error","keystore":"error","libp2phttp":"error","lock":"error","mdns":"error","merkledag":"error","metrics-prometheus":"error","mfs":"error","mount":"error","namesys":"error","nat":"error","net/identify":"error","node":"error","nopfs":"error","nopfs-blocks":"error","p2p-circuit":"error","p2p-config":"error","p2p-holepunch":"error","p2p-mount":"error","p2pnode":"error","path/resolver":"error","pebble":"error","peering":"error","peerstore":"error","pin":"error","ping":"error","pinning-service-http-client":"error","plugin/loader":"error","plugin/peerlog":"error","profile":"error","provider":"error","providers":"error","pstoremanager":"error","pubsub":"error","pubsub-valuestore":"error","quic-transport":"error","quic-utils":"error","rcmgr":"error","relay":"error","remotepinning/mfs":"error","resourcemanager":"error","reuseport-transport":"error","routedhost":"error","routing/composable":"error","routing/delegated":"error","routing/http/client":"error","routing/http/contentrouter":"error","routing/http/filters":"error","routing/http/server":"error","routing/provqrymgr":"error","swarm2":"error","table":"error","tcp-demultiplex":"error","tcp-tpt":"error","ulimit":"error","unixfs":"error","unixfs-hamt":"error","upgrader":"error","webrtc-transport":"error","webrtc-transport-pion":"error","webrtc-udpmux":"error","websocket-transport":"error","webtransport":"error"}}

Get log level for a specific subsystem

> curl -X POST http://0.0.0.0:5001/api/v0/log/level\?arg\=autonat
{"Levels":{"autonat":"error"}}

Set log level for a specific subsystem

> curl -X POST http://0.0.0.0:5001/api/v0/log/level\?arg\=autonat\&arg\=info
{"Message":"Changed log level of 'autonat' to 'info'\n"}

Set log level for all subsystems including default

> curl -X POST http://0.0.0.0:5001/api/v0/log/level\?arg\=\*\&arg\=info
{"Message":"Changed log level of '*' to 'info'\n"}

@SgtPooki SgtPooki self-assigned this Jul 24, 2025
@SgtPooki SgtPooki marked this pull request as ready for review July 24, 2025 19:30
@SgtPooki SgtPooki requested a review from a team as a code owner July 24, 2025 19:30
@lidel
Copy link
Member

lidel commented Jul 25, 2025

Answering some questions:

Error: command must be run on the daemon: [log get-level] when I run ./ipfs log get-level

I think this is fine if you had no daemon?

This is consistent with the log level command (which also has NoLocal: true).
Both commands need to interact with the running daemon's logging system.
(in contrast to commands like ipfs cid that work just fine without daemon)

Do we want to return the key if a specific subsystem is requested?

You mean adjusting Text version (not JSON)? Yes, I think for Text output skipping level name (when provided explicitly) makes sense.

go get github.com/ipfs/go-log/v2@1d9b5d3dc8e2 && make mod_tidy
@SgtPooki

This comment was marked as resolved.

Copy link
Contributor

@gammazero gammazero left a comment

Choose a reason for hiding this comment

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

@SgtPooki @lidel
I would prefer to not have a ipfs log get-level command, but instead use the command ipfs log level without a level.

  • Get the level of the "pebble:" facility: ipfs log level pebble:
  • Set the level of the "pebble" facility: ipfs log level pebble debug

@lidel
Copy link
Member

lidel commented Jul 29, 2025

@gammazero I would also prefer to have a single command that does both get and set, but it gets hairy due to mixing global level, "all", and subsystem names.

The core issue is that "all" is used as a special keyword to represent all subsystems, but it could theoretically conflict with an actual subsystem named "all" (code has this TODO comment about this).

Currently, when users specify all, it gets internally converted to "*" (the go-log library's wildcard for global settings). We should avoid using * in RPC/CLI because if it is not in single quote marks, it has special meaning in terminal, and some shells would expand it to names of all files in a current directory.

NAMING TBD (unsure as non-native speaker) I think the all as an alias for * (default level) is a confusing word here, we should use default and apply changes requested to "default" to both global default and "default" subsystem (in case some app has one). For end user, this should be most intuitive I think?

Something like:

Get Operations (1 arg or no args)

# Get all subsystem levels including default
ipfs log level
# Output:
# default: error
# autonat: error
# dht: error
# bitswap: warn
# ...

# Get global default level only
ipfs log level default
# Output: error

# Get specific subsystem level
ipfs log level dht
# Output: error

# Get wildcard (same as default)
ipfs log level '*'
# Output: error

# Edge case: subsystem actually named "default"
ipfs log level default
# Output: error (ambiguous - shows global default, not subsystem)

Set Operations (2 args)

# Set global default level
ipfs log level default debug
# Changes: * → debug

# Set using wildcard directly
ipfs log level '*' debug
# Changes: * → debug

# Set specific subsystem level
ipfs log level dht info
# Changes: dht → info

# Set multiple levels (3+ args)
ipfs log level default debug dht info bitswap warn
# Changes: * → debug, dht → info, bitswap → warn

OR.. an alternative is to add --get 🤷

Thoughts? @gammazero @SgtPooki

@lidel
Copy link
Member

lidel commented Jul 29, 2025

Colo notes:

  • getting
    • ipfs log level → error, show --help
    • ipfs log level default → returns default level (one)
    • ipfs log level all → return all levels of all systems (incl. default)
    • ipfs log level '*' → same as ipfs log level all
  • setting
    • ipfs log level default debug → set global default
    • ipfs log level all debug → set global default
    • ipfs log level '*' debug → same as ipfs log level all debug

@gammazero
Copy link
Contributor

gammazero commented Jul 30, 2025

@lidel @SgtPooki
I have updated the PR so that the default log level cannot be individually set, separate from log subsystems. Only when setting the level of all subsystems is the default also changed. Do we ever have a case where we need to set just the default but leave the subsystems unchanged?

The use of "*" and "all" in your examples appear identical. If that is the case, then should one of those be dropped?

I updated the PR so that, when getting levels, specifying the subsystem "default" returns only the current default log level. When getting log levels for all subsystems, the default level is identified by the key "default".

The behavior IMO should be:

Examples getting log level:

  • ipfs log level → Shows default level only
  • ipfs log level '*' → Shows level of every subsystem, including default level
  • ipfs log level foo → Shows level of foo facility only

Examples setting log level:

  • ipfs log level '*' debug → Set all subsystems and default to "debug" level
  • ipfs log level '*' default → Set all subsystems to current default level
  • ipfs log level foo debug → Set level of "foo" subsystem to "debug"
  • ipfs log level foo default → Set level of "foo" subsystem to current default level

@lidel lidel mentioned this pull request Aug 5, 2025
51 tasks
@gammazero gammazero changed the title feat: add log get-level command feat: add query functionality to log level command Aug 6, 2025
@lidel lidel assigned lidel and unassigned SgtPooki Aug 6, 2025
@lidel lidel self-requested a review August 6, 2025 16:57
Copy link
Contributor

@gammazero gammazero left a comment

Choose a reason for hiding this comment

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

@lidel Thank you for these changes. Very nice finishing touch.

during testing having to quore/escape '*'  was really annoying
plus removing it is a breaking change

restored it and added tests that ensure it works the same way as '*'
@lidel
Copy link
Member

lidel commented Aug 6, 2025

@gammazero pushed one more: during testing having to quote/escape '*' in terminal feels really annoying 😅 plus removing it is was a breaking change.

I've restored all and added tests that ensure all works the same way as '*'.
(I don't think we need to worry about subsystem being named all, but even if it exists in the future, should be fine -- user just wont be able to adjust it individually)

Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

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

Lgtm, added some examples to ipfs log level --help to cover all cases and then generated tests for those cases.

@SgtPooki mind taking a look last time if this final version does all you need?

Getting Log Levels

# Show only the default fallback level
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level"
{"Levels":{"":"error"}}

# Show all subsystem levels (100+ lines)
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level?arg=all"
{"Levels":{"(default)":"error","autonat":"error","autonatv2":"error","autorelay":"error","autotls":"error","badger":"error","basichost":"error","bitswap":"error","bitswap/bsnet":"error","bitswap/client":"error","bitswap/client/getter":"error","bitswap/client/msgq":"error","bitswap/client/peermgr":"error","bitswap/client/sesspeermgr":"error","bitswap/connevtman":"error","bitswap/server":"error","bitswap/server/decision":"error","bitswap/session":"error","blankhost":"error","blockservice":"error","blockstore":"error","bootstrap":"error","boxo/gateway":"error","canonical-log":"error","chunk":"error","cmd/ipfs":"error","cmds":"error","cmds/cli":"error","cmds/files":"error","cmds/http":"error","command":"error","connmgr":"error","core":"error","core/commands":"error","core/commands/cmdenv":"error","core/commands/ipns":"error","core/server":"error","core:constructor":"error","corerepo":"error","coreunix":"error","dht":"error","dht-crawler":"error","dht.pb":"error","dht/RtDiversityFilter":"error","dht/RtRefreshManager":"error","dht/netsize":"error","discovery-backoff":"error","diversityFilter":"error","doh":"error","eventbus":"error","filestore":"error","flatfs":"error","fsrepo":"error","fullrtdht":"error","fuse/ipfs":"error","fuse/ipns":"error","fxtestplugin":"error","gc":"error","http-peer-id-auth":"error","httpnet":"error","internal/nat":"error","ipns":"error","ipns/repub":"error","keystore":"error","libp2phttp":"error","lock":"error","mdns":"error","merkledag":"error","metrics-prometheus":"error","mfs":"error","mount":"error","namesys":"error","nat":"error","net/identify":"error","node":"error","nopfs":"error","nopfs-blocks":"error","p2p-circuit":"error","p2p-config":"error","p2p-holepunch":"error","p2p-mount":"error","p2pnode":"error","path/resolver":"error","pebble":"error","peering":"error","peerstore":"error","pin":"error","ping":"error","pinning-service-http-client":"error","plugin/loader":"error","plugin/peerlog":"error","profile":"error","provider":"error","providers":"error","pstoremanager":"error","pubsub":"error","pubsub-valuestore":"error","quic-transport":"error","quic-utils":"error","rcmgr":"error","relay":"error","remotepinning/mfs":"error","resourcemanager":"error","reuseport-transport":"error","routedhost":"error","routing/composable":"error","routing/delegated":"error","routing/http/client":"error","routing/http/contentrouter":"error","routing/http/filters":"error","routing/http/server":"error","routing/provqrymgr":"error","socket-activation":"error","swarm2":"error","table":"error","tcp-demultiplex":"error","tcp-tpt":"error","ulimit":"error","unixfs":"error","unixfs-hamt":"error","upgrader":"error","webrtc-transport":"error","webrtc-transport-pion":"error","webrtc-udpmux":"error","websocket-transport":"error","webtransport":"error"}}

# Show level for 'core' subsystem only
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level?arg=core"
{"Levels":{"core":"error"}}

Setting Log Levels

# Set 'core' to 'debug' (default unchanged)
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level?arg=core&arg=debug"
{"Message":"Changed log level of 'core' to 'debug'\n"}

# Set ALL to 'info' (including default)
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level?arg=all&arg=info"
{"Message":"Changed log level of '*' to 'info'\n"}

# Reset 'core' to use current default level
$ curl -X POST "http://127.0.0.1:5001/api/v0/log/level?arg=core&arg=default"
{"Message":"Changed log level of 'core' to 'error'\n"}

Copy link
Contributor

@gammazero gammazero left a comment

Choose a reason for hiding this comment

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

I had removed all, but I like this better to avoid shell escaping

@gammazero
Copy link
Contributor

@SgtPooki Please take a look before merge, since you are primary consumer of the log level getters.

Copy link
Member Author

@SgtPooki SgtPooki left a comment

Choose a reason for hiding this comment

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

lgtm. this should work for the webui diagnostics screen. thanks!

@lidel
Copy link
Member

lidel commented Aug 11, 2025

@ipfs/kubo-maintainers fysa /sbin/tini: /lib/libc.so.6: version `GLIBC_2.38' not found (required by /sbin/tini) is due to new debian stable. workaround in 4db7d96, I will cherry-pick to master shortly

@gammazero gammazero merged commit d3cc4ff into master Aug 11, 2025
16 checks passed
@gammazero gammazero deleted the fix/add-api-v0-log--get-level branch August 11, 2025 19:43
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.

Add /api/v0/log API for querying current log levels
3 participants