nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: hashicorp/go-hclog
Pull request #13 (2017-10-05 04:13:49)

Fix sub-logger name prefixing
Sub-loggers were only having their name set if the parent logger had a name. This patch fixes that and adds some tests to boot.


Patch:
diff --git a/int.go b/int.go
index c8609c3..21f8972 100644
--- a/int.go
+++ b/int.go
@@ -369,6 +369,8 @@ func (z *intLogger) Named(name string) Logger {
 
 	if nz.name != "" {
 		nz.name = nz.name + "." + name
+	} else {
+		nz.name = name
 	}
 
 	return &nz


Test patch:
diff --git a/logger_test.go b/logger_test.go
index 0effcd6..729d273 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -109,6 +109,30 @@ func TestLogger(t *testing.T) {
 		// This test will break if you move this around, it's line dependent, just fyi
 		assert.Equal(t, "[INFO ] go-hclog/logger_test.go:100: test: this is test: who=programmer why=\"testing is fun\"\n", rest)
 	})
+
+	t.Run("prefixes the name", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			// No name!
+			Output: &buf,
+		})
+
+		logger.Info("this is test")
+		str := buf.String()
+		dataIdx := strings.IndexByte(str, ' ')
+		rest := str[dataIdx+1:]
+		assert.Equal(t, "[INFO ] this is test\n", rest)
+
+		buf.Reset()
+
+		another := logger.Named("sublogger")
+		another.Info("this is test")
+		str = buf.String()
+		dataIdx = strings.IndexByte(str, ' ')
+		rest = str[dataIdx+1:]
+		assert.Equal(t, "[INFO ] sublogger: this is test\n", rest)
+	})
 }
 
 func TestLogger_JSON(t *testing.T) {
Repository: hashicorp/go-hclog
Pull request #37 (2019-03-05 18:45:17)

Rename `NewLevelWriter` to `NewLeveledWriter`


Patch:
diff --git a/writer.go b/writer.go
index 3cb30a7..7e8ec72 100644
--- a/writer.go
+++ b/writer.go
@@ -48,11 +48,11 @@ type LeveledWriter struct {
 	overrides map[Level]io.Writer
 }
 
-// NewLevelWriter returns an initialized LeveledWriter.
+// NewLeveledWriter returns an initialized LeveledWriter.
 //
 // standard will be used as the default writer for all log levels,
 // except for log levels that are defined in the overrides map.
-func NewLevelWriter(standard io.Writer, overrides map[Level]io.Writer) *LeveledWriter {
+func NewLeveledWriter(standard io.Writer, overrides map[Level]io.Writer) *LeveledWriter {
 	return &LeveledWriter{
 		standard:  standard,
 		overrides: overrides,


Test patch:
diff --git a/logger_test.go b/logger_test.go
index e8038c4..69dffed 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -343,7 +343,7 @@ func TestLogger_leveledWriter(t *testing.T) {
 
 		logger := New(&LoggerOptions{
 			Name:   "test",
-			Output: NewLevelWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
+			Output: NewLeveledWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
 		})
 
 		logger.Error("this is an error", "who", "programmer", "why", "testing")
@@ -361,7 +361,7 @@ func TestLogger_leveledWriter(t *testing.T) {
 
 		logger := New(&LoggerOptions{
 			Name:   "test",
-			Output: NewLevelWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
+			Output: NewLeveledWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
 		})
 
 		logger.Info("this is test", "who", "programmer", "why", "testing")
@@ -379,7 +379,7 @@ func TestLogger_leveledWriter(t *testing.T) {
 
 		logger := New(&LoggerOptions{
 			Name:   "test",
-			Output: NewLevelWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
+			Output: NewLeveledWriter(&stdout, map[Level]io.Writer{Error: &stderr}),
 		})
 
 		logger.Info("this is test", "who", "programmer", "why", "testing")
Repository: hashicorp/go-hclog
Pull request #75 (2020-10-04 18:36:57)

fix: make JSON formatter respect the value of DisableTime
Plus tests for both the plain and JSON output.

Closes: #74
Signed-off-by: Marco Molteni <marco.molteni@mailbox.org>


Patch:
diff --git a/intlogger.go b/intlogger.go
index f961ed9..2d40b70 100644
--- a/intlogger.go
+++ b/intlogger.go
@@ -416,8 +416,11 @@ func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, a
 
 func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg string) map[string]interface{} {
 	vals := map[string]interface{}{
-		"@message":   msg,
-		"@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"),
+		"@message": msg,
+	}
+	if len(l.timeFormat) > 0 {
+		// FIXME this doesn't respect LoggerOptions.TimeFormat
+		vals["@timestamp"] = t.Format("2006-01-02T15:04:05.000000Z07:00")
 	}
 
 	var levelStr string


Test patch:
diff --git a/logger_test.go b/logger_test.go
index aac7233..cc908f7 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -195,6 +195,22 @@ func TestLogger(t *testing.T) {
 		assert.Equal(t, str[:dataIdx], time.Now().Format(time.Kitchen))
 	})
 
+	t.Run("respects DisableTime", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			Name:        "test",
+			Output:      &buf,
+			DisableTime: true,
+		})
+
+		logger.Info("Señorita banana")
+
+		str := buf.String()
+
+		assert.Equal(t, "[INFO]  test: Señorita banana\n", str)
+	})
+
 	t.Run("use with", func(t *testing.T) {
 		var buf bytes.Buffer
 
@@ -534,6 +550,29 @@ func TestLogger_JSON(t *testing.T) {
 		assert.Equal(t, "testing is fun", raw["why"])
 	})
 
+	t.Run("respects DisableTime", func(t *testing.T) {
+		var buf bytes.Buffer
+		logger := New(&LoggerOptions{
+			Name:        "test",
+			Output:      &buf,
+			JSONFormat:  true,
+			DisableTime: true,
+		})
+
+		logger.Info("Señorita banana")
+
+		b := buf.Bytes()
+
+		var raw map[string]interface{}
+		if err := json.Unmarshal(b, &raw); err != nil {
+			t.Fatal(err)
+		}
+
+		if val, ok := raw["@timestamp"]; ok {
+			t.Fatalf("got: '@timestamp' key (with value %v); want: no '@timestamp' key", val)
+		}
+	})
+
 	t.Run("json formatting with", func(t *testing.T) {
 		var buf bytes.Buffer
 		logger := New(&LoggerOptions{
Repository: hashicorp/go-hclog
Pull request #79 (2020-10-22 16:41:42)

add Level Off
Add an Off log level so that loggers can be easily disabled while
allowing other named loggers to use the same synchronized output.


Patch:
diff --git a/logger.go b/logger.go
index b29d396..68da277 100644
--- a/logger.go
+++ b/logger.go
@@ -38,6 +38,9 @@ const (
 
 	// Error information about unrecoverable events.
 	Error Level = 5
+
+	// Off disables all logging output.
+	Off Level = 6
 )
 
 // Format is a simple convience type for when formatting is required. When
@@ -96,6 +99,8 @@ func LevelFromString(levelStr string) Level {
 		return Warn
 	case "error":
 		return Error
+	case "off":
+		return Off
 	default:
 		return NoLevel
 	}
@@ -115,6 +120,8 @@ func (l Level) String() string {
 		return "error"
 	case NoLevel:
 		return "none"
+	case Off:
+		return "off"
 	default:
 		return "unknown"
 	}


Test patch:
diff --git a/logger_test.go b/logger_test.go
index ed6fcdf..8c0453e 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -413,6 +413,32 @@ func TestLogger(t *testing.T) {
 		rest = str[dataIdx+1:]
 		assert.Equal(t, "[INFO]  this is another test: production=\"13 beans/day\"\n", rest)
 	})
+
+	t.Run("named logger with disabled parent", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			// No name!
+			Output: &buf,
+			Level:  Off,
+		})
+
+		logger.Info("this is test")
+		str := buf.String()
+		if len(str) > 0 {
+			t.Fatal("output from disabled logger:", str)
+		}
+
+		buf.Reset()
+
+		another := logger.Named("sublogger")
+		another.SetLevel(Info)
+		another.Info("this is test")
+		str = buf.String()
+		dataIdx := strings.IndexByte(str, ' ')
+		rest := str[dataIdx+1:]
+		assert.Equal(t, "[INFO]  sublogger: this is test\n", rest)
+	})
 }
 
 func TestLogger_leveledWriter(t *testing.T) {
Repository: hashicorp/go-hclog
Pull request #102 (2021-11-30 21:52:35)

Set `raw=true` when special casing empty strings
Found that empty strings are being rendered as `foo="\"\"'`. Added `raw=true` to the special case for them and that appears to resolve the issue.  Added a test to capture the situation.


Patch:
diff --git a/intlogger.go b/intlogger.go
index fd51af1..e2362e8 100644
--- a/intlogger.go
+++ b/intlogger.go
@@ -281,6 +281,7 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string,
 				val = st
 				if st == "" {
 					val = `""`
+					raw = true
 				}
 			case int:
 				val = strconv.FormatInt(int64(st), 10)


Test patch:
diff --git a/logger_test.go b/logger_test.go
index 403c699..d70ed9e 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -120,6 +120,23 @@ func TestLogger(t *testing.T) {
 		assert.Equal(t, `[INFO]  test: this is test: who=programmer why="this is \"quoted\""`+"\n", rest)
 	})
 
+	t.Run("prints empty double quotes for empty strings", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			Name:   "test",
+			Output: &buf,
+		})
+
+		logger.Info("this is test", "who", "programmer", "why", ``)
+
+		str := buf.String()
+		dataIdx := strings.IndexByte(str, ' ')
+		rest := str[dataIdx+1:]
+
+		assert.Equal(t, `[INFO]  test: this is test: who=programmer why=""`+"\n", rest)
+	})
+
 	t.Run("quotes when there are nonprintable sequences in a value", func(t *testing.T) {
 		var buf bytes.Buffer
Repository: hashicorp/go-hclog
Pull request #137 (2023-12-12 20:58:25)

Conside if the level is to be used separately from if the levels should be calculated


Patch:
diff --git a/intlogger.go b/intlogger.go
index 1a80008..104d82f 100644
--- a/intlogger.go
+++ b/intlogger.go
@@ -93,6 +93,9 @@ type intLogger struct {
 	writer *writer
 	level  *int32
 
+	// The value of curEpoch when our level was set
+	setEpoch uint64
+
 	// The value of curEpoch the last time we performed the level sync process
 	ownEpoch uint64
 
@@ -892,6 +895,7 @@ func (l *intLogger) SetLevel(level Level) {
 	l.level = nsl
 
 	l.ownEpoch = atomic.AddUint64(l.curEpoch, 1)
+	l.setEpoch = l.ownEpoch
 }
 
 func (l *intLogger) searchLevelPtr() *int32 {
@@ -899,11 +903,11 @@ func (l *intLogger) searchLevelPtr() *int32 {
 
 	ptr := l.level
 
-	max := l.ownEpoch
+	max := l.setEpoch
 
 	for p != nil {
-		if p.ownEpoch > max {
-			max = p.ownEpoch
+		if p.setEpoch > max {
+			max = p.setEpoch
 			ptr = p.level
 		}
 


Test patch:
diff --git a/logger_test.go b/logger_test.go
index 1ab9fd5..dea7013 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -666,7 +666,44 @@ func TestLogger(t *testing.T) {
 		assert.Equal(t, Error, b.GetLevel())
 	})
 
-	t.Run("level sync example", func(t *testing.T) {
+	t.Run("level sync example 1", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			Name:            "root",
+			Output:          &buf,
+			SyncParentLevel: true,
+		})
+
+		s := assert.New(t)
+
+		a := logger.Named("a")
+		b := a.Named("b")
+		c := a.Named("c")
+
+		b.SetLevel(Warn)
+		s.Equal(Info, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+		s.Equal(Info, c.GetLevel())
+
+		c.SetLevel(Error)
+		s.Equal(Info, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+		s.Equal(Error, c.GetLevel())
+
+		a.SetLevel(Warn)
+		s.Equal(Warn, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+		s.Equal(Warn, c.GetLevel())
+
+		logger.SetLevel(Trace)
+		s.Equal(Trace, logger.GetLevel())
+		s.Equal(Trace, a.GetLevel())
+		s.Equal(Trace, b.GetLevel())
+		s.Equal(Trace, c.GetLevel())
+	})
+
+	t.Run("level sync example 2", func(t *testing.T) {
 		var buf bytes.Buffer
 
 		logger := New(&LoggerOptions{
@@ -700,6 +737,40 @@ func TestLogger(t *testing.T) {
 		s.Equal(Trace, b.GetLevel())
 		s.Equal(Trace, c.GetLevel())
 	})
+	t.Run("level sync example 3", func(t *testing.T) {
+		var buf bytes.Buffer
+
+		logger := New(&LoggerOptions{
+			Name:            "root",
+			Output:          &buf,
+			SyncParentLevel: true,
+		})
+
+		s := assert.New(t)
+
+		a := logger.Named("a")
+		b := a.Named("b")
+
+		a.SetLevel(Trace)
+		s.Equal(Trace, a.GetLevel())
+		s.Equal(Trace, b.GetLevel())
+
+		b.SetLevel(Warn)
+		s.Equal(Trace, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+
+		c := a.Named("c")
+
+		c.SetLevel(Error)
+		s.Equal(Trace, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+		s.Equal(Error, c.GetLevel())
+
+		a.SetLevel(Warn)
+		s.Equal(Warn, a.GetLevel())
+		s.Equal(Warn, b.GetLevel())
+		s.Equal(Warn, c.GetLevel())
+	})
 }
 
 func TestLogger_leveledWriter(t *testing.T) {