From 1f8c2862f2e620f4c548b3c57d95cf87711fd0dd Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Thu, 29 May 2025 17:24:03 +0800
Subject: [PATCH 01/10] chore(fluentbit): bump version to 4.0.2

---
 Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Dockerfile b/Dockerfile
index b788435..ee67f4d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -17,7 +17,7 @@ FROM registry.drycc.cc/drycc/base:${CODENAME}
 
 ENV DRYCC_UID=1001 \
   DRYCC_GID=1001 \
-  FLUENT_BIT_VERSION=4.0.0 \
+  FLUENT_BIT_VERSION=4.0.2 \
   DRYCC_HOME_DIR=/opt/drycc \
   FLUENT_BIT_PLUGINS_PATH=${DRYCC_HOME_DIR}/fluent-bit/plugins
   

From 59419c83f095c137342a1a03186948e8d8f1d9fd Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Fri, 4 Jul 2025 15:50:55 +0800
Subject: [PATCH 02/10] chore(fluentbit): use quickwit replace redis stream

---
 Dockerfile                                    |  12 +-
 Makefile                                      |   2 -
 README.md                                     |  11 +-
 charts/fluentbit/Chart.lock                   |   6 +
 charts/fluentbit/Chart.yaml                   |   4 +
 charts/fluentbit/charts/common-1.1.4.tgz      | Bin 0 -> 13755 bytes
 charts/fluentbit/templates/_helpers.tpl       |  17 +-
 ...errole.yaml => fluentbit-clusterrole.yaml} |   4 +-
 ...yaml => fluentbit-clusterrolebinding.yaml} |   8 +-
 ...onfigmap.yaml => fluentbit-configmap.yaml} |   2 +-
 ...tbit-daemon.yaml => fluentbit-daemon.yaml} |  28 +--
 ...nt.yaml => fluentbit-service-account.yaml} |   2 +-
 .../logger-fluentbit-secret-creds.yaml        |  10 -
 charts/fluentbit/values.yaml                  |  36 ++--
 go.mod                                        |  15 +-
 go.sum                                        |  65 ++++---
 plugin/out_drycc.go                           | 156 ---------------
 plugin/out_quickwit.go                        | 184 ++++++++++++++++++
 .../fluent-bit/templates/fluent-bit.conf      |  35 ----
 .../drycc/fluent-bit/templates/parsers.conf   |  15 --
 .../drycc/fluent-bit/templates/plugins.conf   |   2 -
 rootfs/usr/local/bin/boot                     |  20 --
 22 files changed, 294 insertions(+), 340 deletions(-)
 create mode 100644 charts/fluentbit/Chart.lock
 create mode 100644 charts/fluentbit/charts/common-1.1.4.tgz
 rename charts/fluentbit/templates/{logger-fluentbit-clusterrole.yaml => fluentbit-clusterrole.yaml} (64%)
 rename charts/fluentbit/templates/{logger-fluentbit-clusterrolebinding.yaml => fluentbit-clusterrolebinding.yaml} (53%)
 rename charts/fluentbit/templates/{logger-fluentbit-configmap.yaml => fluentbit-configmap.yaml} (94%)
 rename charts/fluentbit/templates/{logger-fluentbit-daemon.yaml => fluentbit-daemon.yaml} (72%)
 rename charts/fluentbit/templates/{logger-fluentbit-service-account.yaml => fluentbit-service-account.yaml} (71%)
 delete mode 100644 charts/fluentbit/templates/logger-fluentbit-secret-creds.yaml
 delete mode 100644 plugin/out_drycc.go
 create mode 100644 plugin/out_quickwit.go
 delete mode 100644 rootfs/opt/drycc/fluent-bit/templates/fluent-bit.conf
 delete mode 100644 rootfs/opt/drycc/fluent-bit/templates/parsers.conf
 delete mode 100644 rootfs/opt/drycc/fluent-bit/templates/plugins.conf
 delete mode 100755 rootfs/usr/local/bin/boot

diff --git a/Dockerfile b/Dockerfile
index ee67f4d..cbe91c5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ RUN export GO111MODULE=on \
   && init-stack go mod vendor \
   && init-stack go build \
     -ldflags "-X main.Revision=${BUILD_TAG} -X main.BuildDate=${BUILD_DATE}" \
-    -buildmode=c-shared -o /var/lib/fluent-bit/out_drycc.so plugin/out_drycc.go
+    -buildmode=c-shared -o /var/lib/fluent-bit/out_quickwit.so plugin/out_quickwit.go
 
 
 FROM registry.drycc.cc/drycc/base:${CODENAME}
@@ -18,20 +18,14 @@ FROM registry.drycc.cc/drycc/base:${CODENAME}
 ENV DRYCC_UID=1001 \
   DRYCC_GID=1001 \
   FLUENT_BIT_VERSION=4.0.2 \
-  DRYCC_HOME_DIR=/opt/drycc \
-  FLUENT_BIT_PLUGINS_PATH=${DRYCC_HOME_DIR}/fluent-bit/plugins
+  DRYCC_HOME_DIR=/opt/drycc
   
 RUN groupadd drycc --gid ${DRYCC_GID} \
   && useradd drycc -u ${DRYCC_UID} -g ${DRYCC_GID} -s /bin/bash -m -d ${DRYCC_HOME_DIR}
 
 RUN install-stack fluent-bit ${FLUENT_BIT_VERSION} \
-  && mkdir -p ${FLUENT_BIT_PLUGINS_PATH} \
   && chown -R ${DRYCC_UID}:${DRYCC_GID} ${DRYCC_HOME_DIR}/fluent-bit
 
-COPY --chown=${DRYCC_UID}:${DRYCC_GID} --from=build /var/lib/fluent-bit/out_drycc.so ${FLUENT_BIT_PLUGINS_PATH}
-
-ADD rootfs /
+COPY --chown=${DRYCC_UID}:${DRYCC_GID} --from=build /var/lib/fluent-bit/out_quickwit.so /opt/drycc/fluent-bit/lib
 
 USER ${DRYCC_UID}
-
-CMD ["/usr/local/bin/boot"]
diff --git a/Makefile b/Makefile
index 36af89d..3ccbdc4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,6 @@
 SHORT_NAME ?= fluentbit
 BUILD_TAG ?= git-$(shell git rev-parse --short HEAD)
 BUILD_DATE := $(shell date --rfc-3339=ns | tr " " T)
