Skip to content

Commit

Permalink
PA-24295 Inssqs Implementation (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafet authored Dec 26, 2023
1 parent d127030 commit e06cea1
Show file tree
Hide file tree
Showing 18 changed files with 1,645 additions and 45 deletions.
36 changes: 27 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,37 @@ require (
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/Jamil-Najafov/go-aws-ssm v0.9.0
github.com/aws/aws-sdk-go v1.44.3
github.com/aws/aws-sdk-go-v2 v1.23.1
github.com/aws/aws-sdk-go-v2/config v1.25.4
github.com/aws/aws-sdk-go-v2/service/sqs v1.28.2
github.com/aws/smithy-go v1.17.0
github.com/getsentry/sentry-go v0.13.0
github.com/go-redis/redis v6.15.9+incompatible
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.1
github.com/jellydator/ttlcache/v3 v3.0.0
github.com/pkg/errors v0.9.1
github.com/slok/goresilience v0.2.0
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.1
go.uber.org/mock v0.3.0
go.uber.org/zap v1.26.0
gorm.io/driver/mysql v1.3.4
gorm.io/gorm v1.23.7
)

require (
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.16.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand All @@ -31,13 +48,14 @@ require (
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.19.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 // indirect
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
github.com/prometheus/client_golang v1.11.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/sys v0.14.0 // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
159 changes: 140 additions & 19 deletions go.sum

Large diffs are not rendered by default.

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

import "encoding/json"

func CreateBatches[T any](v []T, recordLimit int, byteLimit int) ([][]T, error) {
batches := make([][]T, 0)
buffer := make([]T, 0)
bufferSize := 0

for _, record := range v {
js, jsErr := json.Marshal(record)
if jsErr != nil {
return nil, jsErr
}

recordSize := len(js)
sizeExceeds := bufferSize+recordSize > byteLimit
bufferFull := len(buffer) == recordLimit

if len(buffer) > 0 && (bufferFull || sizeExceeds) {
batches = append(batches, buffer)
buffer = make([]T, 0)
bufferSize = 0
}

buffer = append(buffer, record)
bufferSize += recordSize
}

if len(buffer) > 0 {
batches = append(batches, buffer)
}

return batches, nil
}

func Contains[T comparable](v []T, e T) bool {
for _, a := range v {
if a == e {
return true
}
}
return false
}

func MapToValueSlice[K comparable, V any](m map[K]V) []V {
v := make([]V, 0, len(m))
for _, value := range m {
v = append(v, value)
}
return v
}
108 changes: 108 additions & 0 deletions insdash/insdash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package insdash

import (
"github.com/stretchr/testify/assert"
"testing"
)

const kb64 = 64 * 1024

func Test_createBatches(t *testing.T) {
t.Run("should_return_empty_batches_when_empty", func(t *testing.T) {
batches, err := CreateBatches([]string{}, 10, kb64)

assert.Nil(t, err, "err should be nil")
assert.Equal(t, 0, len(batches), "batches length should be equal to 0")
})

t.Run("should_return_batches_when_not_empty", func(t *testing.T) {
batches, err := CreateBatches([]string{"test"}, 10, kb64)

assert.Nil(t, err, "err should be nil")
assert.Equal(t, 1, len(batches), "batches length should be equal to 1")
})

t.Run("should_return_batches_by_record_limit", func(t *testing.T) {
batches, err := CreateBatches([]string{"test", "test"}, 10, kb64)

assert.Nil(t, err, "err should be nil")
assert.Equal(t, 2, len(batches), "batches length should be equal to 2")
})

t.Run("should_return_batches_by_byte_limit", func(t *testing.T) {
batches, err := CreateBatches([]string{createString(kb64), createString(kb64)}, 10, kb64)

assert.Nil(t, err, "err should be nil")
assert.Equal(t, 2, len(batches), "batches length should be equal to 2")
})
}

func createString(byteSize int) string {
var str string
for i := 0; i < byteSize; i++ {
str += "a"
}
return str
}

func TestMapToValueSlice(t *testing.T) {
t.Run("should_return_empty_slice_when_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]string{})
assert.Equal(t, 0, len(s), "slice length should be equal to 0")
assert.Equal(t, []string{}, s, "slice value should be equal to []string{}")
})

t.Run("should_return_string_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]string{"test": "test"})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, "test", s[0], "slice value should be equal to \"test\"")
})

t.Run("should_return_int_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]int{"test": 1})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, 1, s[0], "slice value should be equal to 1")
})

