diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9a2893..3e89edd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,19 +1,21 @@ name: CI/CD Pipeline on: - push: - branches: [ main, develop ] pull_request: + types: [opened, synchronize, reopened, ready_for_review] branches: [ main, develop ] - release: - types: [ published ] env: GO_VERSION: '1.24' +defaults: + run: + shell: bash + jobs: - # Code quality and linting + # Code quality and linting (тільки на PR, не на драфт) lint: + if: ${{ !github.event.pull_request.draft }} name: Lint Code runs-on: ubuntu-latest steps: @@ -42,29 +44,31 @@ jobs: - name: Run golint run: golint $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') - - name: Run gofmt + - name: Install gofumpt + run: go install mvdan.cc/gofumpt@latest + + - name: Run gofumpt run: | - if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then - gofmt -s -l . - echo "Code is not formatted properly" + CHANGED=$(gofumpt -l . | wc -l | tr -d ' ') + if [ "$CHANGED" != "0" ]; then + echo "Code is not formatted properly (gofumpt):" + gofumpt -l . exit 1 fi - # Test matrix across multiple Go versions and OS + # Test matrix across multiple Go versions and OS (тільки на PR, не на драфт) test: + if: ${{ !github.event.pull_request.draft }} name: Test runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest] go-version: ['1.22', '1.23', '1.24'] exclude: - # Exclude some combinations to speed up CI - os: windows-latest go-version: '1.22' - - os: macos-latest - go-version: '1.22' steps: - uses: actions/checkout@v4 @@ -90,16 +94,17 @@ jobs: - name: Run tests run: go test -v -race $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') - - name: Run tests with timeout + - name: Run tests (race + timeout) run: go test -v -race -timeout=5m $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') - # Build test + # Build (тільки на PR, не на драфт) build: + if: ${{ !github.event.pull_request.draft }} name: Build runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v4 @@ -112,8 +117,9 @@ jobs: - name: Build run: go build -v $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') - # Dependency check + # Dependency check (тільки на PR, не на драфт) dependency-check: + if: ${{ !github.event.pull_request.draft }} name: Dependency Check runs-on: ubuntu-latest steps: @@ -124,18 +130,36 @@ jobs: with: go-version: ${{ env.GO_VERSION }} - - name: Check for vulnerabilities - run: | - go install golang.org/x/vuln/cmd/govulncheck@latest - govulncheck $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + + - name: Run govulncheck + run: govulncheck $(go list ./... | grep -v '^github.com/sarff/iSlogger/examples') - name: Verify no external dependencies run: | - # Ensure we only use standard library - DEPS=$(go list -m all | grep -v "github.com/sarff/iSlogger" | grep -v "^golang.org/toolchain" | wc -l) - if [ $DEPS -gt 1 ]; then - echo "❌ Found external dependencies:" - go list -m all + set -euo pipefail + echo "PWD: $(pwd)" + echo "GOMOD: $(go env GOMOD)" + + # Поточний модуль (без хардкоду) + MOD=$(go list -m -f '{{.Path}}') + echo "Module: ${MOD}" + + echo "All modules (for debug):" + go list -m -f '{{.Path}} {{.Version}}' all + + # Рахуємо ЗОВНІШНІ модулі: відкидаємо свій і toolchain + DEPS=$(go list -m -f '{{.Path}}' all \ + | awk -v mod="$MOD" '$1!=mod && $1!="golang.org/toolchain"' \ + | wc -l | tr -d ' ') + + echo "External module count: ${DEPS}" + if [ "$DEPS" -gt 0 ]; then + echo "❌ Found external dependencies (excluding your module and toolchain):" + go list -m -f '{{.Path}} {{.Version}}' all \ + | awk -v mod="$MOD" '$1!=mod && $1!="golang.org/toolchain"' exit 1 fi - echo "✅ No external dependencies found" + + echo "✅ No external dependencies found" \ No newline at end of file diff --git a/TODO.md b/TODO.md index 7bab974..700a29b 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,7 @@ - [ ] Support YAML, TOML formats - [ ] Size-based log rotation - [ ] Automatic log compression (gzip) +- [X] Output console option ## ⚡️ Performance - [X] Buffered writes (batching) diff --git a/examples/console/main.go b/examples/console/main.go new file mode 100644 index 0000000..3a46d65 --- /dev/null +++ b/examples/console/main.go @@ -0,0 +1,80 @@ +package main + +import ( + "time" + + "github.com/sarff/iSlogger" +) + +func main() { + // Example 1: Default behavior (console output enabled) + config1 := iSlogger.DefaultConfig(). + WithAppName("console-app"). + WithDebug(true). + WithLogDir("logs") + + logger1, err := iSlogger.New(config1) + if err != nil { + panic(err) + } + defer logger1.Close() + + logger1.Info("This message appears in both console and file (default behavior)") + logger1.Warn("Warning: appears in console and both files") + logger1.Error("Error: appears in console and both files") + + // Example 2: Disable console output (file only) + config2 := iSlogger.DefaultConfig(). + WithAppName("file-only-app"). + WithDebug(true). + WithLogDir("logs"). + WithConsoleOutput(false) + + logger2, err := iSlogger.New(config2) + if err != nil { + panic(err) + } + defer logger2.Close() + + logger2.Info("This message only appears in files, not in console") + logger2.Warn("File-only warning message") + logger2.Error("File-only error message") + + // Example 3: Explicitly enable console output + config3 := iSlogger.DefaultConfig(). + WithAppName("explicit-console"). + WithDebug(true). + WithLogDir("logs"). + WithConsoleOutput(true) + + logger3, err := iSlogger.New(config3) + if err != nil { + panic(err) + } + defer logger3.Close() + + logger3.Info("Explicitly enabled console output") + logger3.Debug("Debug message with console output") + + // Example 4: JSON format with console output + config4 := iSlogger.DefaultConfig(). + WithAppName("json-console"). + WithDebug(true). + WithLogDir("logs"). + WithJSONFormat(true). + WithConsoleOutput(true) + + logger4, err := iSlogger.New(config4) + if err != nil { + panic(err) + } + defer logger4.Close() + + logger4.Info("JSON formatted message in both console and file", + "user_id", 123, + "action", "login", + "timestamp", time.Now(), + ) + + time.Sleep(time.Second) // Allow time for async operations +}