-SHELL_SCRIPTS = $(wildcard rootfs/usr/local/bin/*)
 DRYCC_REGISTRY ?= ${DEV_REGISTRY}
 IMAGE_PREFIX ?= drycc
 PLATFORM ?= linux/amd64,linux/arm64
@@ -42,7 +41,6 @@ style-check:
 	gofmt -l -w -s plugin
 	go vet plugin
 	lint
-	shellcheck $(SHELL_SCRIPTS)
 
 clean:
 	rm -rf _dist
diff --git a/README.md b/README.md
index 649a1ed..c7f0aff 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ a lightweight, [Heroku-inspired](http://heroku.com) workflow.
 ## About
 This is an debian based image for running [fluentbit](http://fluentbit.io). It is built for the purpose of running on a kubernetes cluster.
 
-This image is in with [workflow](https://github.com/drycc/workflow) v2 to send all log data to the [logger](https://github.com/drycc/logger) component.
+This image is in with [workflow](https://github.com/drycc/workflow) v2 to send all log data to the [quickwit](https://github.com/drycc/quickwit) component.
 
 
 ## Helm Chart
@@ -23,12 +23,3 @@ Once you have installed the Helm client, you can deploy a Fluentbit Chart into a
 ```sh
 helm show values oci://registry.drycc.cc/charts-testing/fluentbit
 ```
-
-## Plugins
-
-Fluent Bit currently supports integration of Golang plugins built as shared objects for output plugins only. The interface for the Golang plugins is currently under development but is functional.
-
-### Drycc Output
-Drycc output is a custom fluentbit plugin that was written to forward data directly to drycc components while filtering out data that we did not care about. We have 2 pieces of information we care about currently.
-
-Logs from applications that are written to stdout within the container and the controller logs that represent actions against those applications. These logs are sent to an internal messaging system ([VALKEY](https://valkey.io)) on a configurable topic. The logger component then reads those messages and stores the data in an ring buffer.
diff --git a/charts/fluentbit/Chart.lock b/charts/fluentbit/Chart.lock
new file mode 100644
index 0000000..70fffe4
--- /dev/null
+++ b/charts/fluentbit/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: common
+  repository: oci://registry.drycc.cc/charts
+  version: 1.1.4
+digest: sha256:d101f4d0e796524281dec60d636aa301ba92a42d7c0468aa5072e721bdd48a6b
+generated: "2025-07-01T16:47:29.929607311+08:00"
diff --git a/charts/fluentbit/Chart.yaml b/charts/fluentbit/Chart.yaml
index 3f634f5..148e464 100644
--- a/charts/fluentbit/Chart.yaml
+++ b/charts/fluentbit/Chart.yaml
@@ -3,6 +3,10 @@ home: https://github.com/drycc/fluentbit
 apiVersion: v2
 appVersion: 1.0.0
 version: v1.0.0
+dependencies:
+  - name: common
+    repository: oci://registry.drycc.cc/charts
+    version: ~1.1.2
 description: Log shipping mechanism for Drycc Workflow.
 maintainers:
   - name: Drycc Team
diff --git a/charts/fluentbit/charts/common-1.1.4.tgz b/charts/fluentbit/charts/common-1.1.4.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..4794547e490ed3affe3fdc3e27b12098163657bb
GIT binary patch
diff --git a/charts/fluentbit/templates/_helpers.tpl b/charts/fluentbit/templates/_helpers.tpl
index 9d2d805..250674d 100644
--- a/charts/fluentbit/templates/_helpers.tpl
+++ b/charts/fluentbit/templates/_helpers.tpl
@@ -1,19 +1,8 @@
 {{/* Generate fluentbit envs */}}
 {{- define "fluentbit.envs" }}
 env:
-{{- if (.Values.valkeyUrl) }}
-- name: DRYCC_VALKEY_URL
+- name: NAMESPACE
   valueFrom:
-    secretKeyRef:
-      name: logger-fluentbit-creds
-      key: valkey-url
-{{- else if .Values.valkey.enabled }}
-- name: VALKEY_PASSWORD
-  valueFrom:
-    secretKeyRef:
-      name: valkey-creds
-      key: password
-- name: DRYCC_VALKEY_URL
-  value: "redis://:$(VALKEY_PASSWORD)@drycc-valkey.{{.Release.Namespace}}.svc.{{.Values.global.clusterDomain}}:16379/2"
-{{- end }}
+    fieldRef:
+      fieldPath: metadata.namespace
 {{- end }}
\ No newline at end of file
diff --git a/charts/fluentbit/templates/logger-fluentbit-clusterrole.yaml b/charts/fluentbit/templates/fluentbit-clusterrole.yaml
similarity index 64%
rename from charts/fluentbit/templates/logger-fluentbit-clusterrole.yaml
rename to charts/fluentbit/templates/fluentbit-clusterrole.yaml
index d6b0388..9c95190 100644
--- a/charts/fluentbit/templates/logger-fluentbit-clusterrole.yaml
+++ b/charts/fluentbit/templates/fluentbit-clusterrole.yaml
@@ -1,9 +1,9 @@
 kind: ClusterRole
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
-  name: {{ printf "%s:drycc-logger-fluentbit" .Release.Namespace | quote }}
+  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
   labels:
-    app: drycc-logger-fluentbit
+    app: drycc-fluentbit
     heritage: drycc
 rules:
 - apiGroups: [""]
diff --git a/charts/fluentbit/templates/logger-fluentbit-clusterrolebinding.yaml b/charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml
similarity index 53%
rename from charts/fluentbit/templates/logger-fluentbit-clusterrolebinding.yaml
rename to charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml
index e05225b..f25d985 100644
--- a/charts/fluentbit/templates/logger-fluentbit-clusterrolebinding.yaml
+++ b/charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml
@@ -1,15 +1,15 @@
 kind: ClusterRoleBinding
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
-  name: {{ printf "%s:drycc-logger-fluentbit" .Release.Namespace | quote }}
+  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
   labels:
-    app: drycc-logger-fluentbit
+    app: drycc-fluentbit
     heritage: drycc
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
-  name: {{ printf "%s:drycc-logger-fluentbit" .Release.Namespace | quote }}
+  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
 subjects:
 - kind: ServiceAccount
-  name: drycc-logger-fluentbit
+  name: drycc-fluentbit
   namespace: {{ .Release.Namespace }}
diff --git a/charts/fluentbit/templates/logger-fluentbit-configmap.yaml b/charts/fluentbit/templates/fluentbit-configmap.yaml
similarity index 94%
rename from charts/fluentbit/templates/logger-fluentbit-configmap.yaml
rename to charts/fluentbit/templates/fluentbit-configmap.yaml
index 3de9e14..5915f70 100644
--- a/charts/fluentbit/templates/logger-fluentbit-configmap.yaml
+++ b/charts/fluentbit/templates/fluentbit-configmap.yaml
@@ -1,7 +1,7 @@
 apiVersion: v1
 kind: ConfigMap
 metadata:
