Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7ed74c1
Bring back doFmtVerbLevelColor on Windows
Dec 5, 2015
02b8aca
Fix concurrent data race problem
hilyjiang Dec 7, 2015
2da2aba
Merge pull request #3 from keybase/zanderz/colors_2015.12.04
Dec 7, 2015
d7b8c00
go fmt
Dec 9, 2015
6aa56dd
Merge https://github.com/op/go-logging
taruti Mar 8, 2016
44edaaa
Merge https://github.com/hilyjiang/go-logging
taruti Mar 8, 2016
fd7c815
Merge pull request #5 from keybase/taruti/update-upstream+hilyjiang-repo
taruti Mar 9, 2016
75a0c5e
Fixes missing Criticalf method
gabriel Mar 23, 2016
3ef87c1
Merge pull request #6 from keybase/fixinterface
gabriel Mar 23, 2016
33b7001
Revert "Fixes missing Criticalf method"
gabriel Mar 23, 2016
f3c7c3c
Merge pull request #7 from keybase/revert-6-fixinterface
gabriel Mar 23, 2016
05fd699
fix lint
joshblum Apr 22, 2020
ce9d896
cleanup, rw mutex
joshblum Apr 22, 2020
2c2af16
fix existing broken test
joshblum Apr 22, 2020
ae4bcca
trigger ci
joshblum Apr 22, 2020
0955434
drop go 1.11/1.12
joshblum Apr 22, 2020
7a5ab2e
Merge pull request #9 from keybase/joshblum/locks-HOTPOT-2409
joshblum Apr 23, 2020
58d00cf
move to go modules
marceloneil Apr 29, 2020
153efd7
Merge pull request #10 from marceloneil/marcel/HOTPOT-2576-go-modules
joshblum Nov 9, 2021
854d991
test against supported go versions
joshblum Nov 9, 2021
91d0bb1
kick ci
joshblum Nov 18, 2021
35a15a9
Merge pull request #11 from keybase/joshblum/go1.17
joshblum Nov 18, 2021
aa4058b
test against the latest versions of go
joshblum Oct 7, 2022
c617c0c
go fmt ./...
joshblum Oct 7, 2022
3c57f4b
no ioutil
joshblum Oct 7, 2022
56ff13d
Merge pull request #12 from keybase/joshblum/upgrade-go
joshblum Oct 7, 2022
684745a
migrate to github actions
joshblum Dec 20, 2022
396ca57
Merge pull request #13 from keybase/joshblum/github-actions
joshblum Dec 20, 2022
6019b28
Test against the latest versions of Go
joshblum Dec 13, 2023
4b3ff33
Merge pull request #14 from keybase/joshblum/upgrade-go
joshblum Dec 13, 2023
c0ab005
Upgrade to go 1.23
joshblum Jan 6, 2025
8771804
Merge pull request #15 from keybase/joshblum/go-1.23-upgrade
joshblum Jan 6, 2025
eaed5e0
go1.25
zoom-ua Dec 11, 2025
af512d0
x
zoom-ua Dec 11, 2025
3e12278
x
zoom-ua Dec 11, 2025
c9200e4
x
zoom-ua Dec 11, 2025
ca8e152
Merge pull request #16 from keybase/joshblum/go1.25
zoom-ua Dec 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master
schedule:
# Run daily at 2 AM UTC to check for new vulnerabilities
- cron: "0 2 * * *"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
timeout-minutes: 15
strategy:
matrix:
go-version: [1.25.x, 1.24.x, 1.23.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false

- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}
cache: true

- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.7.2

- name: Build
run: go build -v ./...

- name: Run govulncheck
uses: golang/govulncheck-action@v1
with:
go-version-input: ${{ matrix.go-version }}

- name: Test
run: go test -race ./...
66 changes: 66 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
version: "2"

run:
timeout: 5m
tests: true

formatters:
enable:
- gofumpt

linters:
enable:
# Core recommended linters
- errcheck # Checks for unchecked errors
- govet # Go vet checks
- ineffassign # Detects ineffectual assignments
- staticcheck # Advanced static analysis
- unused # Finds unused code

# Code quality
- misspell # Finds commonly misspelled words
- unconvert # Unnecessary type conversions (already enabled in original)
- unparam # Finds unused function parameters
- gocritic # Various checks (already enabled in original)
- revive # Fast, configurable linter (already enabled in original)

