Skip to content

Commit

Permalink
refactor: update CI setup, kebab-case rule, and refactor modules
Browse files Browse the repository at this point in the history
- Refactored `ci.yml` to update go and python setup steps.
- Modified pre-commit to exclude additional README files.
- Introduced new documentation for `configfx` and `logfx`.
- Renamed various `mod.go` to `mod-fx.go` and updated related functions.
- Improved `ConfigLoader` and added methods `FromEnvFileDirect`, `FromJsonFileDirect`.
- Updated `logfx` with new logging configuration and fx integration.
- Optimized result handling by commenting out unused payload attributes.
  • Loading branch information
eser committed Aug 25, 2024
1 parent 3751da4 commit 4768550
Show file tree
Hide file tree
Showing 16 changed files with 316 additions and 61 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ jobs:
with:
go-version: ${{ matrix.golang-version }}
cache: true
go-version-file: go.mod
cache-dependency-path: go.sum

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Setup govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest
Expand Down
9 changes: 8 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,14 @@ repos:
Dockerfile|
LICENSE|
Makefile|
README.md
README.md|
pkg/bliss/configfx/README.md|
pkg/bliss/datafx/README.md|
pkg/bliss/httpfx/README.md|
pkg/bliss/lib/README.md|
pkg/bliss/logfx/README.md|
pkg/bliss/results/README.md|
pkg/bliss/README.md|
)$
- id: run-tests
name: run tests
Expand Down
123 changes: 123 additions & 0 deletions pkg/bliss/configfx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# bliss/configfx

## Overview

The **configfx** package provides a flexible and powerful configuration loader for Go applications. It supports loading configuration from various sources, including environment files, JSON files, and system environment variables. The package is designed to work seamlessly with the `go.uber.org/fx` framework.

The documentation below provides an overview of the package, its types, functions, and usage examples. For more detailed information, refer to the source code and tests.


## Fx

The `configfx` package provides an `FxModule` that can be used to integrate with the `fx` framework.

```go
import (
...
"github.com/eser/go-service/pkg/bliss/configfx"
"go.uber.org/fx"
...
)

app := fx.New(
configfx.FxModule, // registers configfx.ConfigLoader
...
)

app.Run()
```


## API

### ConfigLoader interface
Defines methods for loading configuration.

```
type ConfigLoader interface {
LoadMeta(i any) (ConfigItemMeta, error)
LoadMap(resources ...ConfigResource) (*map[string]any, error)
Load(i any, resources ...ConfigResource) error
FromEnvFileDirect(filename string) ConfigResource
FromEnvFile(filename string) ConfigResource
FromSystemEnv() ConfigResource
FromJsonFileDirect(filename string) ConfigResource
FromJsonFile(filename string) ConfigResource
}
```


### New function

Creates a new `slog.Logger` object based on the provided configuration.

```go
// func NewLogger(config *Config) (*slog.Logger, error)

logger, err := logfx.NewLogger(config)
```


### NewLoggerAsDefault function

Creates a new `slog.Logger` object based on the provided configuration and makes it default slog instance.

```go
// func NewLoggerAsDefault(config *Config) (*slog.Logger, error)

logger, err := logfx.NewLoggerAsDefault(config)
```


### Load function

The `Load` method loads configuration from multiple resources.

Example:
```go
type AppConfig struct {
AppName string `conf:"NAME" default:"go-service"`

Postgres struct {
Dsn string `conf:"DSN" default:"postgres://localhost:5432"`
} `conf:"POSTGRES"`
}

func loadConfig() (*AppConfig, error) {
conf := &AppConfig{}

err := cl.Load(
conf,
// load order:
cl.FromJsonFile("config.json"), // - attempts to read from config.json,
// config.local.json,
// config.[env].json,
// config.[env].local.json
cl.FromEnvFile(".env"), // - attempts to read from .env
// .env.local
// .env.[env]
// .env.[env].local
cl.FromSystemEnv(), // - attempts to read from system environment variables
)
if err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}

return conf, nil
}

func main() {
appConfig, err := loadConfig()
if err != nil {
log.Fatalf("Error loading config: %v", err)

return
}

// Searches JSON files first, then checks the POSTGRES__DSN among environment variables.
// If the config variable is not specified, it falls back to the default value "postgres://localhost:5432".
fmt.Println(appConfig.Postgres.Dsn)
}
```
6 changes: 3 additions & 3 deletions pkg/bliss/configfx/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const (
tagRequired = "required"
)

var ErrNotStruct = results.Define("ERRBC00001", "not a struct")
var ErrNotStruct = results.Define("ERRBC00001", "not a struct") //nolint:gochecknoglobals

