Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/examples/kubo-as-a-library/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ replace github.com/ipfs/kubo => ./../../..
require (
github.com/ipfs/boxo v0.35.0
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
github.com/libp2p/go-libp2p v0.44.0
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d
github.com/multiformats/go-multiaddr v0.16.1
)

Expand Down Expand Up @@ -93,7 +93,7 @@ require (
github.com/ipfs/go-ipld-format v0.6.3 // indirect
github.com/ipfs/go-ipld-git v0.1.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.2 // indirect
github.com/ipfs/go-log/v2 v2.8.2 // indirect
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b // indirect
github.com/ipfs/go-metrics-interface v0.3.0 // indirect
github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
github.com/ipfs/go-test v0.2.3 // indirect
Expand Down
8 changes: 4 additions & 4 deletions docs/examples/kubo-as-a-library/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.8.2 h1:nVG4nNHUwwI/sTs9Bi5iE8sXFQwXs3AjkkuWhg7+Y2I=
github.com/ipfs/go-log/v2 v2.8.2/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b h1:PtG74rADTbq3f5xA62rjmHd4rRq+rV5uM4E+g3y4ZGM=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
Expand Down Expand Up @@ -428,8 +428,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs=
github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d h1:Qvs1oreO7W7UAboqY402BiYfvBpw+gC70CUW6rv6e+c=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ require (
github.com/ipfs/go-ipld-format v0.6.3
github.com/ipfs/go-ipld-git v0.1.1
github.com/ipfs/go-ipld-legacy v0.2.2
github.com/ipfs/go-log/v2 v2.8.2
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b
github.com/ipfs/go-metrics-interface v0.3.0
github.com/ipfs/go-metrics-prometheus v0.1.0
github.com/ipfs/go-test v0.2.3
Expand All @@ -51,7 +51,7 @@ require (
github.com/jbenet/go-temp-err-catcher v0.1.0
github.com/julienschmidt/httprouter v1.3.0
github.com/libp2p/go-doh-resolver v0.5.0
github.com/libp2p/go-libp2p v0.44.0
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d
github.com/libp2p/go-libp2p-http v0.5.0
github.com/libp2p/go-libp2p-kad-dht v0.35.2-0.20251017193437-abd04263daac
github.com/libp2p/go-libp2p-kbucket v0.8.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.8.2 h1:nVG4nNHUwwI/sTs9Bi5iE8sXFQwXs3AjkkuWhg7+Y2I=
github.com/ipfs/go-log/v2 v2.8.2/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b h1:PtG74rADTbq3f5xA62rjmHd4rRq+rV5uM4E+g3y4ZGM=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
github.com/ipfs/go-metrics-prometheus v0.1.0 h1:bApWOHkrH3VTBHzTHrZSfq4n4weOZDzZFxUXv+HyKcA=
Expand Down Expand Up @@ -508,8 +508,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs=
github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d h1:Qvs1oreO7W7UAboqY402BiYfvBpw+gC70CUW6rv6e+c=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
Expand Down
163 changes: 163 additions & 0 deletions test/cli/log_level_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package cli

import (
"bufio"
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"os/exec"
"strings"
"testing"
"time"

"github.com/ipfs/kubo/test/cli/harness"
. "github.com/ipfs/kubo/test/cli/testutils"
Expand Down Expand Up @@ -599,6 +604,164 @@ func TestLogLevel(t *testing.T) {
})
})

// Constants for slog interop tests
const (
slogTestLogTailTimeout = 10 * time.Second
slogTestLogWaitTimeout = 5 * time.Second
slogTestLogStartupDelay = 1 * time.Second // Wait for log tail to start
slogTestSubsystemCmdsHTTP = "cmds/http" // Native go-log subsystem
slogTestSubsystemNetIdentify = "net/identify" // go-libp2p slog subsystem
)

// logMatch represents a matched log entry for slog interop tests
type logMatch struct {
subsystem string
line string
}

// startLogMonitoring starts ipfs log tail and returns command and channel for matched logs.
startLogMonitoring := func(t *testing.T, node *harness.Node) (*exec.Cmd, chan logMatch) {
t.Helper()

ctx, cancel := context.WithTimeout(context.Background(), slogTestLogTailTimeout)
t.Cleanup(cancel)

cmd := exec.CommandContext(ctx, node.IPFSBin, "log", "tail")
cmd.Env = append([]string(nil), os.Environ()...)
for k, v := range node.Runner.Env {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
}
cmd.Dir = node.Runner.Dir

stdout, err := cmd.StdoutPipe()
require.NoError(t, err)
require.NoError(t, cmd.Start())

matches := make(chan logMatch, 10)

go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
// Check for actual logger field in JSON, not just substring match
if strings.Contains(line, `"logger":"cmds/http"`) {
matches <- logMatch{slogTestSubsystemCmdsHTTP, line}
}
if strings.Contains(line, `"logger":"net/identify"`) {
matches <- logMatch{slogTestSubsystemNetIdentify, line}
}
}
}()

return cmd, matches
}

// waitForBothSubsystems waits for both native go-log and slog subsystems to appear in logs.
waitForBothSubsystems := func(t *testing.T, matches chan logMatch, timeout time.Duration) {
t.Helper()

seen := make(map[string]struct{})
deadline := time.After(timeout)

for len(seen) < 2 {
select {
case match := <-matches:
if _, exists := seen[match.subsystem]; !exists {
t.Logf("Found %s log", match.subsystem)
seen[match.subsystem] = struct{}{}
}
case <-deadline:
t.Fatalf("Timeout waiting for logs. Seen: %v", seen)
}
}

assert.Contains(t, seen, slogTestSubsystemCmdsHTTP, "should see cmds/http (native go-log)")
assert.Contains(t, seen, slogTestSubsystemNetIdentify, "should see net/identify (slog from go-libp2p)")
}

