Skip to content

Commit 6e31ef2

Browse files
committed
feat: initial implementation of go-tlog with examples, CI and README
Initial project setup: - Added logger core (level, format, stacktrace, internal outputs) - Added tests for core logger functionality - Added examples (stdout, stderr, file) - Added GitHub Actions CI workflow - Added README and LICENSE (BSD 2-Clause) - Added .golangci.yml and .gitignore
1 parent 1142341 commit 6e31ef2

30 files changed

+2101
-0
lines changed

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ '**' ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
name: Go tests
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v5
20+
with:
21+
go-version: '1.24.x'
22+
check-latest: true
23+
24+
- name: Download deps
25+
run: go mod download
26+
27+
- name: Run tests
28+
run: make test

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# IDE
2+
.idea
3+
4+
coverage.out

.golangci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
run:
2+
timeout: 5m
3+
modules-download-mode: readonly
4+
5+
issues:
6+
exclude-use-default: false
7+
max-same-issues: 0
8+
max-issues-per-linter: 0
9+
10+
linters:
11+
enable:
12+
- govet
13+
- staticcheck
14+
- revive
15+
- errcheck
16+
- gosimple
17+
- ineffassign
18+
- unused
19+
- typecheck
20+
- gofmt
21+
- goimports
22+
- misspell
23+
- gocritic
24+
25+
linters-settings:
26+
revive:
27+
severity: warning
28+
rules:
29+
- name: unused-parameter
30+
- name: unreachable-code
31+
- name: indent-error-flow
32+
- name: exported
33+
- name: blank-imports
34+
- name: var-declaration
35+
- name: if-return
36+
37+
misspell:
38+
locale: US
39+
40+
goimports:
41+
local-prefixes: github.com/tarantool/go-tlog
42+
43+
# Skip linters on example files and any generated code
44+
exclude-rules:
45+
- path: ^_examples/
46+
linters: [revive, staticcheck, govet, gocritic]
47+
- path: \.pb\.go$|_gen\.go$
48+
linters: [all]

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
12+
### Changed
13+
14+
### Fixed

LICENCE

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
BSD 2-Clause License
2+
3+
Copyright (c) 2025, Tarantool AUTHORS
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Makefile

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Default Go toolchain
2+
GO ?= go
3+
GOLANGCI_LINT ?= golangci-lint
4+
PKG := github.com/tarantool/go-tlog
5+
6+
.PHONY: all test test-race test-coverage lint fmt tidy examples help
7+
8+
all: test
9+
10+
## Run tests
11+
test:
12+
$(GO) test ./...
13+
14+
## Run tests with race detector
15+
test-race:
16+
$(GO) test -race ./...
17+
18+
## Run tests with coverage
19+
test-coverage:
20+
$(GO) test -covermode=atomic -coverprofile=coverage.out ./...
21+
22+
## Run golangci-lint
23+
lint:
24+
$(GOLANGCI_LINT) run ./...
25+
26+
## Format source code
27+
fmt:
28+
$(GO) fmt ./...
29+
30+
## Tidy go.mod / go.sum
31+
tidy:
32+
$(GO) mod tidy
33+
34+
## Run all _examples to ensure they compile and run without panic
35+
examples:
36+
$(GO) run ./_examples/stdout
37+
$(GO) run ./_examples/stderr >/dev/null 2>&1 || true
38+
$(GO) run ./_examples/file
39+
$(GO) run ./_examples/multi
40+
41+
## Show available targets
42+
help:
43+
@echo "Available targets:"
44+
@echo " make test - run tests"
45+
@echo " make test-race - run tests with -race"
46+
@echo " make test-coverage - run tests with coverage"
47+
@echo " make lint - run golangci-lint"
48+
@echo " make fmt - format sources (gofmt)"
49+
@echo " make tidy - go mod tidy"
50+
@echo " make examples - run all examples"