type ConfigItemMeta struct {
Name string
Expand All @@ -34,11 +34,11 @@ type ConfigLoader interface {
LoadMap(resources ...ConfigResource) (*map[string]any, error)
Load(i any, resources ...ConfigResource) error

FromEnvFileSingle(filename string) ConfigResource
FromEnvFileDirect(filename string) ConfigResource
FromEnvFile(filename string) ConfigResource
FromSystemEnv() ConfigResource

FromJsonFileSingle(filename string) ConfigResource
FromJsonFileDirect(filename string) ConfigResource
FromJsonFile(filename string) ConfigResource
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/bliss/configfx/mod.go → pkg/bliss/configfx/mod-fx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
var FxModule = fx.Module( //nolint:gochecknoglobals
"config",
fx.Provide(
New,
FxNew,
),
)

Expand All @@ -17,8 +17,10 @@ type FxResult struct {
ConfigLoader ConfigLoader
}

func New() (FxResult, error) {
return FxResult{ //nolint:exhaustruct
func FxNew() (FxResult, error) {
return FxResult{
Out: fx.Out{},

ConfigLoader: NewConfigLoader(),
}, nil
}
4 changes: 2 additions & 2 deletions pkg/bliss/configfx/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/eser/go-service/pkg/bliss/lib"
)

func (dcl *ConfigLoaderImpl) FromEnvFileSingle(filename string) ConfigResource {
func (dcl *ConfigLoaderImpl) FromEnvFileDirect(filename string) ConfigResource {
return func(target *map[string]any) error {
err := envparser.TryParseFiles(target, filename)
if err != nil {
Expand Down Expand Up @@ -41,7 +41,7 @@ func (dcl *ConfigLoaderImpl) FromSystemEnv() ConfigResource {
}
}

func (dcl *ConfigLoaderImpl) FromJsonFileSingle(filename string) ConfigResource {
func (dcl *ConfigLoaderImpl) FromJsonFileDirect(filename string) ConfigResource {
return func(target *map[string]any) error {
err := jsonparser.TryParseFiles(target, filename)
if err != nil {
Expand Down
8 changes: 5 additions & 3 deletions pkg/bliss/datafx/mod.go → pkg/bliss/datafx/mod-fx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
var FxModule = fx.Module( //nolint:gochecknoglobals
"data",
fx.Provide(
New,
FxNew,
),
)

Expand All @@ -17,8 +17,10 @@ type FxResult struct {
DataProvider DataProvider
}

func New() (FxResult, error) {
return FxResult{ //nolint:exhaustruct
func FxNew() (FxResult, error) {
return FxResult{
Out: fx.Out{},

DataProvider: NewDataProvider(),
}, nil
}
8 changes: 5 additions & 3 deletions pkg/bliss/httpfx/mod.go → pkg/bliss/httpfx/mod-fx.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
var FxModule = fx.Module( //nolint:gochecknoglobals
"httpservice",
fx.Provide(
New,
FxNew,
),
fx.Invoke(
registerHooks,
Expand All @@ -29,7 +29,7 @@ type FxResult struct {
Routes Router
}

func New(config *Config) (FxResult, error) {
func FxNew(config *Config) (FxResult, error) {
routes := NewRouter("/")

server := &http.Server{ //nolint:exhaustruct
Expand All @@ -43,7 +43,9 @@ func New(config *Config) (FxResult, error) {
Handler: routes.GetMux(),
}

return FxResult{ //nolint:exhaustruct
return FxResult{
Out: fx.Out{},

HttpService: &HttpService{Server: server, Config: config, Routes: routes},
Routes: routes,
}, nil
Expand Down
87 changes: 87 additions & 0 deletions pkg/bliss/logfx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# bliss/logfx

## Overview

The **logfx** package is a configurable logging solution leverages the `log/slog` of the standard library for structured logging. It includes pretty-printing options and a fx module for the `go.uber.org/fx` framework. The package also has extensive tests to ensure reliability and correctness, covering configuration parsing, handler behavior and the custom error formatting logic.

The documentation below provides an overview of the package, its types, functions, and usage examples. For more detailed information, refer to the source code and tests.


## Configuration

Configuration struct for the logger:

```
type Config struct {
Level string `conf:"LEVEL" default:"INFO"`
PrettyMode bool `conf:"PRETTY" default:"true"`
AddSource bool `conf:"ADD_SOURCE" default:"false"`
}
```


## Fx

The `logfx` package provides an `FxModule` and `GetFxLogger` that can be used to integrate with the `fx` framework.

```go
import (
...
"github.com/eser/go-service/pkg/bliss/logfx"
"go.uber.org/fx"
...
)

app := fx.New(
fx.WithLogger(logfx.GetFxLogger), // handles fx lifecycle events
logfx.FxModule, // registers slog.Logger
...
)

app.Run()
```


## API

### New function

Creates a new `slog.Logger` object based on the provided configuration.

```go
// func New(config *Config) (*slog.Logger, error)

logger, err := logfx.New(config)
```


### NewDefaultLogger function

Creates a new `slog.Logger` object based on the provided configuration and makes it default slog instance.

```go
// func NewDefaultLogger(config *Config) (*slog.Logger, error)

logger, err := logfx.NewDefaultLogger(config)
```


### Colored function

Returns a ANSI-colored string for terminal output.

```go
// func Colored(color Color, message string) string

// available colors:
// ColorReset ColorDimGray
// ColorRed ColorLightRed
// ColorGreen ColorLightGreen
// ColorYellow ColorLightYellow
// ColorBlue ColorLightBlue
// ColorMagenta ColorLightMagenta
// ColorCyan ColorLightCyan
// ColorGray ColorLightGray

fmt.Println(logfx.Colored(logfx.ColorRed, "test"))
```
2 changes: 1 addition & 1 deletion pkg/bliss/logfx/fx-adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type (
}
)

func GetFxLogger(logger *slog.Logger) fxevent.Logger {
func GetFxLogger(logger *slog.Logger) fxevent.Logger { //nolint:ireturn
return &FxLogger{logger}
}

Expand Down
26 changes: 26 additions & 0 deletions pkg/bliss/logfx/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package logfx

import (
"log/slog"
"os"
)

func NewLogger(config *Config) (*slog.Logger, error) {
handler, err := NewHandler(os.Stderr, config)
if err != nil {
return nil, err
}

return slog.New(handler), nil
}

func NewLoggerAsDefault(config *Config) (*slog.Logger, error) {
logger, err := NewLogger(config)
if err != nil {
return nil, err
}

slog.SetDefault(logger)

return logger, nil
}
Loading

0 comments on commit 4768550

Please sign in to comment.