kandi background
Explore Kits

zap | Blazing fast , structured , leveled logging in Go

 by   uber-go Go Version: v1.21.0 License: MIT

 by   uber-go Go Version: v1.21.0 License: MIT

Download this library from

kandi X-RAY | zap Summary

zap is a Go library typically used in Logging, Kafka applications. zap has no bugs, it has no vulnerabilities, it has a Permissive License and it has medium support. You can download it from GitHub.
Blazing fast, structured, leveled logging in Go.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • zap has a medium active ecosystem.
  • It has 15297 star(s) with 1127 fork(s). There are 249 watchers for this library.
  • There were 2 major release(s) in the last 12 months.
  • There are 84 open issues and 448 have been closed. On average issues are closed in 129 days. There are 18 open pull requests and 0 closed requests.
  • It has a neutral sentiment in the developer community.
  • The latest version of zap is v1.21.0
zap Support
Best in #Go
Average in #Go
zap Support
Best in #Go
Average in #Go

quality kandi Quality

  • zap has 0 bugs and 0 code smells.
zap Quality
Best in #Go
Average in #Go
zap Quality
Best in #Go
Average in #Go

securitySecurity

  • zap has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • zap code analysis shows 0 unresolved vulnerabilities.
  • There are 0 security hotspots that need review.
zap Security
Best in #Go
Average in #Go
zap Security
Best in #Go
Average in #Go

license License

  • zap is licensed under the MIT License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
zap License
Best in #Go
Average in #Go
zap License
Best in #Go
Average in #Go

buildReuse

  • zap releases are available to install and integrate.
  • Installation instructions, examples and code snippets are available.
  • It has 13238 lines of code, 939 functions and 128 files.
  • It has medium code complexity. Code complexity directly impacts maintainability of the code.
zap Reuse
Best in #Go
Average in #Go
zap Reuse
Best in #Go
Average in #Go
Top functions reviewed by kandi - BETA

kandi's functional review helps you automatically verify the functionalities of the libraries and avoid rework.
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here

Get all kandi verified functions for this library.

Get all kandi verified functions for this library.

zap Key Features

Blazing fast, structured, leveled logging in Go.

zap Examples and Code Snippets

See all related Code Snippets

Quick Start

copy iconCopydownload iconDownload
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
  // Structured context as loosely typed key-value pairs.
  "url", url,
  "attempt", 3,
  "backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)

Is it possible to update the log level of a zap logger at runtime?

copy iconCopydownload iconDownload
    // will be actually initialized and changed at run time 
    // based on your business logic
    var infoEnabled bool 

    errorUnlessEnabled := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
        // true: log message at this level
        // false: skip message at this level
        return level >= zapcore.ErrorLevel || infoEnabled
    })

    core := zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        os.Stdout,
        errorUnlessEnabled,
    )
    logger := zap.New(core)

    logger.Info("foo") // not logged
    
    infoEnabled = true

    logger.Info("foo again") // logged
atom := zap.NewAtomicLevel()

// To keep the example deterministic, disable timestamps in the output.
encoderCfg := zap.NewProductionEncoderConfig()
encoderCfg.TimeKey = ""

logger := zap.New(zapcore.NewCore(
    zapcore.NewJSONEncoder(encoderCfg),
    zapcore.Lock(os.Stdout),
    atom,
))
defer logger.Sync()

logger.Info("info logging enabled")
atom.SetLevel(zap.ErrorLevel)
logger.Info("info logging disabled")

UDF executing multiple times with Structured References

copy iconCopydownload iconDownload
=@zap([@A],[@B]) 

How to access Fields in zap Hooks?

copy iconCopydownload iconDownload
type spewDumpEncoder struct {
    zapcore.Encoder
}

func (e *spewDumpEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return e.Encoder.EncodeEntry(entry, fields)
}
type MyCore struct {
    zapcore.Core
}

