{"id":15563114,"url":"https://github.com/dsoprea/go-logging","last_synced_at":"2026-03-04T01:15:08.522Z","repository":{"id":57481960,"uuid":"69721906","full_name":"dsoprea/go-logging","owner":"dsoprea","description":"Useful and awesome logging system for Go with prefixing and stacktraces.","archived":false,"fork":false,"pushed_at":"2021-05-14T06:25:45.000Z","size":64,"stargazers_count":5,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-11T08:59:07.982Z","etag":null,"topics":["go","golang","logging"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dsoprea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-01T05:49:57.000Z","updated_at":"2024-04-26T18:02:59.000Z","dependencies_parsed_at":"2022-09-02T06:10:44.949Z","dependency_job_id":null,"html_url":"https://github.com/dsoprea/go-logging","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dsoprea/go-logging","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-logging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-logging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-logging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-logging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsoprea","download_url":"https://codeload.github.com/dsoprea/go-logging/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsoprea%2Fgo-logging/sbom","scorecard":{"id":357958,"data":{"date":"2025-08-11","repo":{"name":"github.com/dsoprea/go-logging","commit":"b02d349568dd9287e2bc3588023328bda4495632"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"13 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0236 / GHSA-h86h-8ppg-mxmh","Warn: Project is vulnerable to: GO-2021-0238 / GHSA-83g2-8m93-v3w7","Warn: Project is vulnerable to: GO-2022-0288","Warn: Project is vulnerable to: GO-2022-0969 / GHSA-69cg-p879-7622","Warn: Project is vulnerable to: GO-2022-1144 / GHSA-xrjj-mj9h-534m","Warn: Project is vulnerable to: GO-2023-1571 / GHSA-vvpx-j8f3-3w6h","Warn: Project is vulnerable to: GO-2023-1988 / GHSA-2wrh-6pvc-2jm9","Warn: Project is vulnerable to: GO-2023-2102 / GHSA-4374-p667-p6c8","Warn: Project is vulnerable to: GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T10:05:24.912Z","repository_id":57481960,"created_at":"2025-08-18T10:05:24.912Z","updated_at":"2025-08-18T10:05:24.912Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30067967,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T01:03:42.280Z","status":"ssl_error","status_checked_at":"2026-03-04T01:03:23.410Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","golang","logging"],"created_at":"2024-10-02T16:18:31.877Z","updated_at":"2026-03-04T01:15:08.499Z","avatar_url":"https://github.com/dsoprea.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/dsoprea/go-logging.svg?branch=master)](https://travis-ci.org/dsoprea/go-logging)\n[![Coverage Status](https://coveralls.io/repos/github/dsoprea/go-logging/badge.svg?branch=master)](https://coveralls.io/github/dsoprea/go-logging?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/dsoprea/go-logging/v2)](https://goreportcard.com/report/github.com/dsoprea/go-logging/v2)\n[![GoDoc](https://godoc.org/github.com/dsoprea/go-logging/v2?status.svg)](https://godoc.org/github.com/dsoprea/go-logging/v2)\n\n## Introduction\n\nThis project bridges several gaps that are present in the standard logging support in Go:\n\n- Equips errors with stacktraces and provides a facility for printing them\n- Inherently supports the ability for each Go file to print its messages with a prefix representing that file/package\n- Adds some functions to specifically log messages of different levels (e.g. debug, error)\n- Adds a `PanicIf()` function that can be used to conditionally manage errors depending on whether an error variable is `nil` or actually has an error\n- Adds support for pluggable logging adapters (so the output can be sent somewhere other than the console)\n- Adds configuration (such as the logging level or adapter) that can be driven from the environment\n- Supports filtering to show/hide the logging of certain places of the application\n- The loggers can be definded at the package level, so you can determine which Go file any log message came from.\n\nWhen used with the Panic-Defer-Recover pattern in Go, even panics rising from the Go runtime will be caught and wrapped with a stacktrace. This compartmentalizes which function they could have originated from, which is, otherwise, potentially non-trivial to figure out.\n\n## AppEngine\n\nGo under AppEngine is very stripped down, such as there being no logging type (e.g. `Logger` in native Go) and there is no support for prefixing. As each logging call from this project takes a `Context`, this works cooperatively to bridge the additional gaps in AppEngine's logging support.\n\nWith standard console logging outside of this context, that parameter will take a`nil`.\n\n\n## Getting Started\n\nThe simplest, possible example:\n\n```go\npackage thispackage\n\nimport (\n    \"context\"\n    \"errors\"\n\n    \"github.com/dsoprea/go-logging/v2\"\n)\n\nvar (\n    thisfileLog = log.NewLogger(\"thispackage.thisfile\")\n)\n\nfunc a_cry_for_help(ctx context.Context) {\n    err := errors.New(\"a big error\")\n    thisfileLog.Errorf(ctx, err, \"How big is my problem: %s\", \"pretty big\")\n}\n\nfunc init() {\n    cla := log.NewConsoleLogAdapter()\n    log.AddAdapter(\"console\", cla)\n}\n```\n\nNotice two things:\n\n1. We register the \"console\" adapter at the bottom. The first adapter registered will be used by default.\n2. We pass-in a prefix (what we refer to as a \"noun\") to `log.NewLogger()`. This is a simple, descriptive name that represents the subject of the file. By convention, we construct this by dot-separating the current package and the name of the file. We recommend that you define a different log for every file at the package level, but it is your choice whether you want to do this or share the same logger over the entire package, define one in each struct, etc..\n\n\n### Example Output\n\nExample output from a real application (not from the above):\n\n```\n2016/09/09 12:57:44 DEBUG: user: User revisiting: [test@example.com]\n2016/09/09 12:57:44 DEBUG: context: Session already inited: [DCRBDGRY6RMWANCSJXVLD7GULDH4NZEB6SBAQ3KSFIGA2LP45IIQ]\n2016/09/09 12:57:44 DEBUG: session_data: Session save not necessary: [DCRBDGRY6RMWANCSJXVLD7GULDH4NZEB6SBAQ3KSFIGA2LP45IIQ]\n2016/09/09 12:57:44 DEBUG: context: Got session: [DCRBDGRY6RMWANCSJXVLD7GULDH4NZEB6SBAQ3KSFIGA2LP45IIQ]\n2016/09/09 12:57:44 DEBUG: session_data: Found user in session.\n2016/09/09 12:57:44 DEBUG: cache: Cache miss: [geo.geocode.reverse:dhxp15x]\n```\n\n\n## Adapters\n\nThis project provides one built-in logging adapter, \"console\", which prints to the screen. To register it:\n\n```go\ncla := log.NewConsoleLogAdapter()\nlog.AddAdapter(\"console\", cla)\n```\n\n### Custom Adapters\n\nIf you would like to implement your own logger, just create a struct type that satisfies the LogAdapter interface.\n\n```go\ntype LogAdapter interface {\n    Debugf(lc *LogContext, message *string) error\n    Infof(lc *LogContext, message *string) error\n    Warningf(lc *LogContext, message *string) error\n    Errorf(lc *LogContext, message *string) error\n}\n```\n\nThe *LogContext* struct passed in provides additional information that you may need in order to do what you need to do:\n\n```go\ntype LogContext struct {\n    Logger *Logger\n    Ctx context.Context\n}\n```\n\n`Logger` represents your Logger instance.\n\nAdapter example:\n\n```go\ntype DummyLogAdapter struct {\n\n}\n\nfunc (dla *DummyLogAdapter) Debugf(lc *LogContext, message *string) error {\n\n}\n\nfunc (dla *DummyLogAdapter) Infof(lc *LogContext, message *string) error {\n\n}\n\nfunc (dla *DummyLogAdapter) Warningf(lc *LogContext, message *string) error {\n\n}\n\nfunc (dla *DummyLogAdapter) Errorf(lc *LogContext, message *string) error {\n\n}\n```\n\nThen, register it:\n\n```go\nfunc init() {\n    log.AddAdapter(\"dummy\", new(DummyLogAdapter))\n}\n```\n\nIf this is a task-specific implementation, just register it from the `init()` of the file that defines it.\n\nIf this is the first adapter you've registered, it will be the default one used. Otherwise, you'll have to deliberately specify it when you are creating a logger: Instead of calling `log.NewLogger(noun string)`, call `log.NewLoggerWithAdapterName(noun string, adapterName string)`.\n\nWe discuss how to configure the adapter from configuration in the \"Configuration\" section below.\n\n\n### Adapter Notes\n\n- The `Logger` instance exports `Noun()` in the event you want to discriminate where your log entries go in your adapter. It also exports `Adapter()` for if you need to access the adapter instance from your application.\n- If no adapter is registered (specifically, the default adapter-name remains empty), logging calls will be a no-op. This allows libraries to implement *go-logging* where the larger application doesn't.\n\n\n## Filters\n\nWe support the ability to exclusively log for a specific set of nouns (we'll exclude any not specified):\n\n```go\nlog.AddIncludeFilter(\"nountoshow1\")\nlog.AddIncludeFilter(\"nountoshow2\")\n```\n\nDepending on your needs, you might just want to exclude a couple and include the rest:\n\n```go\nlog.AddExcludeFilter(\"nountohide1\")\nlog.AddExcludeFilter(\"nountohide2\")\n```\n\nWe'll first hit the include-filters. If it's in there, we'll forward the log item to the adapter. If not, and there is at least one include filter in the list, we won't do anything. If the list of include filters is empty but the noun appears in the exclude list, we won't do anything.\n\nIt is a good convention to exclude the nouns of any library you are writing whose logging you do not want to generally be aware of unless you are debugging. You might call `AddExcludeFilter()` from the `init()` function at the bottom of those files unless there is some configuration variable, such as \"(LibraryNameHere)DoShowLogging\", that has been defined and set to TRUE.\n\n\n## Configuration\n\nThe following configuration items are available:\n\n- *Format*: The default format used to build the message that gets sent to the adapter. It is assumed that the adapter already prefixes the message with time and log-level (since the default AppEngine logger does). The default value is: `{{.Noun}}: [{{.Level}}] {{if eq .ExcludeBypass true}} [BYPASS]{{end}} {{.Message}}`. The available tokens are \"Level\", \"Noun\", \"ExcludeBypass\", and \"Message\".\n- *DefaultAdapterName*: The default name of the adapter to use when NewLogger() is called (if this isn't defined then the name of the first registered adapter will be used).\n- *LevelName*: The priority-level of messages permitted to be logged (all others will be discarded). By default, it is \"info\". Other levels are: \"debug\", \"warning\", \"error\", \"critical\"\n- *IncludeNouns*: Comma-separated list of nouns to log for. All others will be ignored.\n- *ExcludeNouns*: Comma-separated list on nouns to exclude from logging.\n- *ExcludeBypassLevelName*: The log-level at which we will show logging for nouns that have been excluded. Allows you to hide excessive, unimportant logging for nouns but to still see their warnings, errors, etc...\n\n\n### Configuration Providers\n\nYou provide the configuration by setting a configuration-provider. Configuration providers must satisfy the `ConfigurationProvider` interface. The following are provided with the project:\n\n- `EnvironmentConfigurationProvider`: Read values from the environment.\n- `StaticConfigurationProvider`: Set values directly on the struct.\n\n**The configuration provider must be applied before doing any logging (otherwise it will have no effect).**\n\nEnvironments such as AppEngine work best with `EnvironmentConfigurationProvider` as this is generally how configuration is exposed *by* AppEngine *to* the application. You can define this configuration directly in *that* configuration.\n\nBy default, no configuration-provider is applied, the level is defaulted to INFO and the format is defaulted to \"{{.Noun}}:{{if eq .ExcludeBypass true}} [BYPASS]{{end}} {{.Message}}\".\n\nAgain, if a configuration-provider does not provide a log-level or format, they will be defaulted (or left alone, if already set). If it does not provide an adapter-name, the adapter-name of the first registered adapter will be used.\n\nUsage instructions of both follow.\n\n\n### Environment-Based Configuration\n\n```go\necp := log.NewEnvironmentConfigurationProvider()\nlog.LoadConfiguration(ecp)\n```\n\nEach of the items listed at the top of the \"Configuration\" section can be specified in the environment using a prefix of \"Log\" (e.g. LogDefaultAdapterName).\n\n\n### Static Configuration\n\n```go\nscp := log.NewStaticConfigurationProvider()\nscp.SetLevelName(log.LevelNameWarning)\n\nlog.LoadConfiguration(scp)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsoprea%2Fgo-logging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsoprea%2Fgo-logging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsoprea%2Fgo-logging/lists"}