README.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,189 @@
1+
[![CI](https://github.com/tarantool/go-tlog/actions/workflows/ci.yml/badge.svg)](https://github.com/tarantool/go-tlog/actions/workflows/ci.yml)
2+
[Telegram EN](https://t.me/tarantool)
3+
[Telegram RU](https://t.me/tarantoolru)
4+
5+
---
6+
7+
<p href="https://www.tarantool.io">
8+
<img src="https://github.com/tarantool.png" align="right" width=250>
9+
</p>
10+
111
# go-tlog
12+
13+
`go-tlog` is a lightweight and configurable logging library for Go applications.
14+
It provides structured logging with multiple output destinations, flexible formatting,
15+
and fine-grained log-level control.
16+
17+
---
18+
19+
## Features
20+
21+
- Simple setup via configuration struct
22+
- Text or JSON output formats
23+
- Multiple output targets: **stdout**, **stderr**, **files**
24+
- Log levels: `Trace`, `Debug`, `Info`, `Warn`, `Error`
25+
- Automatic timestamp, source file, and line number
26+
- Stacktrace for errors
27+
28+
---
29+
30+
## Installation
31+
32+
```bash
33+
go get github.com/tarantool/go-tlog@latest
34+
```
35+
36+
Then import:
37+
38+
```go
39+
import "github.com/tarantool/go-tlog"
40+
```
41+
42+
---
43+
44+
## Quick start
45+
46+
```go
47+
package main
48+
49+
import "github.com/tarantool/go-tlog"
50+
51+
func main() {
52+
log, err := tlog.New(tlog.Opts{
53+
Level: tlog.LevelInfo,
54+
Format: tlog.FormatText,
55+
Path: "stdout",
56+
})
57+
if err != nil {
58+
panic(err)
59+
}
60+
defer log.Close()
61+
62+
logger := log.Logger().With(tlog.String("component", "demo"))
63+
logger.Info("service started", "port", 8080)
64+
logger.Error("failed to connect", "err", "timeout")
65+
}
66+
```
67+
68+
Output:
69+
70+
```
71+
2025-11-10T13:30:01+05:00 INFO service started component=demo port=8080
72+
2025-11-10T13:30:01+05:00 ERROR failed to connect err=timeout component=demo stacktrace="..."
73+
```
74+
75+
---
76+
77+
## Configuration
78+
79+
### `type Opts`
80+
81+
```go
82+
type Opts struct {
83+
Level Level // minimal log level
84+
Format Format // FormatText or FormatJSON
85+
Path string // comma-separated outputs: "stdout,/var/log/app.log"
86+
}
87+
```
88+
89+
### Main API
90+
91+
| Function | Description |
92+
|------------------|------------------------------------------|
93+
| `tlog.New(opts)` | Create a new logger |
94+
| `Logger()` | Return the underlying logger for use |
95+
| `Close()` | Flush buffers and close file descriptors |
96+
97+
---
98+
99+
## Log levels
100+
101+
| Level | When to use |
102+
|---------|---------------------------------------------|
103+
| `Trace` | Low-level tracing |
104+
| `Debug` | Debugging information |
105+
| `Info` | Normal operational messages |
106+
| `Warn` | Non-fatal warnings |
107+
| `Error` | Errors and exceptions (includes stacktrace) |
108+
109+
---
110+
111+
## Output formats
112+
113+
| Format | Example |
114+
|--------------|---------------------------------------------------------------|
115+
| `FormatText` | `2025-11-10T13:31:45+05:00 INFO message key=value` |
116+
| `FormatJSON` | `{"time":"...","level":"INFO","msg":"message","key":"value"}` |
117+
118+
---
119+
120+
## Output destinations
121+
122+
You can specify multiple targets separated by commas:
123+
124+
```go
125+
Path: "stdout,/tmp/app.log"
126+
```
127+
128+
Supported targets:
129+
130+
- `stdout`
131+
- `stderr`
132+
- File paths (created automatically if not present)
133+
134+
---
135+
136+
## Examples
137+
138+
Ready-to-run examples are located in the `_examples/` directory:
139+
140+
```
141+
_examples/
142+
├── stdout/
143+
│ └── main.go
144+
├── stderr/
145+
│ └── main.go
146+
├── file/
147+
│ └── main.go
148+
└── multi/
149+
└── main.go
150+
```
151+
152+
Run examples:
153+
154+
```bash
155+
# Example 1 — log to STDOUT in text format
156+
go run ./_examples/stdout
157+
158+
# Example 2 — log to STDERR in JSON format
159+
# Redirect stderr to a file and inspect its contents
160+
go run ./_examples/stderr 2> logs.json
161+
cat logs.json
162+
163+
# Example 3 — log to a file in /tmp directory
164+
# The file will be created automatically if it doesn’t exist
165+
go run ./_examples/file
166+
cat /tmp/tlog_demo/app.log
167+
168+
# Example 4 — log to multiple destinations (stdout + file)
169+
# This writes the same log entry both to console and to /tmp/tlog_multi/app.log
170+
go run ./_examples/multi
171+
cat /tmp/tlog_multi/app.log
172+
```
173+
174+
Each example demonstrates different combinations of Path, Format, and Level,
175+
including how to log to multiple outputs at the same time.
176+
177+
---
178+
179+
## Testing
180+
181+
```bash
182+
go test ./...
183+
```
184+
185+
---
186+
187+
## License
188+
189+
BSD 2-Clause License — see [LICENSE](LICENSE)

_examples/file/main.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"log/slog"
5+
"os"
6+
7+
"github.com/tarantool/go-tlog"
8+
)
9+
10+
func main() {
11+
_ = os.MkdirAll("/tmp/tlog_demo", 0755)
12+
13+
l, err := tlog.New(tlog.Opts{
14+
Level: tlog.LevelInfo,
15+
Format: tlog.FormatText,
16+
Path: "/tmp/tlog_demo/app.log",
17+
})
18+
if err != nil {
19+
panic(err)
20+
}
21+
defer l.Close()
22+
23+
log := l.Logger().With(slog.String("mode", "file"))
24+
log.Info("logging to file", "path", "/tmp/tlog_demo/app.log")
25+
log.Warn("network delay", "ms", 250)
26+
log.Error("write failed", "err", "disk quota exceeded")
27+
}

0 commit comments

Comments
 (0)