func (c *MyCore) Check(entry zapcore.Entry, checked *zapcore.CheckedEntry) *zapcore.CheckedEntry {
    if c.Enabled(entry.Level) {
        return checked.AddCore(entry, c)
    }
    return checked
}

func (c *MyCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return c.Core.Write(entry, fields)
}
    l, _ := zap.NewProduction()
    logger := zap.New(&MyCore{Core: l.Core()})
type spewDumpEncoder struct {
    zapcore.Encoder
}

func (e *spewDumpEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return e.Encoder.EncodeEntry(entry, fields)
}
type MyCore struct {
    zapcore.Core
}

func (c *MyCore) Check(entry zapcore.Entry, checked *zapcore.CheckedEntry) *zapcore.CheckedEntry {
    if c.Enabled(entry.Level) {
        return checked.AddCore(entry, c)
    }
    return checked
}

func (c *MyCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return c.Core.Write(entry, fields)
}
    l, _ := zap.NewProduction()
    logger := zap.New(&MyCore{Core: l.Core()})
type spewDumpEncoder struct {
    zapcore.Encoder
}

func (e *spewDumpEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return e.Encoder.EncodeEntry(entry, fields)
}
type MyCore struct {
    zapcore.Core
}

func (c *MyCore) Check(entry zapcore.Entry, checked *zapcore.CheckedEntry) *zapcore.CheckedEntry {
    if c.Enabled(entry.Level) {
        return checked.AddCore(entry, c)
    }
    return checked
}

func (c *MyCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
    if entry.Level == zapcore.ErrorLevel {
        spew.Dump(entry, fields)
    }
    return c.Core.Write(entry, fields)
}
    l, _ := zap.NewProduction()
    logger := zap.New(&MyCore{Core: l.Core()})

Why custom encoding is lost after calling logger.With in Uber Zap?

copy iconCopydownload iconDownload
type prependEncoder struct {
    zapcore.Encoder
    pool buffer.Pool
    cfg  zapcore.EncoderConfig
}

func (e *prependEncoder) Clone() zapcore.Encoder {
    return &prependEncoder{
        // cloning the encoder with the base config
        Encoder: zapcore.NewConsoleEncoder(e.cfg),
        pool:    buffer.NewPool(),
        cfg:     e.cfg,
    }
}
    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
    child := logger.With(zap.String("foo", "bar"))
    logger.Warn("original")
    child.Info("new one")
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
cloning...
<4> WARN        original
<6> INFO        new one {"foo": "bar"}
type prependEncoder struct {
    zapcore.Encoder
    pool buffer.Pool
    cfg  zapcore.EncoderConfig
}

func (e *prependEncoder) Clone() zapcore.Encoder {
    return &prependEncoder{
        // cloning the encoder with the base config
        Encoder: zapcore.NewConsoleEncoder(e.cfg),
        pool:    buffer.NewPool(),
        cfg:     e.cfg,
    }
}
    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
    child := logger.With(zap.String("foo", "bar"))
    logger.Warn("original")
    child.Info("new one")
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
cloning...
<4> WARN        original
<6> INFO        new one {"foo": "bar"}
type prependEncoder struct {
    zapcore.Encoder
    pool buffer.Pool
    cfg  zapcore.EncoderConfig
}

func (e *prependEncoder) Clone() zapcore.Encoder {
    return &prependEncoder{
        // cloning the encoder with the base config
        Encoder: zapcore.NewConsoleEncoder(e.cfg),
        pool:    buffer.NewPool(),
        cfg:     e.cfg,
    }
}
    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
    child := logger.With(zap.String("foo", "bar"))
    logger.Warn("original")
    child.Info("new one")
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
cloning...
<4> WARN        original
<6> INFO        new one {"foo": "bar"}

Uber Zap Logger: how to prepend every log entry with a string

