Skip to content

Commit

Permalink
Merge pull request #4 from moul/dev/moul/v1
Browse files Browse the repository at this point in the history
  • Loading branch information
moul authored Jun 9, 2021
2 parents 34c30a9 + 55a3fa1 commit 6327ba5
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 19 deletions.
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ GOPKG ?= moul.io/logman

include rules.mk

lint:
cd tool/lint; make
.PHONY: lint
generate:
GO111MODULE=off go get github.com/campoy/embedmd
mkdir -p .tmp
go doc -all > .tmp/godoc.txt
embedmd -w README.md
rm -rf .tmp
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# logman

:smile: logman
:smile: golang library to organize log files (create by date, GC, etc)

[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/moul.io/logman)
[![License](https://img.shields.io/badge/license-Apache--2.0%20%2F%20MIT-%2397ca00.svg)](https://github.com/moul/logman/blob/main/COPYRIGHT)
Expand All @@ -18,18 +18,44 @@

[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/moul/logman)

## Example

[embedmd]:# (example_test.go /import\ / $)
```go
import "moul.io/logman"

func Example() {
writer, _ := logman.NewWriteCloser("./path/to/logdir/", "my-app")
defer writer.Close()
writer.Write([]byte("hello world!"))
}
```

## Usage

[embedmd]:# (.tmp/usage.txt console)
```console
foo@bar:~$ logman hello world
_ _ _ _
__ _ ___ | | __ _ _ _ __ _ ___ _ _ ___ _ __ ___ ___ | |_ ___ _ __ _ __ | | __ _ | |_ ___
/ _` |/ _ \| |/ _` || ' \ / _` ||___|| '_|/ -_)| '_ \/ _ \|___|| _|/ -_)| ' \ | '_ \| |/ _` || _|/ -_)
\__, |\___/|_|\__,_||_||_|\__, | |_| \___|| .__/\___/ \__|\___||_|_|_|| .__/|_|\__,_| \__|\___|
|___/ |___/ |_| |_|
12 CPUs, /home/moul/.gvm/pkgsets/go1.16/global/bin/logman, fwrz, go1.16
args ["logman","hello","world"]
[embedmd]:# (.tmp/godoc.txt txt /FUNCTIONS/ $)
```txt
FUNCTIONS
func LogfileGC(logDir string, max int) error
func NewWriteCloser(target, kind string) (io.WriteCloser, error)
TYPES
type Logfile struct {
Dir string
Name string
Size int64
Kind string
Time time.Time
Latest bool
Errs error `json:"Errs,omitempty"`
}
func LogfileList(logDir string) ([]*Logfile, error)
func (l Logfile) Path() string
```

## Install
Expand Down
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@
// |/ | | \ \ / / ' \/ _ \/ // / / |
// || | | | | | /_/_/_/\___/\_,_/_/ |
// +--------------------------------------------------------------+
package main // import "moul.io/logman"
package logman
9 changes: 9 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package logman_test

import "moul.io/logman"

func Example() {
writer, _ := logman.NewWriteCloser("./path/to/logdir/", "my-app")
defer writer.Close()
writer.Write([]byte("hello world!"))
}
7 changes: 3 additions & 4 deletions go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

151 changes: 151 additions & 0 deletions logman.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package logman

import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"time"

"go.uber.org/multierr"
"moul.io/u"
)

func NewWriteCloser(target, kind string) (io.WriteCloser, error) {
var filename string
switch {
case strings.HasSuffix(target, ".log"): // use the indicated 'path' as filename
filename = target
default: // automatically create a new file in the 'path' directory following a pattern
startTime := time.Now().Format(filePatternDateLayout)
filename = filepath.Join(
target,
fmt.Sprintf("%s-%s.log", kind, startTime),
)
// run gc
{
err := LogfileGC(target, 20)
if err != nil {
return nil, err
}
}
}

if dir := filepath.Dir(filename); !u.DirExists(dir) {
err := os.MkdirAll(dir, 0o711)
if err != nil {
return nil, err
}
}

var writer io.WriteCloser
if u.FileExists(filename) {
var err error
writer, err = os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
return nil, err
}
} else {
var err error
writer, err = os.Create(filename)
if err != nil {
return nil, err
}
}

return writer, nil
}

type Logfile struct {
Dir string
Name string
Size int64
Kind string
Time time.Time
Latest bool
Errs error `json:"Errs,omitempty"`
}

func (l Logfile) Path() string {
return filepath.Join(l.Dir, l.Name)
}

const filePatternDateLayout = "2006-01-02T15-04-05.000"

var filePatternRegex = regexp.MustCompile(`(?m)^(.*)-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}.\d{3}).log$`)

func LogfileList(logDir string) ([]*Logfile, error) {
files, err := ioutil.ReadDir(logDir)
if err != nil {
return nil, err
}

logfiles := []*Logfile{}
for _, file := range files {
sub := filePatternRegex.FindStringSubmatch(file.Name())
if sub == nil {
continue
}
t, err := time.Parse(filePatternDateLayout, sub[2])
var errs error
if err != nil {
errs = multierr.Append(errs, err)
}

logfiles = append(logfiles, &Logfile{
Dir: logDir,
Name: file.Name(),
Size: file.Size(),
Kind: sub[1],
Time: t,
Errs: errs,
})
}

// compute latest
if len(logfiles) > 0 {
var maxTime time.Time
for _, file := range logfiles {
if file.Time.After(maxTime) {
maxTime = file.Time
}
}
for _, file := range logfiles {
if file.Time == maxTime {
file.Latest = true
}
}
}

return logfiles, nil
}

func LogfileGC(logDir string, max int) error {
if !u.DirExists(logDir) {
return nil
}
files, err := LogfileList(logDir)
if err != nil {
return err
}
if len(files) < max {
return nil
}

sort.Slice(files, func(i, j int) bool {
return files[i].Time.Before(files[j].Time)
})

var errs error
for i := 0; i < len(files)-max; i++ {
err := os.Remove(files[i].Path())
if err != nil {
errs = multierr.Append(errs, err)
}
}
return errs
}
Loading

0 comments on commit 6327ba5

Please sign in to comment.