# Go

> Use the justlog3 Go module: loggers, options, cloud sending and why Shutdown() matters.

The `justlog3` Go module writes log lines to a file from a background goroutine and, once you set an API token, sends them to JustLog3 Cloud. It uses only the standard library.

## Install

```bash
go get github.com/OAzizjon/justlog3/go
```

Go 1.23 or newer. The package name is `justlog3`. Reference: [pkg.go.dev](https://pkg.go.dev/github.com/OAzizjon/justlog3/go).

## Log to a file and the cloud

```go
package main

import (
	"log"
	"os"

	justlog3 "github.com/OAzizjon/justlog3/go"
)

func main() {
	err := justlog3.SetAPIToken(os.Getenv("JUSTLOG3_TOKEN"),
		justlog3.WithURL("https://jl3-cloud.site/api/logs/"))
	if err != nil {
		log.Fatal(err)
	}
	defer justlog3.Shutdown() // flushes files and sends what is left

	logger, err := justlog3.NewLogger("app.log")
	if err != nil {
		log.Fatal(err)
	}
	logger.Log("Hi...")
	logger.Log("There is some error!", justlog3.Red())
	logger.Log("OK", justlog3.Green())
	logger.Log("There is critical error!", justlog3.Red(), justlog3.Prefix("CRITICAL!!"))
}
```

## Always call Shutdown

Go has no exit hook. Without `justlog3.Shutdown()` (or `logger.Flush()` / `logger.Close()`) the last buffered lines are lost. `log.Fatal` and `os.Exit` skip deferred calls, so flush before them.

## Levels

```go
logger, _ := justlog3.NewBasicLogger("app.log", justlog3.WithConsoleLevel("INFO"))
logger.Debug("only in the file and cloud")
logger.Info("started")
logger.Successf("processed %d items", 42)
logger.Error("payment failed")
```

`WithConsoleLevel` only filters the console. Every level has an `f` variant (`Infof`, `Errorf`, ...).

## How cloud sending works

- Each logger keeps a cloud buffer of up to 10,000 lines; the oldest lines are dropped on overflow.
- Batches go out when `WithCloudCycles(n)` lines are waiting (default 75) or every flush interval (default 5 s), at most `WithMaxBatch(n)` lines (default 100) and 512 KB of text each. Bodies from 1 KB are gzip-compressed.
- No answer or HTTP 5xx: the batch is resent unchanged with the same `X-JustLog-Seq`, so the server stores it once.
- HTTP 429: nothing is sent until `Retry-After`. HTTP 413: later batches carry half as many lines.
- HTTP 401 / 403: cloud sending stops and files keep being written. Call `SetAPIToken` again to resume.

Cloud options: `WithURL(url)`, `WithFlushInterval(d)`, `WithTimeout(d)`, `WithMaxBatch(n)`.

## Logger options

| Option | Default | Meaning |
|---|---|---|
| `WithTime(bool)` | `true` | timestamp in every line |
| `WithFilemode("a" or "w")` | `"a"` | `"w"` truncates the file once on creation |
| `WithCycles(n)` | `50` | lines per disk write |
| `WithCloudCycles(n)` | `75` | waiting lines that wake the cloud sender |
| `WithConsoleLevel(level)` | `"DEBUG"` | `BasicLogger` only |

The file stays open and is reopened if it is renamed or deleted, so log rotation works, on Windows too.