copy iconCopydownload iconDownload
type prependEncoder struct {
    // embed a zapcore encoder
    // this makes prependEncoder implement the interface without extra work
    zapcore.Encoder

    // zap buffer pool
    pool buffer.Pool
}

// implementing only EncodeEntry
func (e *prependEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    // new log buffer
    buf := e.pool.Get()

    // prepend the JournalD prefix based on the entry level
    buf.AppendString(e.toJournaldPrefix(entry.Level))
    buf.AppendString(" ")

    // calling the embedded encoder's EncodeEntry to keep the original encoding format 
    consolebuf, err := e.Encoder.EncodeEntry(entry, fields)
    if err != nil {
        return nil, err
    }

    // just write the output into your own buffer
    _, err = buf.Write(consolebuf.Bytes())
    if err != nil {
        return nil, err
    }
    return buf, nil
}

// some mapper function
func (e *prependEncoder) toJournaldPrefix(lvl zapcore.Level) string {
    switch lvl {
    case zapcore.DebugLevel:
        return "<7>"
    case zapcore.InfoLevel:
        return "<6>"
    case zapcore.WarnLevel:
        return "<4>"
    }
    return ""
}
package main

import (
    "go.uber.org/zap"
    "go.uber.org/zap/buffer"
    "go.uber.org/zap/zapcore"
    "os"
)

func getConfig() zap.Config {
    // your current config options
    return config
}

func main() {
    cfg := getConfig()

    // constructing our prependEncoder with a ConsoleEncoder using your original configs
    enc := &prependEncoder{
        Encoder: zapcore.NewConsoleEncoder(cfg.EncoderConfig),
        pool:    buffer.NewPool(),
    }

    logger := zap.New(
        zapcore.NewCore(
            enc,
            os.Stdout,
            zapcore.DebugLevel,
        ),
        // this mimics the behavior of NewProductionConfig.Build
        zap.ErrorOutput(os.Stderr), 
    )

    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
}
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
type prependEncoder struct {
    // embed a zapcore encoder
    // this makes prependEncoder implement the interface without extra work
    zapcore.Encoder

    // zap buffer pool
    pool buffer.Pool
}

// implementing only EncodeEntry
func (e *prependEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    // new log buffer
    buf := e.pool.Get()

    // prepend the JournalD prefix based on the entry level
    buf.AppendString(e.toJournaldPrefix(entry.Level))
    buf.AppendString(" ")

    // calling the embedded encoder's EncodeEntry to keep the original encoding format 
    consolebuf, err := e.Encoder.EncodeEntry(entry, fields)
    if err != nil {
        return nil, err
    }

    // just write the output into your own buffer
    _, err = buf.Write(consolebuf.Bytes())
    if err != nil {
        return nil, err
    }
    return buf, nil
}

// some mapper function
func (e *prependEncoder) toJournaldPrefix(lvl zapcore.Level) string {
    switch lvl {
    case zapcore.DebugLevel:
        return "<7>"
    case zapcore.InfoLevel:
        return "<6>"
    case zapcore.WarnLevel:
        return "<4>"
    }
    return ""
}
package main

import (
    "go.uber.org/zap"
    "go.uber.org/zap/buffer"
    "go.uber.org/zap/zapcore"
    "os"
)

func getConfig() zap.Config {
    // your current config options
    return config
}

func main() {
    cfg := getConfig()

    // constructing our prependEncoder with a ConsoleEncoder using your original configs
    enc := &prependEncoder{
        Encoder: zapcore.NewConsoleEncoder(cfg.EncoderConfig),
        pool:    buffer.NewPool(),
    }

    logger := zap.New(
        zapcore.NewCore(
            enc,
            os.Stdout,
            zapcore.DebugLevel,
        ),
        // this mimics the behavior of NewProductionConfig.Build
        zap.ErrorOutput(os.Stderr), 
    )

    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
}
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
type prependEncoder struct {
    // embed a zapcore encoder
    // this makes prependEncoder implement the interface without extra work
    zapcore.Encoder

    // zap buffer pool
    pool buffer.Pool
}

