{"id":20900565,"url":"https://github.com/dataphos/lib-logger","last_synced_at":"2026-05-20T00:06:12.476Z","repository":{"id":257809069,"uuid":"866547003","full_name":"dataphos/lib-logger","owner":"dataphos","description":"Common Logging Library","archived":false,"fork":false,"pushed_at":"2024-10-11T09:21:18.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-19T13:15:34.530Z","etag":null,"topics":["go","library","logging"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dataphos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-02T13:09:50.000Z","updated_at":"2024-10-11T14:44:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"04911879-92e1-467d-88d7-de580b93a49f","html_url":"https://github.com/dataphos/lib-logger","commit_stats":null,"previous_names":["dataphos/lib-logger"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dataphos%2Flib-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dataphos%2Flib-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dataphos%2Flib-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dataphos%2Flib-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dataphos","download_url":"https://codeload.github.com/dataphos/lib-logger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243286641,"owners_count":20267018,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","library","logging"],"created_at":"2024-11-18T11:20:45.188Z","updated_at":"2025-12-29T00:28:04.365Z","avatar_url":"https://github.com/dataphos.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lib-logger\n*Common Logging Library*\n\nThis repository contains the `Log` interface and `standardlogger` implementation\nthat logs to stdout.\n\n## Import package\n```golang\nimport (\n    \"github.com/dataphos/lib-logger/logger\"\n    \"github.com/dataphos/lib-logger/standardlogger\"\n)\n```\n\n## How To Use\n\n### Labels\nTo use the logger you first have to define Labels.\nLabels are a map-like object containing key-value string pairs sent with every log entry.\n\nLabels creation:\n```golang\n// only *strings* are allowed as keys and values\nlabels := logger.Labels{\"product\": \"Persistor\", \"clientId\": \"client0\", \"license\": \"enterprise\"}\n\n// logger.L is an alias of logger.Labels\n// this should be used in the Add method (see below)\nlabels := logger.L{\"product\": \"Persistor\", \"clientId\": \"client0\", \"license\": \"enterprise\"}\n```\nThis creates `\"product\"=\"Persistor\", \"clientId\"=\"client0\", \"license\"=\"enterprise\"` key-value pairs.\n\nLabels also allow you to add and delete keys:\n```golang\nlabels := logger.Labels{\"product\": \"Persistor\", \"clientId\": \"client0\", \"license\": \"enterprise\"}\nlabels.Del(\"clientId\", \"license\")\nlabels.Add(logger.L{\"product\": \"SchemaRegistry\", \"cluster\": \"C1\"}) // overrides product and adds cluster\n```\n\nWhen defining multiple loggers it is useful to have one master `Labels` object\nand many children that add additional information:\n```golang\nmainLabels := logger.Labels{\"product\": \"Persistor\", \"clientId\": \"client0\"}\n\n// subscriber component\n// create an independent copy of the mainLabels and add component=subscriber key-value pair\nsubscriberLabels := mainLabels.Clone()\nsubscriberLabels.Add(logger.L{\"component\": \"subscriber\"})\n\n// publisher component\n// chaining is allowed\npublisherLabels := mainLabels.Clone().Add(logger.L{\"component\": \"publisher\"})\n```\n**Note:** without a call to `Clone()`, child `Labels` is not independent of \nthe parent `Labels`, and calling `Add()` or `Del()` will modify the original `Labels`\ninstance.\n\n### How To Log\nCreate an instance of the `standardlogger` and pass `Labels` instance as \nthe parameter:\n```golang\nlog := standardlogger.New(labels)\n```\n\nTo log a message, use logging functions:\n```golang\n// ======================================\n// LOGGING FUNCTIONS WITHOUT EXTRA FIELDS\n// ======================================\nlog.Info(\"Info\")\nlog.Warn(\"Warning\")\n// Error, Fatal, Panic require error code\nlog.Error(\"Error\", 0)\nlog.Fatal(\"Error\", 0)\nlog.Panic(\"Panic\", 0)\n\n// ======================================\n// LOGGING FUNCTIONS WITH EXTRA FIELDS\n// SHORT SYNTAX\n// logger.F is an alias of logger.Fields\n// ======================================\nlog.Infow(\"Info\", logger.F{\"userId\": 55, \"objId\": 64})\nlog.Warnw(\"Warn\", logger.F{\"objId\": 43})\nlog.Errorw(\"Error\", 0, logger.F{\"objId\": 43})\nlog.Fatalw(\"Fatal\", 0, logger.F{\"userId\": 55})\nlog.Panicw(\"Panic\", 0, logger.F{\"reqId\": 22})\n```\n\n### How To Pass a `log` Object\nTo pass a `log`, use the `logger.Log` interface:\n```golang\nfunc giveMeTheLog(log logger.Log) {\n    log.Info(\"Log passed\")\n}\n```\n\n### How To Log Panics\nTo properly log panics, make a deferred call to `log.PanicLogger()` at the\nbeginning of every goroutine. Possible deferred recovery function should be \ndeferred **before** the PanicLogger. \n\nThe main goroutine begins at `func main()` so\nthat is where you should make a deferred call to `log.PanicLogger()`.\n```golang\nfunc main() {\n    defer func() {\n        if r:=recover(); r!=nil {\n            // recover panicking goroutine\t\n        }\t\n    }()\n    labels := logger.Labels{\"product\": \"Persistor\"}\n    log := standardlogger.New(labels)\t\n    defer log.PanicLogger()\n    \n    // panic can be called directly\n    panic(\"PANIC!\")\n    \n    // it can also be called with the log.Panicw method.\n    // this allows you to set error code and \n    // additional information\n    log.Panicw(\"Panic\", 1000, logger.F{\"reqId\": 22})\n    \n    // goroutine\n    go func() {\n        routineLabels := labels.Clone().\n            Add(logger.L{\"component\": \"routine\", \"remove\": \"me\", \"and\": \"me\"}).\n            Del(\"remove\", \"and\")\n        \n        routineLog := standardlogger.New(routineLabels)\n        defer routineLog.PanicLogger()\n        \n        // code...\n    }()\n}\n```\n### How To Log With Log Level\n\nCreate an instance of the `standardlogger`, pass `Lables` instance and to set desired log level use `WithLogLevel(level)` \nYou can set level to `logger.LevelInfo`, `logger.LevelWarn`, `logger.LevelError`, `logger.LevelPanic` and `logger.LevelFatal`. Logs of a lower level won't be printed to stdout.\nHere is an example of how to do this:\n\n```golang\nlogger := standardlogger.New(labels, standardlogger.WithLogLevel(logger.LevelInfo))\n```\nYou can log a message using logging functions as shown before.\n\n# Testing\nStandard logger has a `NewForTesting` constructor that keeps logged records in memory:\n```golang\nlog, logs := NewForTesting(logger.Labels{\"product\": \"Persistor\"})\n```\nwhere `log` is an instance of the `standardlogger` and `logs` is an instance of \n[zaptest observer](go.uber.org/zap/zaptest/observer)'s `ObservedLogs`.\n\n`ObservedLogs` holds all logged records as a list of `LoggedEntry` instances.\nThey in turn hold the underlying `Entry` and the `Context`:\n```golang\ntype LoggedEntry struct {\n    zapcore.Entry\n    Context []zapcore.Field\n}\n```\nImportant fields in the `zapcore.Entry` are `Message` and `Level`.\n\nThe following example shows basic usage of the `NewForTesting` in a unit test:\n```golang\nfunc TestNewForTesting(t *testing.T) {\n    log, logs := NewForTesting(logger.Labels{})\n    log.Info(\"Info\")\n\n    expectedMsg := \"Info\"\n    entry := logs.All()[0]\n    if entry.Message != expectedMsg {\n        t.Errorf(\"Wrong message, want %s.\", expectedMsg)\n    }\n}\n```\n\nThis example demonstrates how to test when logging with extra fields:\n```golang\nfunc TestNewForTesting_WithLabelsOnWarn(t *testing.T) {\n    log, logs := NewForTesting(\n        logger.Labels{\n            \"product\": \"Persistor\",\n            \"license\": \"enterprise\",\n        })\n    log.Warn(\"Warn\")\n\n    expectedFields := []zap.Field{\n        zap.String(\"product\", \"Persistor\"),\n        zap.String(\"license\", \"enterprise\"),\n    }\n    expectedMsg := \"Warn\"\n\n    entry := logs.All()[0]\n\n    if entry.Message != expectedMsg {\n        t.Errorf(\"Wrong message, want %s.\", expectedMsg)\n    }\n\n    for _, field := range expectedFields {\n        found := false\n        for _, v := range entry.Context {\n            if field.Equals(v) {\n                found = true\n                break\n            }\n        }\n\n        if !found {\n            t.Errorf(\"Field not found, want %v.\", field)\n        }\n    }\n}\n```\n\nMore examples can be found in `standardlogger/standardlogger_test.go`.\n\n## Full Example\nFull working example can be found at `example/main.go`\n\n## Important\nStandard logger is a thin wrapper around Uber `zap` logging library: https://github.com/uber-go/zap.\n\n### Sampling\nSampling is **enabled** to protect from a flood of errors.\nLogs are **dropped intentionally** by zap when sampling is enabled. \nSampling will cause **repeated logs within a second** to be sampled. \nRead more at: https://github.com/uber-go/zap/blob/master/FAQ.md#why-are-some-of-my-logs-missing\n\n## Creating a New Logger\nTo create a new logger, implement the `Log` interface that can be\nfound in the `logger` package.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdataphos%2Flib-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdataphos%2Flib-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdataphos%2Flib-logger/lists"}