{"id":34585145,"url":"https://github.com/planetscale/log","last_synced_at":"2026-05-25T18:33:09.339Z","repository":{"id":37069542,"uuid":"422389953","full_name":"planetscale/log","owner":"planetscale","description":"🪵 📓 PlanetScale's opinionated structured logging library","archived":false,"fork":false,"pushed_at":"2023-08-18T23:00:40.000Z","size":63,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-04-24T05:42:25.894Z","etag":null,"topics":[],"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/planetscale.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":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2021-10-29T00:04:50.000Z","updated_at":"2023-09-14T08:50:30.000Z","dependencies_parsed_at":"2023-02-17T01:01:04.606Z","dependency_job_id":null,"html_url":"https://github.com/planetscale/log","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/planetscale/log","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetscale%2Flog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetscale%2Flog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetscale%2Flog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetscale%2Flog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/planetscale","download_url":"https://codeload.github.com/planetscale/log/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetscale%2Flog/sbom","scorecard":{"id":736953,"data":{"date":"2025-08-11","repo":{"name":"github.com/planetscale/log","commit":"324540f3f1cf9df426eed026fc3178376077067c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"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":"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":"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":"Code-Review","score":10,"reason":"all changesets reviewed","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":"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":"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":"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: Apache License 2.0: 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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"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-22T16:09:32.899Z","repository_id":37069542,"created_at":"2025-08-22T16:09:32.899Z","updated_at":"2025-08-22T16:09:32.899Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33488916,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-25T14:31:05.219Z","status":"ssl_error","status_checked_at":"2026-05-25T14:31:02.878Z","response_time":57,"last_error":"SSL_read: 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":[],"created_at":"2025-12-24T10:29:45.108Z","updated_at":"2026-05-25T18:33:09.330Z","avatar_url":"https://github.com/planetscale.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# log 🪵\n\nPlanetScale's logger module. Implemented as a set of convenience functions providing a common configuration of the [zap](https://github.com/uber-go/zap) logging library.  `zap` *\"provides fast, structured, leveled logging.\"*\n\nLogs emitted follow the standards from [PlanetScale Structure Logging (coda)](https://coda.io/d/Text-Book_dqagsnmBFI6/Structured-Logging_suS7P#_luvPS).\n\n## Usage\n\n```console\ngo get github.com/planetscale/log\n```\n\n`zap` provides two logging interfaces: `zap.Logger` and `zap.SugarLogger`. Zap describes each logger and how to choose between them:\n\n\u003e In contexts where performance is nice, but not critical, use the `zap.SugaredLogger`. It's 4-10x faster than other structured logging packages and supports both structured and printf-style logging. Like log15 and go-kit, the SugaredLogger's structured logging APIs are loosely typed and accept a variadic number of key-value pairs. (For more advanced use cases, they also accept strongly typed fields - see the [SugaredLogger.With](https://pkg.go.dev/go.uber.org/zap@v1.19.1#SugaredLogger.With) documentation for details.\n\n\u003e In the rare contexts where every microsecond and every allocation matter, use the `zap.Logger`. It's even faster than the SugaredLogger and allocates far less, but it only supports strongly-typed, structured logging.\n\n### Examples:\n\n**zap.Logger**:\n\n```go\nimport \"github.com/planetscale/log\"\n\nfunc main() {\n  logger := log.New()\n  defer logger.Sync()\n\n  logger.Info(\"info log with fields\",\n    // Structured context as typed key-value pairs\n    log.String(\"user_id\", \"12345678\"),\n    log.String(\"branch_id\", \"xzyhnkhpi12\"),\n  )\n}\n```\n\n**zap.SugarLogger**:\n\n```go\nimport \"github.com/planetscale/log\"\n\nfunc main() {\n  logger := log.NewPlanetScaleSugarLogger()\n  defer logger.Sync()\n\n  logger.Infof(\"info log printf example: %v\", \"foo\")\n\n  logger.Infow(\"info log with fields\",\n    // Structured context as loosely typed key-value pairs.\n    \"user_id\", \"12345678\",\n    \"branch_id\", \"xzyhnkhpi12\",\n  )\n}\n```\n\nAdditional customizations to the logger config may be obtained by calling the `NewPlanetScaleConfig()` function to return a pre-configured `zap.Config` which can be further customized before calling `.Build()` to create a `zap.Logger`. Example:\n\n```go\n  // disable the `caller` field in logs:\n  cfg := log.NewPlanetScaleConfig()\n  logger, _ := cfg.Build(zap.WithCaller(false))\n  defer logger.Sync()\n```\n\nSee [./examples](./examples).\n\n### glog\n\nMany PlanetScale applications use the [github.com/golang/glog](https://github.com/golang/glog) library which is commonly used in Vitess and Kuberenetes client libraries. Glog has some interesting properties, namely that it hooks into `flags` for configuration and causes libraries that use it to output their own logs, regardless of the application's logging config. When combined with this library you will end up with an application that is mixing structured JSON logs from `zap` with plain-text logs from `glog`.\n\nUsing [noglog](https://github.com/planetscale/noglog) the `glog` library's log calls can be replaced with our logger such that all logs emitted by the application are in a common, structured, JSON format.\n\n1. Add the following to your `go.mod`:\n\n```golang\nrequire (\n    github.com/google/glog master\n)\n\nreplace github.com/google/glog =\u003e github.com/planetscale/noglog master\n```\n\n2. Replace `glog's` log calls with our SugaredLogger:\n\n```golang\n  logger := log.NewPlanetScaleSugarLogger()\n  defer logger.Sync()\n\n  glog.SetLogger(\u0026glog.LoggerFunc{\n    DebugfFunc: func(f string, a ...interface{}) { logger.Debugf(f, a...) },\n    InfofFunc:  func(f string, a ...interface{}) { logger.Infof(f, a...) },\n    WarnfFunc:  func(f string, a ...interface{}) { logger.Warnf(f, a...) },\n    ErrorfFunc: func(f string, a ...interface{}) { logger.Errorf(f, a...) },\n  })\n```\n\nIf using the `zap.Logger` call `.Sugar()` to get a SugaredLogger first:\n\n```golang\n  logger := log.New()\n  defer logger.Sync()\n\n  slogger := logger.Sugar()\n  glog.SetLogger(\u0026glog.LoggerFunc{\n    DebugfFunc: func(f string, a ...interface{}) { slogger.Debugf(f, a...) },\n    InfofFunc:  func(f string, a ...interface{}) { slogger.Infof(f, a...) },\n    WarnfFunc:  func(f string, a ...interface{}) { slogger.Warnf(f, a...) },\n    ErrorfFunc: func(f string, a ...interface{}) { slogger.Errorf(f, a...) },\n  })\n\n```\n\n## Adapters\n\nAdapters are available for the following libraries:\n\n### github.com/slack-go/go\n\nUse `NewSlackGoAdapter()` to wrap a `*zap.Logger` that can be used with the github.com/slack-go/slack package:\n\n```go\nlogger := log.NewPlanetScaleLogger()\ndefer logger.Sync()\n\nwrappedLogger := log.NewSlackGoAdapter(logger)\n\nclient := slack.New(\n  token,\n  slack.OptionAppLevelToken(appToken),\n  slack.OptionLog(wrappedLogger),\n)\n\nsocketClient := socketmode.New(\n  client,\n  socketmode.OptionLog(wrappedLogger),\n)\n```\n\n### github.com/temporalio/sdk-go\n\nUse `NewTemporalAdapter()` to wrap a `*zap.Logger` that can be used with the github.com/temporalio/sdk-go package:\n\n```go\nlogger := log.NewPlanetScaleLogger()\ndefer logger.Sync()\n\ntemporalLogger := log.NewTemporalAdapter(logger)\n\ntClient, err := client.NewClient(client.Options{\n  HostPort: fmt.Sprintf(\"%s:%d\", host, port),\n  Logger: temporalLogger,\n})\n\n// or client.Dial():\ntClient, err := client.Dial(client.Options{\n  HostPort: fmt.Sprintf(\"%s:%d\", host, port),\n  Logger: temporalLogger,\n})\n```\n\n## Development mode\n\nAll logs are emitted as JSON by default. Sometimes this can be difficult to read. Set the `PS_DEV_MODE=1` environment variable to switch into a more human friendly log format.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetscale%2Flog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplanetscale%2Flog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetscale%2Flog/lists"}