// implementing only EncodeEntry
func (e *prependEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    // new log buffer
    buf := e.pool.Get()

    // prepend the JournalD prefix based on the entry level
    buf.AppendString(e.toJournaldPrefix(entry.Level))
    buf.AppendString(" ")

    // calling the embedded encoder's EncodeEntry to keep the original encoding format 
    consolebuf, err := e.Encoder.EncodeEntry(entry, fields)
    if err != nil {
        return nil, err
    }

    // just write the output into your own buffer
    _, err = buf.Write(consolebuf.Bytes())
    if err != nil {
        return nil, err
    }
    return buf, nil
}

// some mapper function
func (e *prependEncoder) toJournaldPrefix(lvl zapcore.Level) string {
    switch lvl {
    case zapcore.DebugLevel:
        return "<7>"
    case zapcore.InfoLevel:
        return "<6>"
    case zapcore.WarnLevel:
        return "<4>"
    }
    return ""
}
package main

import (
    "go.uber.org/zap"
    "go.uber.org/zap/buffer"
    "go.uber.org/zap/zapcore"
    "os"
)

func getConfig() zap.Config {
    // your current config options
    return config
}

func main() {
    cfg := getConfig()

    // constructing our prependEncoder with a ConsoleEncoder using your original configs
    enc := &prependEncoder{
        Encoder: zapcore.NewConsoleEncoder(cfg.EncoderConfig),
        pool:    buffer.NewPool(),
    }

    logger := zap.New(
        zapcore.NewCore(
            enc,
            os.Stdout,
            zapcore.DebugLevel,
        ),
        // this mimics the behavior of NewProductionConfig.Build
        zap.ErrorOutput(os.Stderr), 
    )

    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
}
<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn

How to properly capture zap logger output in unit tests

copy iconCopydownload iconDownload
func main() {
    // some arbitrary custom core logger
    mycore := zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        os.Stderr,
        zapcore.InfoLevel,
    )
    // test core
    observed, logs := observer.New(zapcore.InfoLevel)
    
    // new logger with the two cores tee'd together
    logger := zap.New(zapcore.NewTee(mycore, observed))

    logger.Error("foo")

    entry := logs.All()[0]
    fmt.Println(entry.Message == "foo")            // true
    fmt.Println(entry.Level == zapcore.ErrorLevel) // true
}
// this would be placed in your main code
func NewCustomLogger(pipeTo io.Writer) zapcore.Core {
    return zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        zap.CombineWriteSyncers(os.Stderr, zapcore.AddSync(pipeTo)),
        zapcore.InfoLevel,
    )
}

func TestLogger(t *testing.T) {
    b := &bytes.Buffer{}
    // call the constructor from your test code with the arbitrary writer
    mycore := NewCustomLogger(b)

    logger := zap.New(mycore)
    logger.Error("foo")

    fmt.Println(b.String()) // {"level":"error","ts":1639813360.853494,"msg":"foo"}
}
func main() {
    // some arbitrary custom core logger
    mycore := zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        os.Stderr,
        zapcore.InfoLevel,
    )
    // test core
    observed, logs := observer.New(zapcore.InfoLevel)
    
    // new logger with the two cores tee'd together
    logger := zap.New(zapcore.NewTee(mycore, observed))

    logger.Error("foo")

    entry := logs.All()[0]
    fmt.Println(entry.Message == "foo")            // true
    fmt.Println(entry.Level == zapcore.ErrorLevel) // true
}
// this would be placed in your main code
func NewCustomLogger(pipeTo io.Writer) zapcore.Core {
    return zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        zap.CombineWriteSyncers(os.Stderr, zapcore.AddSync(pipeTo)),
        zapcore.InfoLevel,
    )
}