-  name: logger-fluentbit-config
+  name: fluentbit-config
   namespace: {{ .Release.Namespace }}
   labels:
     heritage: drycc
diff --git a/charts/fluentbit/templates/logger-fluentbit-daemon.yaml b/charts/fluentbit/templates/fluentbit-daemon.yaml
similarity index 72%
rename from charts/fluentbit/templates/logger-fluentbit-daemon.yaml
rename to charts/fluentbit/templates/fluentbit-daemon.yaml
index b8bb0f0..892091d 100644
--- a/charts/fluentbit/templates/logger-fluentbit-daemon.yaml
+++ b/charts/fluentbit/templates/fluentbit-daemon.yaml
@@ -1,7 +1,7 @@
 apiVersion: apps/v1
 kind: DaemonSet
 metadata:
-  name: drycc-logger-fluentbit
+  name: drycc-fluentbit
   labels:
     heritage: drycc
   annotations:
@@ -11,33 +11,37 @@ spec:
     type: RollingUpdate
   selector:
     matchLabels:
-      app: drycc-logger-fluentbit
+      app: drycc-fluentbit
       heritage: drycc
   template:
     metadata:
-      name: drycc-logger-fluentbit
+      name: drycc-fluentbit
       labels: {{- include "common.labels.standard" . | nindent 8 }}
         heritage: drycc
-        app: drycc-logger-fluentbit
+        app: drycc-fluentbit
     spec:
-      serviceAccount: drycc-logger-fluentbit
+      serviceAccount: drycc-fluentbit
       initContainers:
-      - name: drycc-logger-fluentbit-init
+      - name: drycc-fluentbit-init
         image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/python-dev:latest
         imagePullPolicy: {{.Values.imagePullPolicy}}
         args:
         - netcat
         - -v
         - -u
-        - $(DRYCC_VALKEY_URL)
+        - http://drycc-quickwit-indexer.{{ $.Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:7280
         {{- include "fluentbit.envs" . | indent 8 }}
       containers:
-      - name: drycc-logger-fluentbit
+      - name: drycc-fluentbit
         image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/fluentbit:{{.Values.imageTag}}
         imagePullPolicy: {{.Values.imagePullPolicy}}
         {{- if .Values.diagnosticMode.enabled }}
         command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 10 }}
         args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 10 }}
+        {{- else }}
+        args:
+        - fluent-bit
+        - --config=/opt/drycc/fluent-bit/etc/fluent-bit/fluent-bit.conf
         {{- end }}
         {{- with index .Values "resources" }}
         resources:
@@ -47,15 +51,15 @@ spec:
         volumeMounts:
         - name: varlog
           mountPath: /var/log
-        - name: logger-fluentbit-config
-          mountPath: /opt/drycc/fluent-bit/templates
+        - name: fluentbit-config
+          mountPath: /opt/drycc/fluent-bit/etc/fluent-bit
       volumes:
       - name: varlog
         hostPath:
           path: /var/log
-      - name: logger-fluentbit-config
+      - name: fluentbit-config
         configMap:
-          name: logger-fluentbit-config
+          name: fluentbit-config
       securityContext:
         fsGroup: 0
         runAsGroup: 0
diff --git a/charts/fluentbit/templates/logger-fluentbit-service-account.yaml b/charts/fluentbit/templates/fluentbit-service-account.yaml
similarity index 71%
rename from charts/fluentbit/templates/logger-fluentbit-service-account.yaml
rename to charts/fluentbit/templates/fluentbit-service-account.yaml
index 2f87155..5d03f02 100644
--- a/charts/fluentbit/templates/logger-fluentbit-service-account.yaml
+++ b/charts/fluentbit/templates/fluentbit-service-account.yaml
@@ -1,6 +1,6 @@
 apiVersion: v1
 kind: ServiceAccount
 metadata:
-  name: drycc-logger-fluentbit
+  name: drycc-fluentbit
   labels:
     heritage: drycc
diff --git a/charts/fluentbit/templates/logger-fluentbit-secret-creds.yaml b/charts/fluentbit/templates/logger-fluentbit-secret-creds.yaml
deleted file mode 100644
index 7a26ea2..0000000
--- a/charts/fluentbit/templates/logger-fluentbit-secret-creds.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
-  name: logger-fluentbit-creds
-  labels:
-    heritage: drycc
-data:
-  {{- if (.Values.valkeyUrl) }}
-  valkey-url: {{ .Values.valkeyUrl | b64enc }}
-  {{- end }}
\ No newline at end of file
diff --git a/charts/fluentbit/values.yaml b/charts/fluentbit/values.yaml
index 7e52dd8..6738034 100644
--- a/charts/fluentbit/values.yaml
+++ b/charts/fluentbit/values.yaml
@@ -27,10 +27,11 @@ resources: {}
   #   memory: 30Mi
 
 # Interval to flush output (seconds)
-flush: 1
+flush: 10
 
-# external valkey configuration
-valkeyUrl: ""
+# The log index prefix in Quickwit, which is prepended to the index name.
+quickwit:
+  logIndexPrefix: "logs-"
 
 ## https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/configuration-file
 config:
@@ -39,14 +40,14 @@ config:
         Flush               {{ .Values.flush }}
         Daemon              Off
         Log_Level           info
-        Plugins_File        /opt/drycc/fluent-bit/etc/fluent-bit/plugins.conf
         Parsers_File        /opt/drycc/fluent-bit/etc/fluent-bit/parsers.conf
+        Plugins_File        /opt/drycc/fluent-bit/etc/fluent-bit/plugins.conf
 
   ## https://docs.fluentbit.io/manual/pipeline/inputs
   inputs: |
     [INPUT]
         Name                tail