t.Run("should_return_bool_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]bool{"test": true})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, true, s[0], "slice value should be equal to true")
})

t.Run("should_return_float_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]float64{"test": 1.0})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, 1.0, s[0], "slice value should be equal to 1.0")
})

t.Run("should_return_struct_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]struct{}{"test": {}})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, struct{}{}, s[0], "slice value should be equal to struct{}{}")
})

t.Run("should_return_interface_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]interface{}{"test": 1})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, 1, s[0], "slice value should be equal to 1")
})

t.Run("should_return_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string][]string{"test": {"test"}})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, []string{"test"}, s[0], "slice value should be equal to []string{\"test\"}")
})

t.Run("should_return_map_slice_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]map[string]string{"test": {"test": "test"}})
assert.Equal(t, 1, len(s), "slice length should be equal to 1")
assert.Equal(t, map[string]string{"test": "test"}, s[0], "slice value should be equal to map[string]string{\"test\": \"test\"}")
})

t.Run("should_return_slice_with_multiple_values_when_not_empty", func(t *testing.T) {
s := MapToValueSlice(map[string]string{"test": "test", "test2": "test2"})
assert.Equal(t, 2, len(s), "slice length should be equal to 2")
assert.Equal(t, []string{"test", "test2"}, s, "slice value should be equal to []string{\"test\", \"test2\"}")
})
}
103 changes: 103 additions & 0 deletions inslogger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Inslogger

Inslogger is a logging package designed to provide flexible and comprehensive logging capabilities in Go applications.

## Features

- **Multi-Level Logging:** Supports logging at various levels including Debug, Info, Warn, Error, and Fatal.
- **Error Handling:** Provides methods to log errors with different formatting options.

## Installation

```bash
go get github.com/yourusername/inslogger
```

## Usage

```go
import "github.com/yourusername/inslogger"

// Initialize a logger
logger := inslogger.NewLogger(inslogger.Debug)

// Log an error
err := someFunction()
if err != nil {
logger.Error(err)
}

// Log a message
logger.Log("This is a log message")

// Set log level
logger.SetLevel(inslogger.Info)
```

## Interface
The package provides an Interface that exposes various logging methods:
```go
type Interface interface {
LogMultiple(errs []error)
Log(i interface{})
Logf(format string, args ...interface{})
Warn(i interface{})
Warnf(format string, args ...interface{})
Error(err error)
Errorf(format string, args ...interface{})
Debug(i interface{})
Debugf(format string, args ...interface{})
Fatal(err error)
Fatalf(format string, args ...interface{})
initLogger() error
SetLevel(level LogLevel)
}
```


# Configuration

The `inslogger` package offers configuration options to customize logging behavior.

## Log Levels

The package supports the following log levels:

- `DEBUG`
- `INFO`
- `WARN`
- `ERROR`
- `FATAL`

## Setting Log Level

The default log level is `INFO`. To set a different log level:

```go
logger := inslogger.NewLogger(inslogger.Debug)
```

## Example
```go
// Initialize a logger with Debug level
logger := inslogger.NewLogger(inslogger.Debug)

// Log an error
err := someFunction()
if err != nil {
logger.Error(err)
}

// Log a debug message
logger.Debugf("Debug message with arguments: %s", arg)

// Change log level to Info
logger.SetLevel(inslogger.Info)

// Log an informational message
logger.Infof("Informational message")

```
## Contribution
Feel free to contribute by forking this repository and creating pull requests. Please ensure to adhere to the existing code style and conventions.

Loading

0 comments on commit e06cea1

Please sign in to comment.