func TestLogger(t *testing.T) {
    b := &bytes.Buffer{}
    // call the constructor from your test code with the arbitrary writer
    mycore := NewCustomLogger(b)

    logger := zap.New(mycore)
    logger.Error("foo")

    fmt.Println(b.String()) // {"level":"error","ts":1639813360.853494,"msg":"foo"}
}

How do I create the OpenAPI section for the 404 page?

copy iconCopydownload iconDownload
import yaml
from sys import argv
import re

order = ['openapi','paths','components']
level0re = re.compile('(?<=\n)[^ ][^:]+')

def _propfill(rootnode, nodes, value):
    if len(nodes) == 1:
        rootnode[nodes[0]] = value
    if len(nodes) > 1:
        nextnode = rootnode.get(nodes[0]) 
        if rootnode.get(nodes[0]) is None:
            nextnode = {}
            rootnode[nodes[0]] = nextnode
        _propfill(nextnode, nodes[1:], value)

def propfill(rootnode, nodepath, value):
    _propfill(rootnode, [n.replace('__slash__','/') for n in nodepath.replace('\/','__slash__').split('/')], value)

def yamlfill(filepath):
    with open(filepath, 'r') as file:
        yamltree = yaml.safe_load(file)
    #propfill(yamltree, 'components/schemas/notFoundResponse/...', '')
    propfill(yamltree, 'components/responses/notFound/description', 'Not found response')
    propfill(yamltree, 'components/responses/notFound/content/application\/json/schema/$ref', '#/components/schemas/notFoundResponse')
    responses = [mv['responses'] if 'responses' in mv else [] for pk,pv in (yamltree['paths'].items() if 'paths' in yamltree else []) for mk,mv in pv.items()]
    for response in responses:
        propfill(response, '404/$ref', '#/components/responses/notFound')
    yamlstring = yaml.dump(yamltree)
    offsets = [i[1] for i in sorted([(order.index(f.group(0)) if f.group(0) in order else len(order),f.start()-1) for f in [f for f in level0re.finditer('\n'+yamlstring)]])]
    offsets = [(offset,(sorted([o for o in offsets if o > offset]+[len(yamlstring)-1])[0])) for offset in offsets]
    with open(filepath[:-5]+'_404.yaml', 'w') as file:
        file.write(''.join(['\n'+yamlstring[o[0]:o[1]] for o in offsets]).strip())

yamlfill(argv[-1])

Mail service using AWS ses in GO

copy iconCopydownload iconDownload
<em>Copyright © {{ .Year }} Hive Wealth, All rights reserved.</em>


templateData := struct {
        Year int
    }{
        Year: time.Now().Year(),
    }
    // The HTML body for the email.
    newtemp, err := temp.ParseFiles(fmt.Sprintf("%s", "./schemas/html/"+template+".html"))
    if err != nil {
        Logger.Error("template failed", zap.Any("err", err))
    }
    buf := new(bytes.Buffer)
    if err = newtemp.Execute(buf, templateData); err != nil {
        Logger.Error("template failed", zap.Any("err", err))
    }
    htmlBody := buf.String()

Pattern for re not retriving any results

copy iconCopydownload iconDownload
r1 = re.findall(r'[a-zA-Z0-9~@#$^*()_+=[\]{}|\\,.?: -]{36}',t)
r1: ['var t = r(d[0])(r(d[1])), n = r(d[0]',
 ')(r(d[2])), o = r(d[0])(r(d[3])), c ',
 '= r(d[0])(r(d[4])), l = r(d[0])(r(d[',
 '2301ae56-3b9c-4653-963b-2ad84d06ba08',
 '                style: { height: 0.5',
 'a887526b-ff19-4409-91ff-e1679e418922',
 '                style: { height: t }']
r1 = re.findall(r'[a-zA-Z0-9\-]{36}',t)
r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
r1 = re.findall(r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}', t, re.IGNORECASE)

