diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..08a3074 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + time: "17:00" + open-pull-requests-limit: 10 \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..413c0ae --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: ^1.15 + - run: | + go get -v -t -d ./... + - run: | + go test -v ./... + env: + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} \ No newline at end of file diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..219a772 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,24 @@ +name: Close stale issues and pull requests + +on: + schedule: + - cron: 0 0 * * * + +jobs: + stale: + name: Update stale issues and pull requests + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: This issue is stale because it has been open ${{ secrets.OPEN_DAYS }} days with no activity. Remove stale label or comment or this will be closed in ${{ secrets.STALE_DAYS }} days. + stale-pr-message: This pull request is stale because it has been open ${{ secrets.OPEN_DAYS }} days with no activity. Remove stale label or comment or this will be closed in ${{ secrets.STALE_DAYS }} days. + close-issue-message: This issue has been closed because it has been open for ${{ secrets.TOTAL_DAYS }} days with no activity. + close-pr-message: This pull request has been closed because it has been open for ${{ secrets.TOTAL_DAYS }} days with no activity. + stale-issue-label: stale-closing-soon + stale-pr-label: stale-closing-soon + close-issue-label: stale-closed + close-pr-label: stale-closed + days-before-stale: ${{ secrets.OPEN_DAYS }} + days-before-close: ${{ secrets.STALE_DAYS }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 888aba4..23ebd6a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,12 +12,13 @@ *.out # Text editors/IDEs -.vscode +.vscode/ __debug_bin -.idea +.idea/ # Directories. -dist +bin/ +dist/ -# Env files +# Env files. *.env \ No newline at end of file diff --git a/README.md b/README.md index 7cb9557..e24380d 100644 --- a/README.md +++ b/README.md @@ -1 +1,70 @@ -# little logger \ No newline at end of file +## A package for structured logging + +![GitHub tag (latest SemVer pre-release)](https://img.shields.io/github/v/tag/gofor-little/log?include_prereleases) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gofor-little/log) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/gofor-little/log/main/LICENSE) +![GitHub Workflow Status](https://img.shields.io/github/workflow/status/gofor-little/log/CI) +[![Go Report Card](https://goreportcard.com/badge/github.com/gofor-little/log)](https://goreportcard.com/report/github.com/gofor-little/log) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/gofor-little/log)](https://pkg.go.dev/github.com/gofor-little/log) + +### Introduction +* Structured logging +* Supports AWS CloudWatch +* Simple interface for implementing your own + +### Example +```go +package main + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws/session" + "github.com/gofor-little/log" +) + +func main() { + // Standard logger writes to a user defined io.Writer. + log.Log = log.NewStandardLogger(os.Stdout, log.Fields{ + "tag": "standard_logger", + }) + + // CloudWatch logger writes to an AWS CloudWatch log group. + sess, err = session.NewSession() + log.Log, err = log.NewCloudWatchLogger(sess, "CloudWatchLoggerTest", log.Fields{ + "tag": "cloudWatchLoggerTest", + }) + if err != nil { + t.Fatalf("failed to create new CloudWatchLogger: %v", err) + } + + // Log at info, error and debug levels. + log.Info(log.Fields{ + "message": "info message", + "bool": true, + "int": 64, + "float": 3.14159, + }) + + log.Error(log.Fields{ + "string": "error message", + "bool": true, + "int": 64, + "float": 3.14159, + }) + + log.Debug(log.Fields{ + "string": "debug message", + "bool": true, + "int": 64, + "float": 3.14159, + }) +} +``` + +### Testing +Ensure the following environment variables are set, usually with a .env file. +* ```AWS_PROFILE``` (an AWS CLI profile name) +* ```AWS_REGION``` (a valid AWS region) + +Run ```go test ./...``` in the root directory. \ No newline at end of file diff --git a/cloud_watch_logger_test.go b/cloud_watch_logger_test.go index e2f2b4d..c1327e8 100644 --- a/cloud_watch_logger_test.go +++ b/cloud_watch_logger_test.go @@ -1,25 +1,38 @@ package log_test import ( - "fmt" "testing" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" + "github.com/gofor-little/env" "github.com/gofor-little/log" ) func TestCloudWatchLogger(t *testing.T) { - sess := session.Must(session.NewSessionWithOptions(session.Options{ - Config: aws.Config{ - Region: aws.String("ap-southeast-2"), - }, - Profile: "", - })) - + var sess *session.Session var err error + + if err := env.Load(".env"); err != nil { + t.Log(".env file not found, ignore this if running in CI/CD Pipeline") + } + + if env.Get("ENVIRONMENT", "ci/cd") == "development" { + sess, err = session.NewSessionWithOptions(session.Options{ + Config: aws.Config{ + Region: aws.String(env.Get("AWS_REGION", "ap-southeast-2")), + }, + Profile: env.Get("AWS_PROFILE", "default"), + }) + } else { + sess, err = session.NewSession() + } + if err != nil { + t.Fatalf("failed to create new session.Session") + } + log.Log, err = log.NewCloudWatchLogger(sess, "CloudWatchLoggerTest", log.Fields{ "tag": "cloudWatchLoggerTest", }) @@ -27,13 +40,32 @@ func TestCloudWatchLogger(t *testing.T) { t.Fatalf("failed to create new CloudWatchLogger: %v", err) } - for i := 0; i < 100; i++ { - if err := log.Info(log.Fields{ - "message": fmt.Sprintf("test info message number: %v", i), - }); err != nil { - t.Fatalf("failed to write info log: %v", err) - } + if err := log.Info(log.Fields{ + "string": "test info string", + "bool": true, + "int": 64, + "float": 3.14159, + }); err != nil { + t.Fatalf("failed to write Info log message") + } + + if err := log.Error(log.Fields{ + "string": "test error string", + "bool": true, + "int": 64, + "float": 3.14159, + }); err != nil { + t.Fatalf("failed to write Error log message") + } + + if err := log.Debug(log.Fields{ + "string": "test debug string", + "bool": true, + "int": 64, + "float": 3.14159, + }); err != nil { + t.Fatalf("failed to write Debug log message") } - time.Sleep(time.Second * 5) + time.Sleep(time.Second) } diff --git a/go.mod b/go.mod index 42ee2eb..5cbe514 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ module github.com/gofor-little/log -go 1.13 +go 1.15 require ( github.com/aws/aws-sdk-go v1.36.17 + github.com/gofor-little/env v0.4.3 github.com/gofor-little/ts v0.1.0 github.com/stretchr/testify v1.5.1 // indirect ) diff --git a/go.sum b/go.sum index 4dba4aa..c311b39 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,18 @@ github.com/aws/aws-sdk-go v1.29.29 h1:4TdSYzXL8bHKu80tzPjO4c0ALw4Fd8qZGqf1aozUcBU= github.com/aws/aws-sdk-go v1.29.29/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= +github.com/aws/aws-sdk-go v1.36.17 h1:8zTvseyGhgs3uQAzkgnFy7dvTo+ZnZLYmrhnopFxYME= github.com/aws/aws-sdk-go v1.36.17/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/gofor-little/env v0.4.3 h1:FqtZmTzUxju/DBSSv/m/3noBt10pdU+7695XgHJtaoo= +github.com/gofor-little/env v0.4.3/go.mod h1:aPkmDX9t/3zhViWDnhNH8RtlSbSOoZ9dmKbUo12tnN8= github.com/gofor-little/ts v0.1.0 h1:40dDLxNORHXzETnKmRhm7YrzU1p7S79sClFSJMAB4PQ= github.com/gofor-little/ts v0.1.0/go.mod h1:ZT8fzifgCAHMch+P88ViTj9Tgke/rHIDsl3LN7g/zFE= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/standard_logger_test.go b/standard_logger_test.go index 96fd989..89240eb 100644 --- a/standard_logger_test.go +++ b/standard_logger_test.go @@ -12,33 +12,30 @@ func TestLog(t *testing.T) { "tag": "logTest", }) - err := log.Info(log.Fields{ + if err := log.Info(log.Fields{ "string": "test info string", "bool": true, "int": 64, "float": 3.14159, - }) - if err != nil { + }); err != nil { t.Fatalf("failed to write Info log message") } - err = log.Error(log.Fields{ + if err := log.Error(log.Fields{ "string": "test error string", "bool": true, "int": 64, "float": 3.14159, - }) - if err != nil { + }); err != nil { t.Fatalf("failed to write Error log message") } - err = log.Debug(log.Fields{ + if err := log.Debug(log.Fields{ "string": "test debug string", "bool": true, "int": 64, "float": 3.14159, - }) - if err != nil { + }); err != nil { t.Fatalf("failed to write Debug log message") } }