// triggerIdentifyProtocol connects node1 to node2, triggering net/identify logs.
triggerIdentifyProtocol := func(t *testing.T, node1, node2 *harness.Node) {
t.Helper()

// Get node2's peer ID and address
node2ID := node2.PeerID().String()
addrsRes := node2.IPFS("id", "-f", "<addrs>")
require.NoError(t, addrsRes.Err)

addrs := strings.Split(strings.TrimSpace(addrsRes.Stdout.String()), "\n")
require.NotEmpty(t, addrs, "node2 should have at least one address")

// Connect node1 to node2
multiaddr := fmt.Sprintf("%s/p2p/%s", addrs[0], node2ID)
res := node1.IPFS("swarm", "connect", multiaddr)
require.NoError(t, res.Err)
}

// verifySlogInterop verifies that both native go-log and slog from go-libp2p
// appear in ipfs log tail with correct formatting and level control.
verifySlogInterop := func(t *testing.T, node1, node2 *harness.Node) {
t.Helper()

cmd, matches := startLogMonitoring(t, node1)
defer func() {
_ = cmd.Process.Kill()
}()

time.Sleep(slogTestLogStartupDelay)

// Trigger cmds/http (native go-log)
node1.IPFS("version")

// Trigger net/identify (slog from go-libp2p)
triggerIdentifyProtocol(t, node1, node2)

waitForBothSubsystems(t, matches, slogTestLogWaitTimeout)
}

// This test verifies that go-log's slog bridge works with go-libp2p's gologshim
// when log levels are set via GOLOG_LOG_LEVEL environment variable.
// It tests both native go-log loggers (cmds/http) and slog-based loggers from
// go-libp2p (net/identify), ensuring both types appear in `ipfs log tail`.
t.Run("slog interop via env var", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)

node1 := h.NewNode().Init()
node1.Runner.Env["GOLOG_LOG_LEVEL"] = "error,cmds/http=debug,net/identify=debug"
node1.StartDaemon()
defer node1.StopDaemon()

node2 := h.NewNode().Init().StartDaemon()
defer node2.StopDaemon()

verifySlogInterop(t, node1, node2)
})

// This test verifies that go-log's slog bridge works with go-libp2p's gologshim
// when log levels are set dynamically via `ipfs log level` CLI commands.
// It tests the key feature that SetLogLevel auto-creates level entries for subsystems
// that don't exist yet, enabling `ipfs log level net/identify debug` to work even
// before the net/identify logger is created. This is critical for slog interop.
t.Run("slog interop via CLI", func(t *testing.T) {
t.Parallel()
h := harness.NewT(t)

node1 := h.NewNode().Init().StartDaemon()
defer node1.StopDaemon()

node2 := h.NewNode().Init().StartDaemon()
defer node2.StopDaemon()

// Set levels via CLI for both subsystems BEFORE triggering events
res := node1.IPFS("log", "level", slogTestSubsystemCmdsHTTP, "debug")
require.NoError(t, res.Err)

res = node1.IPFS("log", "level", slogTestSubsystemNetIdentify, "debug")
require.NoError(t, res.Err) // Auto-creates level entry for slog subsystem

verifySlogInterop(t, node1, node2)
})

}

func getExpectedSubsystems(t *testing.T, node *harness.Node) []string {
Expand Down
4 changes: 2 additions & 2 deletions test/dependencies/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
github.com/golangci/golangci-lint v1.64.8
github.com/ipfs/go-cidutil v0.1.0
github.com/ipfs/go-log/v2 v2.8.2
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b
github.com/ipfs/go-test v0.2.3
github.com/ipfs/hang-fds v0.1.0
github.com/ipfs/iptb v1.4.1
Expand Down Expand Up @@ -182,7 +182,7 @@ require (
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-doh-resolver v0.5.0 // indirect
github.com/libp2p/go-flow-metrics v0.3.0 // indirect
github.com/libp2p/go-libp2p v0.44.0 // indirect
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.35.2-0.20251017193437-abd04263daac // indirect
github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions test/dependencies/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aO
github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.8.2 h1:nVG4nNHUwwI/sTs9Bi5iE8sXFQwXs3AjkkuWhg7+Y2I=
github.com/ipfs/go-log/v2 v2.8.2/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b h1:PtG74rADTbq3f5xA62rjmHd4rRq+rV5uM4E+g3y4ZGM=
github.com/ipfs/go-log/v2 v2.8.3-0.20251028000959-dc9bb9f04e8b/go.mod h1:UhIYAwMV7Nb4ZmihUxfIRM2Istw/y9cAk3xaK+4Zs2c=
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
Expand Down Expand Up @@ -464,8 +464,8 @@ github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+s
github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU=
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs=
github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d h1:Qvs1oreO7W7UAboqY402BiYfvBpw+gC70CUW6rv6e+c=
github.com/libp2p/go-libp2p v0.44.1-0.20251027235033-ea2c010ece2d/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-kad-dht v0.35.2-0.20251017193437-abd04263daac h1:2TWHkp8MJBLfwIRMUfvjFb2DABcjLaYAwVBzAEirkhU=
Expand Down
Loading