r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
t = """Object.defineProperty(e, '__esModule', { value: !0 }), e.default = void 0;
var t = r(d[0])(r(d[1])), n = r(d[0])(r(d[2])), o = r(d[0])(r(d[3])), c = r(d[0])(r(d[4])), l = r(d[0])(r(d[5])), u = function (t) {
        return [
            {
                contentId: '2301ae56-3b9c-4653-963b-2ad84d06ba08',
                prettyId: 'super',
                style: { height: 0.5 * t }
            },
            {
                contentId: 'a887526b-ff19-4409-91ff-e1679e418922',
                prettyId: 'zap',
                style: { height: t }
            }
        ];
    },"""
r1 = re.findall(r'[a-zA-Z0-9~@#$^*()_+=[\]{}|\\,.?: -]{36}',t)
r1: ['var t = r(d[0])(r(d[1])), n = r(d[0]',
 ')(r(d[2])), o = r(d[0])(r(d[3])), c ',
 '= r(d[0])(r(d[4])), l = r(d[0])(r(d[',
 '2301ae56-3b9c-4653-963b-2ad84d06ba08',
 '                style: { height: 0.5',
 'a887526b-ff19-4409-91ff-e1679e418922',
 '                style: { height: t }']
r1 = re.findall(r'[a-zA-Z0-9\-]{36}',t)
r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
r1 = re.findall(r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}', t, re.IGNORECASE)

r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
t = """Object.defineProperty(e, '__esModule', { value: !0 }), e.default = void 0;
var t = r(d[0])(r(d[1])), n = r(d[0])(r(d[2])), o = r(d[0])(r(d[3])), c = r(d[0])(r(d[4])), l = r(d[0])(r(d[5])), u = function (t) {
        return [
            {
                contentId: '2301ae56-3b9c-4653-963b-2ad84d06ba08',
                prettyId: 'super',
                style: { height: 0.5 * t }
            },
            {
                contentId: 'a887526b-ff19-4409-91ff-e1679e418922',
                prettyId: 'zap',
                style: { height: t }
            }
        ];
    },"""
r1 = re.findall(r'[a-zA-Z0-9~@#$^*()_+=[\]{}|\\,.?: -]{36}',t)
r1: ['var t = r(d[0])(r(d[1])), n = r(d[0]',
 ')(r(d[2])), o = r(d[0])(r(d[3])), c ',
 '= r(d[0])(r(d[4])), l = r(d[0])(r(d[',
 '2301ae56-3b9c-4653-963b-2ad84d06ba08',
 '                style: { height: 0.5',
 'a887526b-ff19-4409-91ff-e1679e418922',
 '                style: { height: t }']
r1 = re.findall(r'[a-zA-Z0-9\-]{36}',t)
r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
r1 = re.findall(r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}', t, re.IGNORECASE)

r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
t = """Object.defineProperty(e, '__esModule', { value: !0 }), e.default = void 0;
var t = r(d[0])(r(d[1])), n = r(d[0])(r(d[2])), o = r(d[0])(r(d[3])), c = r(d[0])(r(d[4])), l = r(d[0])(r(d[5])), u = function (t) {
        return [
            {
                contentId: '2301ae56-3b9c-4653-963b-2ad84d06ba08',
                prettyId: 'super',
                style: { height: 0.5 * t }
            },
            {
                contentId: 'a887526b-ff19-4409-91ff-e1679e418922',
                prettyId: 'zap',
                style: { height: t }
            }
        ];
    },"""
r1 = re.findall(r'[a-zA-Z0-9~@#$^*()_+=[\]{}|\\,.?: -]{36}',t)
r1: ['var t = r(d[0])(r(d[1])), n = r(d[0]',
 ')(r(d[2])), o = r(d[0])(r(d[3])), c ',
 '= r(d[0])(r(d[4])), l = r(d[0])(r(d[',
 '2301ae56-3b9c-4653-963b-2ad84d06ba08',
 '                style: { height: 0.5',
 'a887526b-ff19-4409-91ff-e1679e418922',
 '                style: { height: t }']
