Skip to content

Commit 7f761de

Browse files
committed
refactor(v2): reorganize kubernetes examples and improve documentation
- Reorganize k8s examples into quickstart/, init-container/, production/ - Standardize plugin path to /fluent-bit/plugins/ across all configs - Add educational comments to YAML files explaining k8s concepts - Add CONTRIBUTING.md with development setup and code structure - Update all READMEs with consistent terminology and navigation - Fix log level table in kubernetes README to match source code - Remove legacy daemonset/ and sidecar/ directories
1 parent 36770c8 commit 7f761de

36 files changed

+1705
-789
lines changed

.yamllint.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Local overrides for yamllint
2+
# Extends the base config from yscope-dev-utils
3+
4+
extends: "tools/yscope-dev-utils/exports/lint-configs/.yamllint.yml"
5+
6+
rules:
7+
# Allow document separators (---) for multi-resource Kubernetes manifests
8+
document-start: "disable"

CONTRIBUTING.md

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
# Contributing to Fluent Bit CLP Plugins
2+
3+
Guide for developers who want to contribute to or extend the CLP plugins.
4+
5+
## Table of Contents
6+
7+
- [Development Setup](#development-setup)
8+
- [Building](#building)
9+
- [Testing](#testing)
10+
- [Code Structure](#code-structure)
11+
- [Adding Features](#adding-features)
12+
- [Submitting Changes](#submitting-changes)
13+
14+
---
15+
16+
## Development Setup
17+
18+
### Prerequisites
19+
20+
| Tool | Version | Purpose |
21+
|------|---------|---------|
22+
| [Go](https://go.dev/dl/) | 1.24+ | Plugin compilation |
23+
| [Task](https://taskfile.dev/installation/) | 3.x | Build automation |
24+
| [Docker](https://docs.docker.com/get-docker/) | 20+ | Container builds and testing |
25+
26+
### Clone and Initialize
27+
28+
```shell
29+
# Clone with submodules (required for clp-ffi-go)
30+
git clone --recursive https://github.com/y-scope/fluent-bit-clp.git
31+
cd fluent-bit-clp
32+
33+
# If you already cloned without --recursive:
34+
git submodule update --init --recursive
35+
36+
# Download CLP native libraries
37+
bash third-party/clp-ffi-go/scripts/download-libs.sh
38+
```
39+
40+
### Verify Setup
41+
42+
```shell
43+
# Build both plugins
44+
task build
45+
46+
# Run tests
47+
go test ./...
48+
49+
# Check linting (requires uv for Python tools)
50+
task lint:check
51+
```
52+
53+
---
54+
55+
## Building
56+
57+
### Build Commands
58+
59+
```shell
60+
# Build all plugins
61+
task build
62+
63+
# Build specific plugin
64+
task build:s3v2 # out_clp_s3_v2 (continuous sync)
65+
task build:s3 # out_clp_s3 (batch upload)
66+
```
67+
68+
Output binaries are placed in `pre-built/`:
69+
```
70+
pre-built/
71+
├── out_clp_s3_v2_linux_amd64.so
72+
├── out_clp_s3_v2_linux_arm64.so
73+
├── out_clp_s3_linux_amd64.so
74+
└── out_clp_s3_linux_arm64.so
75+
```
76+
77+
### Docker Builds
78+
79+
```shell
80+
# Build Docker image for out_clp_s3_v2
81+
cd plugins/out_clp_s3_v2
82+
./scripts/build-docker.sh --amd64 # Single architecture
83+
./scripts/build-docker.sh # Both amd64 and arm64
84+
85+
# Build and push to registry
86+
IMAGE_NAME=myregistry/fluent-bit-clp-s3-v2 ./scripts/build-docker.sh --push
87+
```
88+
89+
### Cross-Compilation
90+
91+
The plugins use CGO with the CLP FFI library. Cross-compilation requires the
92+
appropriate native libraries:
93+
94+
```shell
95+
# Libraries are downloaded per-architecture
96+
bash third-party/clp-ffi-go/scripts/download-libs.sh
97+
98+
# Build for specific architecture
99+
GOARCH=arm64 task build:s3v2
100+
```
101+
102+
---
103+
104+
## Testing
105+
106+
### Unit Tests
107+
108+
```shell
109+
# Run all tests
110+
go test ./...
111+
112+
# Run with verbose output
113+
go test -v ./...
114+
115+
# Run specific package tests
116+
go test -v ./plugins/out_clp_s3_v2/internal/...
117+
118+
# Run with coverage
119+
go test -cover ./...
120+
```
121+
122+
### Integration Testing with Docker Compose
123+
124+
The fastest way to test changes end-to-end:
125+
126+
```shell
127+
cd plugins/out_clp_s3_v2/examples/docker-compose
128+
129+
# Start services (builds plugin from source)
130+
docker compose up --build
131+
132+
# In another terminal, check logs are being uploaded
133+
docker exec docker-compose-minio-1 mc ls local/logs/
134+
135+
# View MinIO Console at http://localhost:9001 (minioadmin/minioadmin)
136+
137+
# Cleanup
138+
docker compose down -v
139+
```
140+
141+
### Manual Testing with Fluent Bit
142+
143+
```shell
144+
# Build the plugin
145+
task build:s3v2
146+
147+
# Run Fluent Bit with your config
148+
fluent-bit -c /path/to/fluent-bit.yaml
149+
150+
# Or use the example config
151+
cd plugins/out_clp_s3_v2
152+
fluent-bit -c fluent-bit.yaml
153+
```
154+
155+
---
156+
157+
## Code Structure
158+
159+
```
160+
fluent-bit-clp/
161+
├── internal/ # Shared code between plugins
162+
│ ├── decoder/ # Fluent Bit record decoding
163+
│ ├── irzstd/ # CLP IR + Zstd compression writers
164+
│ └── outctx/ # Output context management
165+
166+
├── plugins/
167+
│ ├── out_clp_s3_v2/ # Continuous sync plugin
168+
│ │ ├── out_clp_s3_v2.go # Plugin entry points (register, flush, exit)
169+
│ │ ├── internal/
170+
│ │ │ ├── context.go # Plugin instance state
171+
│ │ │ ├── flush_manager.go # Dual-timer flush logic
172+
│ │ │ ├── ingestion.go # Log record processing
173+
│ │ │ └── s3.go # S3 upload operations
174+
│ │ ├── examples/ # Docker/Kubernetes examples
175+
│ │ └── Dockerfile
176+
│ │
177+
│ └── out_clp_s3/ # Batch upload plugin
178+
│ ├── out_clp_s3.go
179+
│ ├── internal/
180+
│ │ ├── flush/ # Size-based flush logic
181+
│ │ └── recovery/ # Crash recovery
182+
│ └── examples/
183+
184+
├── third-party/
185+
│ └── clp-ffi-go/ # CLP FFI Go bindings (submodule)
186+
187+
└── taskfiles/ # Task build definitions
188+
├── build.yaml
189+
└── lint.yaml
190+
```
191+
192+
### Key Components
193+
194+
#### Fluent Bit Plugin Interface
195+
196+
Plugins implement the [Fluent Bit Go interface](https://docs.fluentbit.io/manual/development/golang-output-plugins):
197+
198+
```go
199+
// out_clp_s3_v2.go
200+
201+
//export FLBPluginRegister
202+
func FLBPluginRegister(def unsafe.Pointer) int {
203+
// Called once at startup to register the plugin
204+
}
205+
206+
//export FLBPluginInit
207+
func FLBPluginInit(plugin unsafe.Pointer) int {
208+
// Called once per output instance to initialize
209+
}
210+
211+
//export FLBPluginFlush
212+
func FLBPluginFlush(data unsafe.Pointer, length C.int, tag *C.char) int {
213+
// Called when Fluent Bit has records to flush
214+
}
215+
216+
//export FLBPluginExit
217+
func FLBPluginExit() int {
218+
// Called at shutdown for cleanup
219+
}
220+
```
221+
222+
#### CLP IR Compression
223+
224+
The `internal/irzstd` package handles CLP compression:
225+
226+
```go
227+
// Create a writer that outputs CLP IR compressed with Zstd
228+
writer := irzstd.NewDiskWriter("/tmp/output.clp.zst")
229+
defer writer.Close()
230+
231+
// Write log records
232+
writer.Write(timestamp, message)
233+
```
234+
235+
#### Dual-Timer Flush Strategy (v2)
236+
237+
The `flush_manager.go` implements the dual-timer strategy:
238+
239+
- **Soft timer**: Resets on every new log, triggers upload during quiet periods
240+
- **Hard timer**: Never resets (only moves earlier), guarantees max latency
241+
242+
```go
243+
// When a log arrives, update timers based on its level
244+
manager.UpdateTimers(logLevel)
245+
246+
// Check if flush is needed
247+
if manager.ShouldFlush() {
248+
// Upload to S3
249+
}
250+
```
251+
252+
---
253+
254+
## Adding Features
255+
256+
### Adding a New Configuration Option
257+
258+
1. **Define the option** in the plugin's config parsing:
259+
260+
```go
261+
// out_clp_s3_v2.go - in FLBPluginInit
262+
myOption := output.FLBPluginConfigKey(plugin, "my_option")
263+
```
264+
265+
2. **Store in context** (`internal/context.go`):
266+
267+
```go
268+
type Context struct {
269+
// ...
270+
MyOption string
271+
}
272+
```
273+
274+
3. **Document** in the plugin's README.md
275+
276+
4. **Add to examples** in `examples/` directories
277+
278+
### Adding a New Log Level
279+
280+
Edit `logLevelMap` in `out_clp_s3_v2.go`:
281+
282+
```go
283+
var logLevelMap = map[string]int{
284+
// Add new mappings
285+
"verbose": LogLevelDebug,
286+
"VERBOSE": LogLevelDebug,
287+
}
288+
```
289+
290+
### Adding Tests
291+
292+
Create `*_test.go` files alongside the code:
293+
294+
```go
295+
// internal/flush_manager_test.go
296+
func TestFlushManager_UpdateTimers(t *testing.T) {
297+
manager := NewFlushManager(config)
298+
manager.UpdateTimers(LogLevelError)
299+
300+
if !manager.ShouldFlush() {
301+
t.Error("Expected flush after error log")
302+
}
303+
}
304+
```
305+
306+
---
307+
308+
## Linting
309+
310+
```shell
311+
# Check for issues
312+
task lint:check
313+
314+
# Auto-fix issues (Go formatting)
315+
task lint:fix
316+
```
317+
318+
The project uses:
319+
- [golangci-lint](https://golangci-lint.run/) for Go (config: `.golangci.yaml`)
320+
- [yamllint](https://yamllint.readthedocs.io/) for YAML (config: `.yamllint.yml`)
321+
322+
---
323+
324+
## Submitting Changes
325+
326+
### Commit Messages
327+
328+
Use [Conventional Commits](https://www.conventionalcommits.org/):
329+
330+
```
331+
feat(v2): add support for custom S3 prefix
332+
fix(v2): handle empty log records gracefully
333+
docs: update Kubernetes examples
334+
test(v2): add flush manager unit tests
335+
refactor: extract common S3 upload logic
336+
```
337+
338+
### Pull Request Process
339+
340+
1. Fork the repository
341+
2. Create a feature branch: `git checkout -b feat/my-feature`
342+
3. Make changes and add tests
343+
4. Run linting: `task lint:check`
344+
5. Run tests: `go test ./...`
345+
6. Commit with conventional commit message
346+
7. Push and open a PR against `main`
347+
348+
### CI Checks
349+
350+
PRs must pass:
351+
- Go build (amd64 and arm64)
352+
- Unit tests
353+
- Linting (golangci-lint, yamllint)
354+
355+
---
356+
357+
## Resources
358+
359+
- [Fluent Bit Go Plugin Development](https://docs.fluentbit.io/manual/development/golang-output-plugins)
360+
- [CLP Documentation](https://docs.yscope.com/clp/main/)
361+
- [CLP FFI Go Bindings](https://github.com/y-scope/clp-ffi-go)
362+
- [Task Documentation](https://taskfile.dev/)

0 commit comments

Comments
 (0)