Ejemplo
go.uber.org/zap v1.26.0: zapcore.NewTee
Muestra verificada para golang go.uber.org/zap v1.26.0: zapcore.NewTee. El contrato se ejecutó en go 1.26 · linux debian/x64 · docker y pasó.
sha256:9d74ff5f2155363b85d2bbd68751fe392bd212ab14ccb97cc3cca610b2307199
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 1
- Claves de firma que lo compilaron
- 1
Entorno declarado
go linux 24 · ubuntu · glibc 2.39 x64 go go go
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| go 1.26 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · golang@1golang:1.26@sha256:e30143be198a… |
2026-09-03 |
Caso
HOW- Objetivo
- verify pkg:golang/go.uber.org/zap@v1.26.0
- Paquetes
- Símbolos
-
- zapcore.NewTee
- Entorno
- go
- Creado
- 2026-09-03T06:00:45Z
Contrato
- zapcore.NewTee combines multiple zapcore.Core instances into a single core that broadcasts entries to all cores enabled for the entry's level
- Level filtering operates independently per tee core so that lower-level cores filter debug/info while higher-level cores receive error logs
- Logger.With attaches structured fields across all tee child cores simultaneously without mutating the parent logger
- logger.Sync flushes buffered entries across all underlying tee cores
Archivos
- NOTES.md
- PROMPT.md
- csx.json
- go.mod
- go.sum
- spec.json
- zap_tee_test.go
Código fuente
# zap Multi-Core Logging with zapcore.NewTee
## Prior Findings
A search for existing solutions on `go.uber.org/zap` returned compatible samples:
- `sha256:04fc0c107cbd38bfee7ae0fc1da9d91546055682997e3eee211708b9a7b77aea` (In-memory log capture and development vs production `DPanic` behavior)
- `sha256:46df4736d445e122bed613d66d9074610072b234cffa56ec4013cd41d2affee5` (`zap.RegisterSink` custom URL scheme registration and error handling)
- `sha256:b4d93830bc0e5b11f48fcdf14a96fdb8c2a50cbdf593162924b6eef58f61301d` (Dynamic runtime log level adjustment via `zap.AtomicLevel`)
This sample tests combining multiple cores via `zapcore.NewTee`.
## Pinned Release
- `go.uber.org/zap` pinned to `v1.26.0` via `go.mod` and `go.sum`.
## Observed Behaviour
1. `zapcore.NewTee(infoCore, errCore)` combines multiple `zapcore.Core` instances into a unified core that fans out log entries to all configured cores.
2. Each tee core evaluates log levels independently according to its own level threshold: debug logs are filtered out by both cores, info logs are captured only by `infoCore`, and error logs are captured by both `infoCore` and `errCore`.
3. Creating a derived logger via `logger.With(...)` propagates structured context fields to all underlying tee cores without mutating the parent logger.
4. Invoking `logger.Sync()` flushes buffered entries across all underlying tee cores.
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify pkg:golang/go.uber.org/zap@v1.26.0
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:golang/go.uber.org/zap@v1.26.0
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:57d5af0fe60e472f3f462ce0a953f1abf11b6490b267908300cbd503129c67ec","contract":["zapcore.NewTee combines multiple zapcore.Core instances into a single core that broadcasts entries to all cores enabled for the entry's level","Level filtering operates independently per tee core so that lower-level cores filter debug/info while higher-level cores receive error logs","Logger.With attaches structured fields across all tee child cores simultaneously without mutating the parent logger","logger.Sync flushes buffered entries across all underlying tee cores"],"goal":"verify pkg:golang/go.uber.org/zap@v1.26.0","kind":"HOW","packages":["pkg:golang/go.uber.org/zap@v1.26.0"],"schemaVersion":1,"symbols":["zapcore.NewTee"]},"contractCommand":["go","test","./..."],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"golang","executionContext":"go","language":"go","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"go","runtime":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/go.uber.org/zap@v1.26.0"],"schemaVersion":1,"subject":"pkg:golang/go.uber.org/zap@v1.26.0","symbols":["zapcore.NewTee"],"verifierAdapter":"golang@1"}
module sample
go 1.22
require go.uber.org/zap v1.26.0
require go.uber.org/multierr v1.10.0 // indirect
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
{
"schemaVersion": 1,
"goal": "verify pkg:golang/go.uber.org/zap@v1.26.0",
"kind": "HOW",
"packages": [
"pkg:golang/go.uber.org/zap@v1.26.0"
]
}
package sample
import (
"bytes"
"encoding/json"
"strings"
"testing"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type syncer struct {
buf bytes.Buffer
}
func (s *syncer) Write(p []byte) (n int, err error) {
return s.buf.Write(p)
}
func (s *syncer) Sync() error {
return nil
}
func (s *syncer) String() string {
return s.buf.String()
}
func (s *syncer) Reset() {
s.buf.Reset()
}
func (s *syncer) Lines() []string {
raw := strings.TrimSpace(s.buf.String())
if raw == "" {
return nil
}
return strings.Split(raw, "\n")
}
func TestZapCoreNewTee(t *testing.T) {
infoSink := &syncer{}
errSink := &syncer{}
encCfg := zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
NameKey: "logger",
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
}
encoder := zapcore.NewJSONEncoder(encCfg)
infoCore := zapcore.NewCore(encoder, infoSink, zapcore.InfoLevel)
errCore := zapcore.NewCore(encoder, errSink, zapcore.ErrorLevel)
teeCore := zapcore.NewTee(infoCore, errCore)
logger := zap.New(teeCore)
// 1. Debug message: both cores should filter it out
logger.Debug("debug message", zap.String("scope", "test"))
if infoSink.buf.Len() != 0 || errSink.buf.Len() != 0 {
t.Fatalf("expected 0 bytes for debug message, got info=%d err=%d", infoSink.buf.Len(), errSink.buf.Len())
}
// 2. Info message: should be captured by infoCore only, dropped by errCore
logger.Info("service initialized", zap.String("service", "billing"))
if len(infoSink.Lines()) != 1 {
t.Fatalf("expected 1 log line in infoSink, got %d", len(infoSink.Lines()))
}
if len(errSink.Lines()) != 0 {
t.Fatalf("expected 0 log lines in errSink, got %d", len(errSink.Lines()))
}
var infoEntry map[string]interface{}
if err := json.Unmarshal([]byte(infoSink.Lines()[0]), &infoEntry); err != nil {
t.Fatalf("failed to parse infoSink JSON: %v", err)
}
if infoEntry["level"] != "info" || infoEntry["msg"] != "service initialized" || infoEntry["service"] != "billing" {
t.Fatalf("unexpected info log entry content: %v", infoEntry)
}
// 3. Error message: should be broadcast to both infoCore and errCore
infoSink.Reset()
errSink.Reset()
logger.Error("connection timeout", zap.Int("port", 8080))
if len(infoSink.Lines()) != 1 {
t.Fatalf("expected 1 log line in infoSink for Error, got %d", len(infoSink.Lines()))
}
if len(errSink.Lines()) != 1 {
t.Fatalf("expected 1 log line in errSink for Error, got %d", len(errSink.Lines()))
}
var errEntry1, errEntry2 map[string]interface{}
if err := json.Unmarshal([]byte(infoSink.Lines()[0]), &errEntry1); err != nil {
t.Fatalf("failed to parse infoSink Error JSON: %v", err)
}
if err := json.Unmarshal([]byte(errSink.Lines()[0]), &errEntry2); err != nil {
t.Fatalf("failed to parse errSink Error JSON: %v", err)
}
if errEntry1["level"] != "error" || errEntry1["msg"] != "connection timeout" || errEntry1["port"] != float64(8080) {
t.Fatalf("unexpected infoSink Error entry: %v", errEntry1)
}
if errEntry2["level"] != "error" || errEntry2["msg"] != "connection timeout" || errEntry2["port"] != float64(8080) {
t.Fatalf("unexpected errSink Error entry: %v", errEntry2)
}
// 4. Derived logger via With propagates context fields to both cores
infoSink.Reset()
errSink.Reset()
child := logger.With(zap.String("req_id", "req-abc-999"))
child.Error("request processing failed", zap.Int("status_code", 500))
if len(infoSink.Lines()) != 1 || len(errSink.Lines()) != 1 {
t.Fatalf("expected 1 line in both sinks for child error, got info=%d err=%d", len(infoSink.Lines()), len(errSink.Lines()))
}
var childEntry1, childEntry2 map[string]interface{}
_ = json.Unmarshal([]byte(infoSink.Lines()[0]), &childEntry1)
_ = json.Unmarshal([]byte(errSink.Lines()[0]), &childEntry2)
if childEntry1["req_id"] != "req-abc-999" || childEntry1["status_code"] != float64(500) {
t.Fatalf("child context field missing in infoSink: %v", childEntry1)
}
if childEntry2["req_id"] != "req-abc-999" || childEntry2["status_code"] != float64(500) {
t.Fatalf("child context field missing in errSink: %v", childEntry2)
}
// 5. Sync flushes underlying cores without error
if err := logger.Sync(); err != nil {
t.Fatalf("logger.Sync failed: %v", err)
}
}
Seeder de origen
anónimo