r1 = re.findall(r'[a-zA-Z0-9\-]{36}',t)
r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
r1 = re.findall(r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}', t, re.IGNORECASE)

r1: ['2301ae56-3b9c-4653-963b-2ad84d06ba08',
 'a887526b-ff19-4409-91ff-e1679e418922']
t = """Object.defineProperty(e, '__esModule', { value: !0 }), e.default = void 0;
var t = r(d[0])(r(d[1])), n = r(d[0])(r(d[2])), o = r(d[0])(r(d[3])), c = r(d[0])(r(d[4])), l = r(d[0])(r(d[5])), u = function (t) {
        return [
            {
                contentId: '2301ae56-3b9c-4653-963b-2ad84d06ba08',
                prettyId: 'super',
                style: { height: 0.5 * t }
            },
            {
                contentId: 'a887526b-ff19-4409-91ff-e1679e418922',
                prettyId: 'zap',
                style: { height: t }
            }
        ];
    },"""

What is the correspondence between go-logr and uber's zap verbosity levels?

copy iconCopydownload iconDownload
zapLevel = -1 * logrLevel
func (zl *zapLogger) V(level int) logr.Logger {
    return &zapLogger{
        lvl: zl.lvl - zapcore.Level(level),
        l:   zl.l,
    }
}
var levelStrings = map[string]zapcore.Level{
    "debug": zap.DebugLevel,
    "info":  zap.InfoLevel,
    "error": zap.ErrorLevel,
}
zapLevel = -1 * logrLevel
func (zl *zapLogger) V(level int) logr.Logger {
    return &zapLogger{
        lvl: zl.lvl - zapcore.Level(level),
        l:   zl.l,
    }
}
var levelStrings = map[string]zapcore.Level{
    "debug": zap.DebugLevel,
    "info":  zap.InfoLevel,
    "error": zap.ErrorLevel,
}
zapLevel = -1 * logrLevel
func (zl *zapLogger) V(level int) logr.Logger {
    return &zapLogger{
        lvl: zl.lvl - zapcore.Level(level),
        l:   zl.l,
    }
}
var levelStrings = map[string]zapcore.Level{
    "debug": zap.DebugLevel,
    "info":  zap.InfoLevel,
    "error": zap.ErrorLevel,
}

See all related Code Snippets

Community Discussions

Trending Discussions on zap
  • Is it possible to update the log level of a zap logger at runtime?
  • UDF executing multiple times with Structured References
  • How to access Fields in zap Hooks?
  • Why custom encoding is lost after calling logger.With in Uber Zap?
  • Uber Zap Logger: how to prepend every log entry with a string
  • How to properly capture zap logger output in unit tests
  • How do I create the OpenAPI section for the 404 page?
  • Mail service using AWS ses in GO
  • zap-api-scan.py: How to limit the time / recursion / depth?
  • Google Sign In with firebase on android keeps failing
Trending Discussions on zap

QUESTION

Is it possible to update the log level of a zap logger at runtime?

Asked 2022-Mar-17 at 18:11

I created a logger with kubebuilder, it is based on zap logger:

import (
    "flag"
    "github.com/gin-gonic/gin"
    "net/http"
    "os"
    "go.uber.org/zap/zapcore"
    uzap "go.uber.org/zap"
    // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
    // to ensure that exec-entrypoint and run can make use of them.
    _ "k8s.io/client-go/plugin/pkg/client/auth"

    "k8s.io/apimachinery/pkg/runtime"
    utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    ctrl "sigs.k8s.io/controller-runtime"
    "sigs.k8s.io/controller-runtime/pkg/healthz"
    "sigs.k8s.io/controller-runtime/pkg/log/zap"

)

var (
    scheme   = runtime.NewScheme()
    setupLog = ctrl.Log.WithName("setup")
)

