Skip to content

Commit f8e07d0

Browse files
author
Stephen High
committed
init commit
0 parents  commit f8e07d0

File tree

13 files changed

+1841
-0
lines changed

13 files changed

+1841
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.idea
2+
.vscode
3+
*.env
4+
coverage.out
5+
TESTING.md

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2025 12 Parsecs
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Makefile for github.com/twlvprscs/log
2+
3+
# Default target is help
4+
.DEFAULT_GOAL := help
5+
6+
# COLORS
7+
GREEN := $(shell tput -Txterm setaf 2)
8+
YELLOW := $(shell tput -Txterm setaf 3)
9+
WHITE := $(shell tput -Txterm setaf 7)
10+
RESET := $(shell tput -Txterm sgr0)
11+
12+
.PHONY: help
13+
help: ## Show this help message
14+
@echo ''
15+
@echo 'Usage:'
16+
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
17+
@echo ''
18+
@echo 'Targets:'
19+
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " ${GREEN}%-15s${RESET} %s\n", $$1, $$2}' $(MAKEFILE_LIST)
20+
21+
.PHONY: fmt
22+
fmt: ## Run gofmt on all Go files
23+
@echo "Formatting Go code..."
24+
@gofmt -s -w .
25+
26+
.PHONY: test
27+
test: ## Run unit tests
28+
@echo "Running tests..."
29+
@go test -v ./...
30+
31+
.PHONY: lint
32+
lint: ## Run golang-ci linter
33+
@echo "Running linter..."
34+
@if command -v golangci-lint > /dev/null; then \
35+
golangci-lint run; \
36+
else \
37+
echo "golangci-lint not found. Please install it first."; \
38+
echo "See https://golangci-lint.run/usage/install/ for installation instructions."; \
39+
exit 1; \
40+
fi