-        Path                /var/log/containers/*_{{ .Release.Namespace }}_*.log
+        Path                /var/log/containers/*.log
         DB                  /var/log/containers.pos.db
         DB.locking          true
         Offset_Key          offset
@@ -59,24 +60,26 @@ config:
     [FILTER]
         Name                kubernetes
         Match               kubernetes.*
-        Kube_URL            https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}
+        Kube_URL            https://kubernetes.default.svc:443
         Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
         Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token
         Kube_Tag_Prefix     kubernetes.var.log.containers.
         tls.verify          false
         Buffer_Size         0
+        Merge_Log           On
+        Keep_Log            Off
 
   ## https://docs.fluentbit.io/manual/pipeline/outputs
   outputs: |
     [OUTPUT]
-        Name                drycc
+        Name                quickwit
         Match               kubernetes.*
-        Stream              logs
-        Max_Len             3000
-        Valkey_URL          ${DRYCC_VALKEY_URL}
-        Controller_Name     drycc-controller
-        Controller_Regex    ^(INFO|WARN|DEBUG|ERROR)\s+(\[(\S+)\])+:(.*)
-        Exclude_Namespaces  drycc,drycc-manager,drycc-helmbroker,kube-system,metallb
+        Base_URL            http://drycc-quickwit-indexer.{{ $.Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:7280
+        Compress            true
+        Index_Name          {{ .Values.quickwit.logIndexPrefix }}${ .kubernetes.namespace_name | default "{{ .Release.Namespace }}" }
+        Buffer_Size         65536
+        Json_Date_Key       timestamp
+        Json_Date_Format    %Y-%m-%dT%H:%M:%S%z
   ## https://docs.fluentbit.io/manual/pipeline/parsers
   parsers: |
     [PARSER]
@@ -86,7 +89,7 @@ config:
         Time_Format         %Y-%m-%dT%H:%M:%S.%L
         Time_Keep           On
 
-    [PARSER]
+    [PARSER] 
         # http://rubular.com/r/tjUt3Awgg4
         Name                cri
         Format              regex
@@ -97,7 +100,4 @@ config:
   ## https://docs.fluentbit.io/manual/development/golang-output-plugins
   plugins: |
     [PLUGINS]
-        Path                ${FLUENT_BIT_PLUGINS_PATH}/out_drycc.so
-
-valkey:
-  enabled: true
+        Path                /opt/drycc/fluent-bit/lib/out_quickwit.so
diff --git a/go.mod b/go.mod
index 089fc7e..f65181a 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,21 @@ module github.com/drycc/fluentbit
 go 1.24
 
 require (
+	github.com/Masterminds/sprig/v3 v3.3.0
 	github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c
-	github.com/valkey-io/valkey-go v1.0.56
-	github.com/valkey-io/valkey-go/valkeycompat v1.0.56
 )
 
 require (
+	dario.cat/mergo v1.0.1 // indirect
+	github.com/Masterminds/goutils v1.1.1 // indirect
+	github.com/Masterminds/semver/v3 v3.3.0 // indirect
+	github.com/google/go-cmp v0.7.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/huandu/xstrings v1.5.0 // indirect
+	github.com/mitchellh/copystructure v1.2.0 // indirect
+	github.com/mitchellh/reflectwalk v1.0.2 // indirect
+	github.com/shopspring/decimal v1.4.0 // indirect
+	github.com/spf13/cast v1.7.0 // indirect
 	github.com/ugorji/go/codec v1.2.12 // indirect
-	golang.org/x/sys v0.31.0 // indirect
+	golang.org/x/crypto v0.26.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 33b3aa0..3639cf0 100644
--- a/go.sum
+++ b/go.sum
@@ -1,36 +1,49 @@
+dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
+dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
+github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
+github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
+github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
+github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c h1:yKN46XJHYC/gvgH2UsisJ31+n4K3S7QYZSfU2uAWjuI=
 github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c/go.mod h1:L92h+dgwElEyUuShEwjbiHjseW410WIcNz+Bjutc8YQ=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
-github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
-github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
-github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
-github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
-github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
-github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
-github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
+github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
+github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
+github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
 github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
-github.com/valkey-io/valkey-go v1.0.56 h1:7qp/9dqqPbYEEKeFZCnpX6nzM5XzO2MPp0iKh9+c9Wg=
-github.com/valkey-io/valkey-go v1.0.56/go.mod h1:sxpCChk8i3oTG+A/lUi9Lj8C/7WI+yhnQCvDJlPVKNM=
-github.com/valkey-io/valkey-go/mock v1.0.56 h1:ZJ1W5nBLPcYxqTHqlbLFZ+QTkP8csJAmTGiairz8cVo=
-github.com/valkey-io/valkey-go/mock v1.0.56/go.mod h1:PotVMrBbjcPwBgec2CFEHfe+4/URbxN7cnBmU3sTy9o=
-github.com/valkey-io/valkey-go/valkeycompat v1.0.56 h1:bqltI2FCAElpY/LHKJe5scRtdRvHdIbhKPkCWki3Ppg=
-github.com/valkey-io/valkey-go/valkeycompat v1.0.56/go.mod h1:knF+QzcgwPDEoes594Rircbt+ZhXtnnEGc2UzvNqEFU=
-go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
-go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
-golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
-golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
-golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
-golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
+golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/plugin/out_drycc.go b/plugin/out_drycc.go
deleted file mode 100644
index b0bb894..0000000
--- a/plugin/out_drycc.go
+++ /dev/null
@@ -1,156 +0,0 @@
-package main
-
-import (
-	"C"
-	"unsafe"
-
-	"context"
-	"strings"
-
-	"github.com/fluent/fluent-bit-go/output"
-	"github.com/valkey-io/valkey-go"
-	"github.com/valkey-io/valkey-go/valkeycompat"
-)
-import (
-	"encoding/json"
-	"fmt"
-	"regexp"
-	"strconv"
-	"time"
-)
-
-var (
-	Stream            string
-	MaxLen            int64
-	Revision          string
-	BuildDate         string
-	ControllerName    string
-	ControllerRegex   *regexp.Regexp
-	ExcludeNamespaces []string
-	ValkeyClient      valkey.Client
-)
-
-//export FLBPluginRegister
-func FLBPluginRegister(ctx unsafe.Pointer) int {
-	fmt.Printf("Drycc output version %s %s", Revision, BuildDate)
-	return output.FLBPluginRegister(ctx, "drycc", "Ship fluent-bit logs to valkey xstream")
-}
-
-// (fluentbit will call this)
-// ctx (context) pointer to fluentbit context (state/ c code)
-//
-//export FLBPluginInit
-func FLBPluginInit(ctx unsafe.Pointer) int {
-	var err error
-	Stream = output.FLBPluginConfigKey(ctx, "Stream")
-	MaxLen, err = strconv.ParseInt(output.FLBPluginConfigKey(ctx, "Max_Len"), 10, 64)
-	if err != nil {
-		MaxLen = 1000
-	}
-	ValkeyURL := output.FLBPluginConfigKey(ctx, "Valkey_URL")
-	ControllerName = output.FLBPluginConfigKey(ctx, "Controller_Name")
-	ControllerRegex = regexp.MustCompile(output.FLBPluginConfigKey(ctx, "Controller_Regex"))
-	ExcludeNamespaces = strings.Split(output.FLBPluginConfigKey(ctx, "Exclude_Namespaces"), ",")
-
-	ValkeyClient, err = valkey.NewClient(valkey.MustParseURL(ValkeyURL))
-	if err != nil {
-		return output.FLB_ERROR
-	}
-	return output.FLB_OK
-}
-
-//export FLBPluginFlushCtx
-//revive:disable:unused-parameter
-func FLBPluginFlushCtx(ctx, data unsafe.Pointer, length C.int, _ *C.char) int {
-	status := output.FLB_OK
-	context, cancel := context.WithTimeout(context.Background(), time.Second*30)
-	defer cancel()
-	decoder := output.NewDecoder(data, int(length))
-	pipeline := valkeycompat.NewAdapter(ValkeyClient).Pipeline()
-	for {
-		ret, ts, rec := output.GetRecord(decoder)
-		if ret != 0 {
-			break
-		}
-		// Get timestamp
-		rec["time"] = toTimestamp(ts)
-		if !checkRecord(rec) {
-			continue
-		}
-		if values, err := toValues(rec); err == nil {
-			pipeline.XAdd(context, valkeycompat.XAddArgs{
-				Stream:     Stream,
-				NoMkStream: false,
-				MaxLen:     MaxLen,
-				Approx:     true,
-				ID:         "*",
-				Values:     values,
-			})
-		} else {
-			status = output.FLB_ERROR
-		}
-	}
-	if _, err := pipeline.Exec(context); err != nil {
-		status = output.FLB_ERROR
-	}
-	return status
-}
-
-//export FLBPluginExit
-func FLBPluginExit() int {
-	ValkeyClient.Close()
-	return output.FLB_OK
-}
-
-func toMap(values map[interface{}]interface{}) map[string]interface{} {
-	m := make(map[string]interface{})
-	for k, v := range values {
-		switch t := v.(type) {
-		case []byte:
-			// prevent encoding to base64
-			m[k.(string)] = string(t)
-		case map[interface{}]interface{}:
-			m[k.(string)] = toMap(t)
-		default:
-			m[k.(string)] = v
-		}
-	}
-	return m
-}
-
-func toValues(values map[interface{}]interface{}) (map[string]interface{}, error) {
-	data, err := json.Marshal(toMap(values))
-	if err != nil {
-		return nil, err
-	}
-	return map[string]interface{}{"data": data, "timestamp": time.Now().Unix()}, err
-}
-
-func toTimestamp(ts interface{}) string {
-	var timestamp time.Time
-	switch t := ts.(type) {
-	case output.FLBTime:
-		timestamp = ts.(output.FLBTime).Time
-	case uint64:
-		timestamp = time.Unix(int64(t), 0)
-	default:
-		timestamp = time.Now()
-	}
-	return timestamp.Format(time.RFC3339Nano)
-}
-
-func checkRecord(record map[interface{}]interface{}) bool {
-	if kubernetes, ok := record["kubernetes"].(map[interface{}]interface{}); ok {
-		// drycc controller
-		container := fmt.Sprintf("%s", kubernetes["container_name"])
-		if ok && strings.HasPrefix(container, ControllerName) {
-			log := fmt.Sprintf("%s", record["log"])
-			if ok && len(ControllerRegex.FindStringSubmatch(log)) > 0 {
-				return true
-			}
-		}
-	}
-	return false
-}
-
-func main() {}
diff --git a/plugin/out_quickwit.go b/plugin/out_quickwit.go
new file mode 100644
index 0000000..7d6d340
--- /dev/null
+++ b/plugin/out_quickwit.go
@@ -0,0 +1,184 @@
+package main
+
+import (
+	"C"
+	"unsafe"
+
+	"github.com/fluent/fluent-bit-go/output"
+)
+import (
+	"bytes"
+	"crypto/tls"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"strconv"
+	"strings"
+	"sync"
+	"text/template"
+	"time"
+
+	"github.com/Masterminds/sprig/v3"
+)
+
+var (
+	MaxLen    int64
+	Revision  string
+	BuildDate string
+
+	// plugin config
+	BaseURL        string
+	IndexName      string
+	Compress       bool
+	BufferSize     int
+	JSONDateKey    string
+	JSONDateFormat string
+	// internal variables
+	BufferPool        sync.Pool
+	IndexNameTemplate *template.Template
+)
+
+//export FLBPluginRegister
+func FLBPluginRegister(ctx unsafe.Pointer) int {
+	fmt.Printf("Quickwit output version %s %s", Revision, BuildDate)
+	return output.FLBPluginRegister(ctx, "quickwit", "Ship fluent-bit logs to quickwit")
+}
+
+// (fluentbit will call this)
+// ctx (context) pointer to fluentbit context (state/ c code)
+//
+//export FLBPluginInit
+func FLBPluginInit(ctx unsafe.Pointer) int {
+	BaseURL = output.FLBPluginConfigKey(ctx, "Base_URL")
+	IndexName = output.FLBPluginConfigKey(ctx, "Index_Name")
+	Compress, _ = strconv.ParseBool(output.FLBPluginConfigKey(ctx, "Compress"))
+
+	var err error
+	BufferSize, err = strconv.Atoi(output.FLBPluginConfigKey(ctx, "Buffer_Size"))
+	if err != nil {
+		panic(err)
+	}
+	BufferPool = sync.Pool{
+		New: func() any {
+			buffer := &bytes.Buffer{}
+			buffer.Grow(BufferSize)
+			return buffer
+		},
+	}
+	IndexNameTemplate, err = template.New("url").Funcs(sprig.FuncMap()).Delims("${", "}").Parse(IndexName)
+	if err != nil {
+		panic(err)
+	}
+	JSONDateKey = output.FLBPluginConfigKey(ctx, "Json_Date_Key")
+	JSONDateFormat = output.FLBPluginConfigKey(ctx, "Json_Date_Format")
+	return output.FLB_OK
+}
+
+//export FLBPluginFlushCtx
+//revive:disable:unused-parameter
+func FLBPluginFlushCtx(ctx, data unsafe.Pointer, length C.int, _ *C.char) int {
+	decoder := output.NewDecoder(data, int(length))
+	results := make(map[string]*bytes.Buffer)
+	for {
+		ret, ts, rec := output.GetRecord(decoder)
+		if ret != 0 {
+			break
+		}
+		data := convertMap(rec)
+		data[JSONDateKey] = formatTime(ts, JSONDateFormat)
+		if jsonBytes, err := json.Marshal(data); err == nil {
+			var buffer bytes.Buffer
+			IndexNameTemplate.Execute(&buffer, data)
+			index := buffer.String()
+			if buffer, ok := results[index]; !ok {
+				buffer := BufferPool.Get().(*bytes.Buffer)
+				results[index] = buffer
+				buffer.Write(jsonBytes)
+				buffer.WriteByte('\n')
+			} else {
+				buffer.Write(jsonBytes)
+				buffer.WriteByte('\n')
+			}
+		}
+	}
+	if err := sendResults(results); err != nil {
+		return output.FLB_ERROR
+	}
+	return output.FLB_OK
+}
+
+//export FLBPluginExit
+func FLBPluginExit() int {
+	return output.FLB_OK
+}
+
+func formatTime(ts any, format string) string {
+	var timestamp time.Time
+	switch t := ts.(type) {
+	case output.FLBTime:
+		timestamp = ts.(output.FLBTime).Time
+	case uint64:
+		timestamp = time.Unix(int64(t), 0)
+	default:
+		timestamp = time.Now()
+	}
+	return timestamp.Format(strings.NewReplacer(
+		"%Y", "2006",
+		"%y", "06",
+		"%m", "01",
+		"%d", "02",
+		"%H", "15",
+		"%I", "03",
+		"%M", "04",
+		"%S", "05",
+		"%p", "PM",
+		"%L", "000",
+		"%f", "000000",
+		"%z", "-0700",
+		"%Z", "MST",
+	).Replace(format))
+}
+
+func convertMap(values map[any]any) map[string]any {
+	m := make(map[string]any)
+	for k, v := range values {
+		key := fmt.Sprintf("%v", k)
+		switch t := v.(type) {
+		case []byte:
+			m[key] = string(t)
+		case map[any]any:
+			m[key] = convertMap(t)
+		default:
+			m[key] = v
+		}
+	}
+	return m
+}
+
+func sendResults(results map[string]*bytes.Buffer) error {
+	client := &http.Client{
+		Transport: &http.Transport{
+			TLSClientConfig:    &tls.Config{InsecureSkipVerify: false},
+			ForceAttemptHTTP2:  true,
+			MaxIdleConns:       100,
+			IdleConnTimeout:    90 * time.Second,
+			DisableCompression: !Compress,
+		},
+		Timeout: 30 * time.Second,
+	}
+	defer client.CloseIdleConnections()
+	for index, body := range results {
+		url := fmt.Sprintf("%s/api/v1/%s/ingest", BaseURL, index)
+		if req, err := http.NewRequest("POST", url, body); err == nil {
+			if resp, err := client.Do(req); err == nil {
+				io.Copy(io.Discard, resp.Body)
+				resp.Body.Close()
+				body.Reset()
+			}
+		}
+	}
+	return nil
+}
+
+func main() {}
diff --git a/rootfs/opt/drycc/fluent-bit/templates/fluent-bit.conf b/rootfs/opt/drycc/fluent-bit/templates/fluent-bit.conf
deleted file mode 100644
index 6d9fa26..0000000
--- a/rootfs/opt/drycc/fluent-bit/templates/fluent-bit.conf
+++ /dev/null
@@ -1,35 +0,0 @@
-[SERVICE]
-    Flush               1
-    Daemon              Off
-    Log_Level           info
-    Plugins_File        /opt/drycc/fluent-bit/etc/fluent-bit/plugins.conf
-    Parsers_File        /opt/drycc/fluent-bit/etc/fluent-bit/parsers.conf
-
-[INPUT]
-    Name                tail
-    Path                /var/log/containers/*.log
-    DB                  /var/log/containers.pos.db
-    DB.locking          true
-    Offset_Key          offset
-    Tag                 kubernetes.*
-    Read_from_Head      false
-    multiline.parser    docker,cri
-
-[FILTER]
-    Name                kubernetes
-    Match               kubernetes.*
-    Kube_URL            https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}
-    Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
-    Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token
-    Kube_Tag_Prefix     kubernetes.var.log.containers.
-    tls.verify          false
-
-[OUTPUT]
-    Name                drycc
-    Match               kubernetes.*
-    Stream              logs
-    Max_Len             3000
-    Valkey_URL          ${DRYCC_VALKEY_URL}
-    Controller_Name     drycc-controller
-    Controller_Regex    ^(INFO|WARN|DEBUG|ERROR)\s+(\[(\S+)\])+:(.*)
-    Exclude_Namespaces  drycc,drycc-manager,drycc-helmbroker,kube-system,metallb
\ No newline at end of file
diff --git a/rootfs/opt/drycc/fluent-bit/templates/parsers.conf b/rootfs/opt/drycc/fluent-bit/templates/parsers.conf
deleted file mode 100644
index ec918ee..0000000
--- a/rootfs/opt/drycc/fluent-bit/templates/parsers.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-[PARSER]
-    Name                docker
-    Format              json
-    Time_Key            time
-    Time_Format         %Y-%m-%dT%H:%M:%S.%L
-    Time_Keep           On
-
-[PARSER]
-    # http://rubular.com/r/tjUt3Awgg4
-    Name                cri
-    Format              regex
-    Regex               ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$
-    Time_Key            time
-    Time_Format         %Y-%m-%dT%H:%M:%S.%L%z
-    Time_Keep           On
\ No newline at end of file
diff --git a/rootfs/opt/drycc/fluent-bit/templates/plugins.conf b/rootfs/opt/drycc/fluent-bit/templates/plugins.conf
deleted file mode 100644
index 0f56db0..0000000
--- a/rootfs/opt/drycc/fluent-bit/templates/plugins.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[PLUGINS]
-    Path                ${FLUENT_BIT_PLUGINS_PATH}/out_drycc.so
\ No newline at end of file
diff --git a/rootfs/usr/local/bin/boot b/rootfs/usr/local/bin/boot
deleted file mode 100755
index 39d4c4b..0000000
--- a/rootfs/usr/local/bin/boot
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env bash
-set -eo pipefail
-shopt -s expand_aliases
-
-eval "cat <<EOF
-$(</opt/drycc/fluent-bit/templates/plugins.conf)
-EOF
-" 2> /dev/null > /opt/drycc/fluent-bit/etc/fluent-bit/plugins.conf
-
-eval "cat <<EOF
-$(</opt/drycc/fluent-bit/templates/parsers.conf)
-EOF
-" 2> /dev/null > /opt/drycc/fluent-bit/etc/fluent-bit/parsers.conf
-
-eval "cat <<EOF
-$(</opt/drycc/fluent-bit/templates/fluent-bit.conf)
-EOF
-" 2> /dev/null > /opt/drycc/fluent-bit/etc/fluent-bit/fluent-bit.conf
-
-fluent-bit -c /opt/drycc/fluent-bit/etc/fluent-bit/fluent-bit.conf

From cd39efdf9dc6f87c9a8193247e96cbcc659c76d0 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Fri, 11 Jul 2025 13:05:49 +0800
Subject: [PATCH 03/10] chore(fluentbit): add rfc3399 format

---
 charts/fluentbit/Chart.lock              |   6 ----
 charts/fluentbit/charts/common-1.1.4.tgz | Bin 13755 -> 0 bytes
 charts/fluentbit/values.yaml             |   7 ++--
 plugin/out_quickwit.go                   |  39 +++++++++++++----------
 4 files changed, 28 insertions(+), 24 deletions(-)
 delete mode 100644 charts/fluentbit/Chart.lock
 delete mode 100644 charts/fluentbit/charts/common-1.1.4.tgz

diff --git a/charts/fluentbit/Chart.lock b/charts/fluentbit/Chart.lock
deleted file mode 100644
index 70fffe4..0000000
--- a/charts/fluentbit/Chart.lock
+++ /dev/null
@@ -1,6 +0,0 @@
-dependencies:
-- name: common
-  repository: oci://registry.drycc.cc/charts
-  version: 1.1.4
-digest: sha256:d101f4d0e796524281dec60d636aa301ba92a42d7c0468aa5072e721bdd48a6b
-generated: "2025-07-01T16:47:29.929607311+08:00"
diff --git a/charts/fluentbit/charts/common-1.1.4.tgz b/charts/fluentbit/charts/common-1.1.4.tgz
deleted file mode 100644
index 4794547e490ed3affe3fdc3e27b12098163657bb..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/charts/fluentbit/values.yaml b/charts/fluentbit/values.yaml
index 6738034..3b7696f 100644
--- a/charts/fluentbit/values.yaml
+++ b/charts/fluentbit/values.yaml
@@ -76,10 +76,10 @@ config:
         Match               kubernetes.*
         Base_URL            http://drycc-quickwit-indexer.{{ $.Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:7280
         Compress            true
-        Index_Name          {{ .Values.quickwit.logIndexPrefix }}${ .kubernetes.namespace_name | default "{{ .Release.Namespace }}" }
+        Index_Name          {{printf "%s{{ %s | default \"%s\" }}" .Values.quickwit.logIndexPrefix ".kubernetes.namespace_name" .Release.Namespace }}
         Buffer_Size         65536
         Json_Date_Key       timestamp
-        Json_Date_Format    %Y-%m-%dT%H:%M:%S%z
+        Json_Date_Format    rfc3399
   ## https://docs.fluentbit.io/manual/pipeline/parsers
   parsers: |
     [PARSER]
@@ -101,3 +101,6 @@ config:
   plugins: |
     [PLUGINS]
         Path                /opt/drycc/fluent-bit/lib/out_quickwit.so
+
+global:
+  clusterDomain: "cluster.local"
diff --git a/plugin/out_quickwit.go b/plugin/out_quickwit.go
index 7d6d340..bdf49b3 100644
--- a/plugin/out_quickwit.go
+++ b/plugin/out_quickwit.go
@@ -66,7 +66,7 @@ func FLBPluginInit(ctx unsafe.Pointer) int {
 			return buffer
 		},
 	}
-	IndexNameTemplate, err = template.New("url").Funcs(sprig.FuncMap()).Delims("${", "}").Parse(IndexName)
+	IndexNameTemplate, err = template.New("index").Funcs(sprig.FuncMap()).Parse(IndexName)
 	if err != nil {
 		panic(err)
 	}
@@ -123,21 +123,28 @@ func formatTime(ts any, format string) string {
 	default:
 		timestamp = time.Now()
 	}
-	return timestamp.Format(strings.NewReplacer(
-		"%Y", "2006",
-		"%y", "06",
-		"%m", "01",
-		"%d", "02",
-		"%H", "15",
-		"%I", "03",
-		"%M", "04",
-		"%S", "05",
-		"%p", "PM",
-		"%L", "000",
-		"%f", "000000",
-		"%z", "-0700",
-		"%Z", "MST",
-	).Replace(format))
+	switch format {
+	case "rfc3399":
+		return timestamp.Format(time.RFC3339)
+	case "unix_timestamp":
+		return fmt.Sprint(timestamp.Unix())
+	default:
+		return timestamp.Format(strings.NewReplacer(
+			"%Y", "2006",
+			"%y", "06",
+			"%m", "01",
+			"%d", "02",
+			"%H", "15",
+			"%I", "03",
+			"%M", "04",
+			"%S", "05",
+			"%p", "PM",
+			"%L", "000",
+			"%f", "000000",
+			"%z", "-0700",
+			"%Z", "MST",
+		).Replace(format))
+	}
 }
 
 func convertMap(values map[any]any) map[string]any {

From ebac91c9656d5bf7aecc2863df51e1e31d8841c2 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Tue, 15 Jul 2025 23:27:51 +0800
Subject: [PATCH 04/10] chore(charts): remove cluster domain

---
 charts/fluentbit/templates/fluentbit-daemon.yaml | 2 +-
 charts/fluentbit/values.yaml                     | 5 +----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/charts/fluentbit/templates/fluentbit-daemon.yaml b/charts/fluentbit/templates/fluentbit-daemon.yaml
index 892091d..ddb77ce 100644
--- a/charts/fluentbit/templates/fluentbit-daemon.yaml
+++ b/charts/fluentbit/templates/fluentbit-daemon.yaml
@@ -29,7 +29,7 @@ spec:
         - netcat
         - -v
         - -u
-        - http://drycc-quickwit-indexer.{{ $.Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:7280
+        - http://drycc-quickwit-indexer:7280
         {{- include "fluentbit.envs" . | indent 8 }}
       containers:
       - name: drycc-fluentbit
diff --git a/charts/fluentbit/values.yaml b/charts/fluentbit/values.yaml
index 3b7696f..66e1754 100644
--- a/charts/fluentbit/values.yaml
+++ b/charts/fluentbit/values.yaml
@@ -74,7 +74,7 @@ config:
     [OUTPUT]
         Name                quickwit
         Match               kubernetes.*
-        Base_URL            http://drycc-quickwit-indexer.{{ $.Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:7280
+        Base_URL            http://drycc-quickwit-indexer:7280
         Compress            true
         Index_Name          {{printf "%s{{ %s | default \"%s\" }}" .Values.quickwit.logIndexPrefix ".kubernetes.namespace_name" .Release.Namespace }}
         Buffer_Size         65536
@@ -101,6 +101,3 @@ config:
   plugins: |
     [PLUGINS]
         Path                /opt/drycc/fluent-bit/lib/out_quickwit.so
-
-global:
-  clusterDomain: "cluster.local"

From 9fe2fce4aadbd819e9df316c534cfd143b95bd65 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Fri, 18 Jul 2025 09:31:10 +0800
Subject: [PATCH 05/10] chore(filter): use tag for meta

---
 charts/fluentbit/values.yaml | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/charts/fluentbit/values.yaml b/charts/fluentbit/values.yaml
index 66e1754..ac1bb89 100644
--- a/charts/fluentbit/values.yaml
+++ b/charts/fluentbit/values.yaml
@@ -60,14 +60,10 @@ config:
     [FILTER]
         Name                kubernetes
         Match               kubernetes.*
-        Kube_URL            https://kubernetes.default.svc:443
-        Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
-        Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token
-        Kube_Tag_Prefix     kubernetes.var.log.containers.
-        tls.verify          false
-        Buffer_Size         0
-        Merge_Log           On
         Keep_Log            Off
+        Merge_Log           On
+        Buffer_Size         0
+        Use_Tag_For_Meta    true
 
   ## https://docs.fluentbit.io/manual/pipeline/outputs
   outputs: |

From 950b5222f44488fc123196c5b64721b57610d8a9 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Fri, 18 Jul 2025 09:44:22 +0800
Subject: [PATCH 06/10] chore(charts): remove redundant rbac configurations

---
 .../templates/fluentbit-clusterrole.yaml          | 11 -----------
 .../templates/fluentbit-clusterrolebinding.yaml   | 15 ---------------
 charts/fluentbit/values.yaml                      |  7 +++++++
 3 files changed, 7 insertions(+), 26 deletions(-)
 delete mode 100644 charts/fluentbit/templates/fluentbit-clusterrole.yaml
 delete mode 100644 charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml

diff --git a/charts/fluentbit/templates/fluentbit-clusterrole.yaml b/charts/fluentbit/templates/fluentbit-clusterrole.yaml
deleted file mode 100644
index 9c95190..0000000
--- a/charts/fluentbit/templates/fluentbit-clusterrole.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-kind: ClusterRole
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
-  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
-  labels:
-    app: drycc-fluentbit
-    heritage: drycc
-rules:
-- apiGroups: [""]
-  resources: ["pods", "namespaces"]
-  verbs: ["list", "get", "watch"]
\ No newline at end of file
diff --git a/charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml b/charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml
deleted file mode 100644
index f25d985..0000000
--- a/charts/fluentbit/templates/fluentbit-clusterrolebinding.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-kind: ClusterRoleBinding
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
-  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
-  labels:
-    app: drycc-fluentbit
-    heritage: drycc
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: ClusterRole
-  name: {{ printf "%s:drycc-fluentbit" .Release.Namespace | quote }}
-subjects:
-- kind: ServiceAccount
-  name: drycc-fluentbit
-  namespace: {{ .Release.Namespace }}
diff --git a/charts/fluentbit/values.yaml b/charts/fluentbit/values.yaml
index ac1bb89..b815578 100644
--- a/charts/fluentbit/values.yaml
+++ b/charts/fluentbit/values.yaml
@@ -63,6 +63,7 @@ config:
         Keep_Log            Off
         Merge_Log           On
         Buffer_Size         0
+        Regex_Parser        kubernetes
         Use_Tag_For_Meta    true
 
   ## https://docs.fluentbit.io/manual/pipeline/outputs
@@ -93,6 +94,12 @@ config:
         Time_Key            time
         Time_Format         %Y-%m-%dT%H:%M:%S.%L%z
         Time_Keep           On
+
+    [PARSER]
+        Name    kubernetes
+        Format  regex
+        Regex   (?<tag>[^.]+)?\.?(?<pod_name>[a-z0-9](?:[-a-z0-9]*[a-z0-9])?(?:\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$
+
   ## https://docs.fluentbit.io/manual/development/golang-output-plugins
   plugins: |
     [PLUGINS]

From 6fb296035ccf20e2a04cc9139b66af972ac238cc Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Fri, 12 Sep 2025 10:19:52 +0800
Subject: [PATCH 07/10] chore(go): bump go version to 1.25

---
 go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index f65181a..731700a 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/drycc/fluentbit
 
-go 1.24
+go 1.25
 
 require (
 	github.com/Masterminds/sprig/v3 v3.3.0

From 44575046fd086c08ffe8516db3f98421b8d288e9 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Sun, 14 Sep 2025 01:20:25 +0800
Subject: [PATCH 08/10] chore(fluentbit): bump new version

---
 Dockerfile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index cbe91c5..bc971bc 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -17,9 +17,9 @@ FROM registry.drycc.cc/drycc/base:${CODENAME}
 
 ENV DRYCC_UID=1001 \
   DRYCC_GID=1001 \
-  FLUENT_BIT_VERSION=4.0.2 \
+  FLUENT_BIT_VERSION=4.0.9 \
   DRYCC_HOME_DIR=/opt/drycc
-  
+
 RUN groupadd drycc --gid ${DRYCC_GID} \
   && useradd drycc -u ${DRYCC_UID} -g ${DRYCC_GID} -s /bin/bash -m -d ${DRYCC_HOME_DIR}
 

From b022d5c3790134781abfc87a923dc7b63a32ad97 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Wed, 17 Sep 2025 15:13:41 +0800
Subject: [PATCH 09/10] chore(fluentbit): fmt go code

---
 plugin/out_quickwit.go | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/plugin/out_quickwit.go b/plugin/out_quickwit.go
index bdf49b3..c4c6c79 100644
--- a/plugin/out_quickwit.go
+++ b/plugin/out_quickwit.go
@@ -1,11 +1,10 @@
+// drycc quickwit plugin
 package main
 
 import (
 	"C"
-	"unsafe"
-
-	"github.com/fluent/fluent-bit-go/output"
 )
+
 import (
 	"bytes"
 	"crypto/tls"
@@ -18,8 +17,10 @@ import (
 	"sync"
 	"text/template"
 	"time"
+	"unsafe"
 
 	"github.com/Masterminds/sprig/v3"
+	"github.com/fluent/fluent-bit-go/output"
 )
 
 var (

From 55c0baa1189176ca01330432cba3ca65ae9e0750 Mon Sep 17 00:00:00 2001
From: duanhongyi <duanhongyi@doopai.com>
Date: Thu, 6 Nov 2025 17:03:12 +0800
Subject: [PATCH 10/10] chore(fluentbit): change env to build arg

---
 Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Dockerfile b/Dockerfile
index bc971bc..045e8b5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,7 +15,7 @@ RUN export GO111MODULE=on \
 
 FROM registry.drycc.cc/drycc/base:${CODENAME}
 
-ENV DRYCC_UID=1001 \
+ARG DRYCC_UID=1001 \
   DRYCC_GID=1001 \
   FLUENT_BIT_VERSION=4.0.9 \
   DRYCC_HOME_DIR=/opt/drycc