var zapOpts []uzap.Option
    zapOpts = append(zapOpts, uzap.AddCaller())
    zapOpts = append(zapOpts, uzap.AddCallerSkip(1))
    zapOpts = append(zapOpts, uzap.AddStacktrace(uzap.DebugLevel))

    opts := zap.Options{
        Development:     developmentFlag,
        StacktraceLevel: stacktraceLevel,
        Level:           level,
        Encoder:         encoder,
        ZapOpts:  zapOpts,
    }

    opts.BindFlags(flag.CommandLine)
    flag.Parse()

    ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

Now I want to change the log level to zapcore.InfoLevel at run time. I didn't find any SetLogLevel or similar API.

Do I need to create new opts and then set the new level?

Also I need to set the logger with sigs.k8s.io/controller-runtime/pkg/log/zap library. The interface of the logger is from go-logr and it implements logr.Logger interface. If I tried to change it to zapcore.NewCore than I can't set the logger with ctrl.SetLogger anymore.

I want to keep the options to update all the options of zap.Options and also to change the log level, and still to use the zap from sigs.k8s.io/controller-runtime/pkg/log/zap.

Is it possible to do it with sigs.k8s.io/controller-runtime/pkg/log/zap and sigs.k8s.io/controller-runtime?

ANSWER

Answered 2022-Mar-17 at 18:11

Better answer: as suggested by @Oliver Dain, use zap.AtomicLevel. See their answer for details.

Another option is to create a core with a custom LevelEnabler function. You can use zap.LevelEnablerFunc to convert a closure to a zapcore.LevelEnabler.

The relevant docs:

LevelEnabler decides whether a given logging level is enabled when logging a message.

LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with an anonymous function.

That function may then return true or false based on some other variable that changes at runtime:

    // will be actually initialized and changed at run time 
    // based on your business logic
    var infoEnabled bool 

    errorUnlessEnabled := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
        // true: log message at this level
        // false: skip message at this level
        return level >= zapcore.ErrorLevel || infoEnabled
    })

    core := zapcore.NewCore(
        zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
        os.Stdout,
        errorUnlessEnabled,
    )
    logger := zap.New(core)

    logger.Info("foo") // not logged
    
    infoEnabled = true

    logger.Info("foo again") // logged

PS: this code is contrived. Your program will have to implement initialization, value change at run-time and proper synchronization (if needed) over the infoEnabled variable.

You can run this example in the playground: https://play.golang.org/p/oT3nvnP1Bwc

Source https://stackoverflow.com/questions/69738222

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install zap

Note that zap only supports the two most recent minor versions of Go.
In contexts where performance is nice, but not critical, use the SugaredLogger. It's 4-10x faster than other structured logging packages and includes both structured and printf-style APIs. When performance and type safety are critical, use the Logger. It's even faster than the SugaredLogger and allocates far less, but it only supports structured logging. See the documentation and FAQ for more details.

Support

We encourage and support an active, healthy community of contributors — including you! Details are in the contribution guide and the code of conduct. The zap maintainers keep an eye on issues and pull requests, but you can also report any negative conduct to oss-conduct@uber.com. That email list is a private, safe space; even the zap maintainers don't have access, so don't hesitate to hold us to a high standard. Released under the MIT License. 1 In particular, keep in mind that we may be benchmarking against slightly older versions of other packages. Versions are pinned in the benchmarks/go.mod file. ↩.

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases
Explore Kits

Save this library and start creating your kit

Explore Related Topics

Share this Page

share link
Reuse Pre-built Kits with zap
Consider Popular Go Libraries
Try Top Libraries by uber-go
Compare Go Libraries with Highest Support
Compare Go Libraries with Highest Quality
Compare Go Libraries with Highest Security
Compare Go Libraries with Permissive License
Compare Go Libraries with Highest Reuse
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases
Explore Kits

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.