README.md

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# twlvprscs/log
2+
3+
A structured logging package for Go applications built on top of [Uber's Zap](https://github.com/uber-go/zap) logging library. This package provides a simplified API for common logging patterns while maintaining the performance benefits of Zap.
4+
5+
## Features
6+
7+
- **Structured logging** with key-value pairs for better log analysis
8+
- **Multiple logging levels** (Debug, Info, Warn, Error, DPanic, Panic, Fatal)
9+
- **Context-aware logging** to propagate logging fields through your application
10+
- **Global logging functions** for simple use cases
11+
- **Highly configurable** with sensible defaults
12+
- **High performance** leveraging Zap's optimized logging implementation
13+
14+
## Installation
15+
16+
```bash
17+
go get github.com/twlvprscs/log
18+
```
19+
20+
## Basic Usage
21+
22+
### Using Global Functions
23+
24+
The simplest way to use the package is with the global logging functions:
25+
26+
```go
27+
package main
28+
29+
import (
30+
"time"
31+
32+
"github.com/twlvprscs/log"
33+
"go.uber.org/zap"
34+
)
35+
36+
func main() {
37+
// Initialize a default logger and set it as global
38+
log.NewLogger(log.AsGlobal())
39+
40+
// Use global logging functions
41+
log.Info("Application started", zap.Int("port", 8080))
42+
43+
// Add structured data to your logs
44+
log.Debug("Connection established",
45+
zap.String("remote_addr", "192.168.1.1:3000"),
46+
zap.Duration("latency", 5*time.Millisecond),
47+
)
48+
49+
// Log errors with stack traces
50+
if err := connectToDatabase(); err != nil {
51+
log.Error("Database connection failed", zap.Error(err))
52+
}
53+
54+
// Function defined elsewhere in your code
55+
// func connectToDatabase() error { ... }
56+
57+
// Ensure logs are flushed before exiting
58+
defer log.Sync()
59+
}
60+
```
61+
62+
### Creating a Custom Logger
63+
64+
For more control, you can create a custom logger:
65+
66+
```go
67+
package main
68+
69+
import (
70+
"github.com/twlvprscs/log"
71+
"go.uber.org/zap"
72+
"go.uber.org/zap/zapcore"
73+
)
74+
75+
func main() {
76+
// Create a custom logger with specific options
77+
logger := log.NewLogger(
78+
log.WithLevel(zapcore.InfoLevel),
79+
log.WithFields(
80+
zap.String("service", "api"),
81+
zap.String("version", "1.0.0"),
82+
),
83+
)
84+
85+
// Use the logger directly
86+
logger.Info("Server starting")
87+
88+
// Add more fields to an existing logger
89+
apiLogger := logger.With(zap.String("component", "auth"))
90+
apiLogger.Debug("Processing request")
91+
92+
// Ensure logs are flushed
93+
defer logger.Sync()
94+
}
95+
```
96+
97+
## Advanced Usage
98+
99+
### Context-Aware Logging
100+
101+
The package provides context-aware logging to propagate logging fields through your application:
102+
103+
```go
104+
package main
105+
106+
import (
107+
"context"
108+
109+
"github.com/twlvprscs/log"
110+
"go.uber.org/zap"
111+
)
112+
113+
func main() {
114+
// Initialize the global logger
115+
log.NewLogger(log.AsGlobal())
116+
117+
// Create a context with logging fields
118+
ctx := context.Background()
119+
ctx = log.Stash(ctx, zap.String("request_id", "abc-123"))
120+
121+
// Pass the context to other functions
122+
processRequest(ctx)
123+
}
124+
125+
func processRequest(ctx context.Context) {
126+
// Get a logger from the context
127+
logger := log.Ctx(ctx)
128+
129+
// Log with the fields from the context
130+
logger.Info("Processing request")
131+
132+
// Add more fields for this specific log
133+
logger.Debug("Request details",
134+
zap.String("path", "/api/users"),
135+
zap.String("method", "GET"),
136+
)
137+
138+
// Pass the context to other functions
139+
validateRequest(ctx)
140+
}
141+
142+
func validateRequest(ctx context.Context) {
143+
// All logs will include the request_id from the context
144+
log.Ctx(ctx).Info("Validating request")
145+
}
146+
```
147+
148+
### Custom Configuration
149+
150+
For advanced configuration needs:
151+
152+
```go
153+
package main
154+
155+
import (
156+
"github.com/twlvprscs/log"
157+
"go.uber.org/zap"
158+
)
159+
160+
func main() {
161+
// Create a custom configuration
162+
cfg := zap.NewProductionConfig()
163+
cfg.Encoding = "json"
164+
cfg.OutputPaths = []string{"stdout", "/var/log/app.log"}
165+
166+
// Customize the encoder config
167+
cfg.EncoderConfig.TimeKey = "timestamp"
168+
cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
169+
170+
// Create a logger with the custom configuration
171+
logger := log.NewLogger(log.WithConfig(&cfg))
172+
173+
// Use the logger
174+
logger.Info("Application configured with custom settings")
175+
}
176+
```
177+
178+
### Redirecting Standard Library Logs
179+
180+
Capture logs from the standard library:
181+
182+
```go
183+
package main
184+
185+
import (
186+
stdlog "log"
187+
188+
"github.com/twlvprscs/log"
189+
"go.uber.org/zap/zapcore"
190+
)
191+
192+
func main() {
193+
// Redirect standard library logs to our logger at warning level
194+
log.NewLogger(
195+
log.AsGlobal(),
196+
log.WithRedirectStdLog(zapcore.WarnLevel),
197+
)
198+
199+
// Standard library logs will now be captured
200+
stdlog.Println("This will be captured as a warning log")
201+
}
202+
```
203+
204+
## API Reference
205+
206+
### Logger Creation
207+
208+
- `NewLogger(opts ...Option) *zap.Logger`: Creates a new logger with the specified options
209+
210+
### Options
211+
212+
- `WithLevel(level zapcore.Level) Option`: Sets the minimum log level
213+
- `WithSampling(sampling *zap.SamplingConfig) Option`: Configures log sampling
214+
- `AsGlobal() Option`: Sets the logger as the global logger
215+
- `WithFields(fields ...zap.Field) Option`: Adds fields to all log entries
216+
- `WithConfig(cfg *zap.Config) Option`: Sets a custom configuration
217+
- `WithRedirectStdLog(lvl zapcore.Level) Option`: Redirects standard library logs
218+
219+
### Global Functions
220+
221+
- `Debug(msg string, fields ...zap.Field)`: Logs at debug level
222+
- `Info(msg string, fields ...zap.Field)`: Logs at info level
223+
- `Warn(msg string, fields ...zap.Field)`: Logs at warning level
224+
- `Error(msg string, fields ...zap.Field)`: Logs at error level
225+
- `DPanic(msg string, fields ...zap.Field)`: Logs at development panic level
226+
- `Panic(msg string, fields ...zap.Field)`: Logs at panic level and panics
227+
- `Fatal(msg string, fields ...zap.Field)`: Logs at fatal level and exits
228+
- `Sync() error`: Flushes any buffered logs
229+
- `With(fields ...zap.Field) *zap.Logger`: Creates a new logger with additional fields
230+
231+
### Context Functions
232+
233+
- `Stash(parent context.Context, fields ...zap.Field) context.Context`: Stores logging fields in a context
234+
- `Ctx(parent context.Context) ContextLogger`: Gets a logger from a context
235+
236+
## License
237+
238+
This project is licensed under the MIT License - see the LICENSE file for details.

UBER_LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2016-2024 Uber Technologies, Inc.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

0 commit comments

Comments
 (0)