# Security and best practices
- gosec # Security-focused linter
- bodyclose # Checks HTTP response body closed
- noctx # Finds HTTP requests without context

settings:
gocritic:
disabled-checks:
- ifElseChain
- elseif

govet:
enable-all: true
disable:
- shadow
- fieldalignment

revive:
enable-all-rules: false

exclusions:
rules:
# Exclude specific revive rules
- linters:
- revive
text: "package-comments"

- linters:
- revive
text: "exported"

# Exclude specific staticcheck rules
- linters:
- staticcheck
text: "ST1005"

# Exclude specific gocritic rules
- linters:
- gocritic
text: "ifElseChain"
6 changes: 0 additions & 6 deletions .travis.yml

This file was deleted.

9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Golang logging library

[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/op/go-logging) [![build](https://img.shields.io/travis/op/go-logging.svg?style=flat)](https://travis-ci.org/op/go-logging)
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/op/go-logging)
[![Build Status](https://github.com/keybase/go-logging/actions/workflows/ci.yml/badge.svg)](https://github.com/keybase/go-logging/actions)

Package logging implements a logging infrastructure for Go. Its output format
is customizable and supports different logging backends like syslog, file and
Expand Down Expand Up @@ -72,11 +73,11 @@ func main() {

## Installing

### Using *go get*
### Using _go get_

$ go get github.com/op/go-logging

After this command *go-logging* is ready to use. Its source will be in:
After this command _go-logging_ is ready to use. Its source will be in:

$GOPATH/src/pkg/github.com/op/go-logging

Expand All @@ -90,4 +91,4 @@ For docs, see http://godoc.org/github.com/op/go-logging or run:

## Additional resources

* [wslog](https://godoc.org/github.com/cryptix/go/logging/wslog) -- exposes log messages through a WebSocket.
- [wslog](https://godoc.org/github.com/cryptix/go/logging/wslog) -- exposes log messages through a WebSocket.
11 changes: 10 additions & 1 deletion backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@

package logging

import (
"sync"
)

// defaultBackend is the backend used for all logging calls.
var defaultBackend LeveledBackend
var (
defaultBackend LeveledBackend
defaultBackendMutex sync.RWMutex
)

// Backend is the interface which a log backend need to implement to be able to
// be used as a logging backend.
Expand All @@ -23,6 +30,8 @@ func SetBackend(backends ...Backend) LeveledBackend {
backend = MultiLogger(backends...)
}

defaultBackendMutex.Lock()
defer defaultBackendMutex.Unlock()
defaultBackend = AddModuleLevel(backend)
return defaultBackend
}
Expand Down
4 changes: 2 additions & 2 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ func Example() {
// This call is for testing purposes and will set the time to unix epoch.
InitForTesting(DEBUG)

var log = MustGetLogger("example")
log := MustGetLogger("example")

// For demo purposes, create two backend for os.Stdout.
//
Expand All @@ -18,7 +18,7 @@ func Example() {
// For messages written to backend2 we want to add some additional
// information to the output, including the used log level and the name of
// the function.
var format = MustStringFormatter(
format := MustStringFormatter(
`%{time:15:04:05.000} %{shortfunc} %{level:.1s} %{message}`,
)
backend2Formatter := NewBackendFormatter(backend2, format)
Expand Down
5 changes: 3 additions & 2 deletions examples/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"os"

"github.com/op/go-logging"
"github.com/keybase/go-logging"
)

var log = logging.MustGetLogger("example")
Expand All @@ -27,7 +27,8 @@ func main() {
// For demo purposes, create two backend for os.Stderr.
backend1 := logging.NewLogBackend(os.Stderr, "", 0)
backend2 := logging.NewLogBackend(os.Stderr, "", 0)

backend1.Color = true
backend2.Color = true
// For messages written to backend2 we want to add some additional
// information to the output, including the used log level and the name of
// the function.
Expand Down
70 changes: 35 additions & 35 deletions format.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ type Formatter interface {
Format(calldepth int, r *Record, w io.Writer) error
}

// formatter is used by all backends unless otherwise overriden.
// formatter is used by all backends unless otherwise overridden.
var formatter struct {
sync.RWMutex
def Formatter
Expand Down Expand Up @@ -154,17 +154,18 @@ type stringFormatter struct {
// The verbs:
//
// General:
// %{id} Sequence number for log message (uint64).
// %{pid} Process id (int)
// %{time} Time when log occurred (time.Time)
// %{level} Log level (Level)
// %{module} Module (string)
// %{program} Basename of os.Args[0] (string)
// %{message} Message (string)
// %{longfile} Full file name and line number: /a/b/c/d.go:23
// %{shortfile} Final file name element and line number: d.go:23
// %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call ~. meaning truncated path
// %{color} ANSI color based on log level
//
// %{id} Sequence number for log message (uint64).
// %{pid} Process id (int)
// %{time} Time when log occurred (time.Time)
// %{level} Log level (Level)
// %{module} Module (string)
// %{program} Basename of os.Args[0] (string)
// %{message} Message (string)
// %{longfile} Full file name and line number: /a/b/c/d.go:23
// %{shortfile} Final file name element and line number: d.go:23
// %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call ~. meaning truncated path
// %{color} ANSI color based on log level
//
// For normal types, the output can be customized by using the 'verbs' defined
// in the fmt package, eg. '%{id:04d}' to make the id output be '%04d' as the
Expand All @@ -191,13 +192,14 @@ type stringFormatter struct {
// future.
//
// Experimental:
// %{longpkg} Full package path, eg. github.com/go-logging
// %{shortpkg} Base package path, eg. go-logging
// %{longfunc} Full function name, eg. littleEndian.PutUint32
// %{shortfunc} Base function name, eg. PutUint32
// %{callpath} Call function path, eg. main.a.b.c
//
// %{longpkg} Full package path, eg. github.com/go-logging
// %{shortpkg} Base package path, eg. go-logging
// %{longfunc} Full function name, eg. littleEndian.PutUint32
// %{shortfunc} Base function name, eg. PutUint32
// %{callpath} Call function path, eg. main.a.b.c
func NewStringFormatter(format string) (Formatter, error) {
var fmter = &stringFormatter{}
fmter := &stringFormatter{}

// Find the boundaries of all %{vars}
matches := formatRe.FindAllStringSubmatchIndex(format, -1)
Expand Down Expand Up @@ -271,41 +273,36 @@ func (f *stringFormatter) add(verb fmtVerb, layout string) {
f.parts = append(f.parts, part{verb, layout})
}

func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) error {
func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) (err error) {
for _, part := range f.parts {
if part.verb == fmtVerbStatic {
output.Write([]byte(part.layout))
} else if part.verb == fmtVerbTime {
output.Write([]byte(r.Time.Format(part.layout)))
} else if part.verb == fmtVerbLevelColor {
switch part.verb {
case fmtVerbStatic:
_, _ = output.Write([]byte(part.layout))
case fmtVerbTime:
_, _ = output.Write([]byte(r.Time.Format(part.layout)))
case fmtVerbLevelColor:
doFmtVerbLevelColor(part.layout, r.Level, output)
} else if part.verb == fmtVerbCallpath {
case fmtVerbCallpath:
depth, err := strconv.Atoi(part.layout)
if err != nil {
depth = 0
}
output.Write([]byte(formatCallpath(calldepth+1, depth)))
} else {
_, _ = output.Write([]byte(formatCallpath(calldepth+1, depth)))
default:
var v interface{}
switch part.verb {
case fmtVerbLevel:
v = r.Level
break
case fmtVerbID:
v = r.ID
break
case fmtVerbPid:
v = pid
break
case fmtVerbProgram:
v = program
break
case fmtVerbModule:
v = r.Module
break
case fmtVerbMessage:
v = r.Message()
break
case fmtVerbLongfile, fmtVerbShortfile:
_, file, line, ok := runtime.Caller(calldepth + 1)
if !ok {
Expand All @@ -327,7 +324,10 @@ func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) err
default:
panic("unhandled format part")
}
fmt.Fprintf(output, part.layout, v)
_, err = fmt.Fprintf(output, part.layout, v)
if err != nil {
return err
}
}
}
return nil
Expand Down Expand Up @@ -400,7 +400,7 @@ type backendFormatter struct {
}

// NewBackendFormatter creates a new backend which makes all records that
// passes through it beeing formatted by the specific formatter.
// passes through it being formatted by the specific formatter.
func NewBackendFormatter(b Backend, f Formatter) Backend {
return &backendFormatter{b, f}
}
Expand Down
Loading