diff --git a/cmd/main.go b/cmd/main.go
index 20788d10d0..8c57771e39 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -93,7 +93,7 @@ func main() {
flag.Parse()
- logger := utils.InitLogger("cluster-logging-operator")
+ logger := utils.InitStaticLogger("cluster-logging-operator")
// LOG-5136 Fixes error caused by updates to controller-runtime
ctrl.SetLogger(logger)
diff --git a/go.mod b/go.mod
index 8c651d164c..b04898ee0e 100644
--- a/go.mod
+++ b/go.mod
@@ -21,10 +21,12 @@ require (
github.com/prometheus/client_golang v1.20.5
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
+ github.com/vspaz/wls-go v0.0.0-20230405190232-47d1e477c82c
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
golang.org/x/net v0.37.0
golang.org/x/sync v0.12.0
golang.org/x/sys v0.32.0
+ gonum.org/v1/plot v0.16.0
k8s.io/api v0.32.2
k8s.io/apimachinery v0.32.2
k8s.io/apiserver v0.32.2
@@ -36,11 +38,17 @@ require (
require (
cel.dev/expr v0.18.0 // indirect
+ codeberg.org/go-fonts/liberation v0.5.0 // indirect
+ codeberg.org/go-latex/latex v0.1.0 // indirect
+ codeberg.org/go-pdf/fpdf v0.10.0 // indirect
+ git.sr.ht/~sbinet/gg v0.6.0 // indirect
+ github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/aws/smithy-go v1.8.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
+ github.com/campoy/embedmd v1.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -56,6 +64,7 @@ require (
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.22.0 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
@@ -93,6 +102,7 @@ require (
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
+ golang.org/x/image v0.25.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect
diff --git a/go.sum b/go.sum
index a04a77056b..ef2502acae 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,26 @@
cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
+codeberg.org/go-fonts/dejavu v0.4.0 h1:2yn58Vkh4CFK3ipacWUAIE3XVBGNa0y1bc95Bmfx91I=
+codeberg.org/go-fonts/dejavu v0.4.0/go.mod h1:abni088lmhQJvso2Lsb7azCKzwkfcnttl6tL1UTWKzg=
+codeberg.org/go-fonts/latin-modern v0.4.0 h1:vkRCc1y3whKA7iL9Ep0fSGVuJfqjix0ica9UflHORO8=
+codeberg.org/go-fonts/latin-modern v0.4.0/go.mod h1:BF68mZznJ9QHn+hic9ks2DaFl4sR5YhfM6xTYaP9vNw=
+codeberg.org/go-fonts/liberation v0.5.0 h1:SsKoMO1v1OZmzkG2DY+7ZkCL9U+rrWI09niOLfQ5Bo0=
+codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU=
+codeberg.org/go-latex/latex v0.1.0 h1:hoGO86rIbWVyjtlDLzCqZPjNykpWQ9YuTZqAzPcfL3c=
+codeberg.org/go-latex/latex v0.1.0/go.mod h1:LA0q/AyWIYrqVd+A9Upkgsb+IqPcmSTKc9Dny04MHMw=
+codeberg.org/go-pdf/fpdf v0.10.0 h1:u+w669foDDx5Ds43mpiiayp40Ov6sZalgcPMDBcZRd4=
+codeberg.org/go-pdf/fpdf v0.10.0/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU=
+git.sr.ht/~sbinet/cmpimg v0.1.0 h1:E0zPRk2muWuCqSKSVZIWsgtU9pjsw3eKHi8VmQeScxo=
+git.sr.ht/~sbinet/cmpimg v0.1.0/go.mod h1:FU12psLbF4TfNXkKH2ZZQ29crIqoiqTZmeQ7dkp/pxE=
+git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38=
+git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ViaQ/logerr/v2 v2.1.0 h1:8WwzuNa1x+a6tRUl+6sFel83A/QxlFBUaFW2FyG2zzY=
github.com/ViaQ/logerr/v2 v2.1.0/go.mod h1:/qoWLm3YG40Sv5u75s4fvzjZ5p36xINzaxU2L+DJ9uw=
+github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
+github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
+github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
+github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -18,6 +37,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
+github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY=
+github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@@ -58,6 +79,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g=
@@ -159,6 +182,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/vspaz/wls-go v0.0.0-20230405190232-47d1e477c82c h1:gc7YbOdV619w8KYK71jClfbq6m89wJkCVTAko8DNtfY=
+github.com/vspaz/wls-go v0.0.0-20230405190232-47d1e477c82c/go.mod h1:sN2G8r+ME16x0qBg571lKYvJe9dLgY5Kil58P7dm1Vw=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -192,6 +217,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
+golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
+golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -210,6 +237,7 @@ golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
@@ -224,6 +252,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -232,6 +261,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+gonum.org/v1/plot v0.16.0 h1:dK28Qx/Ky4VmPUN/2zeW0ELyM6ucDnBAj5yun7M9n1g=
+gonum.org/v1/plot v0.16.0/go.mod h1:Xz6U1yDMi6Ni6aaXILqmVIb6Vro8E+K7Q/GeeH+Pn0c=
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw=
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs=
@@ -251,6 +284,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4=
@@ -269,6 +303,8 @@ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJ
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.19.6 h1:fuq53qTLQ7aJTA7aNsklNnu7eQtSFqJUomOyM+phPLk=
diff --git a/internal/cmd/forwarder-generator/main.go b/internal/cmd/forwarder-generator/main.go
index 33383e0a63..d1c06fb3ff 100644
--- a/internal/cmd/forwarder-generator/main.go
+++ b/internal/cmd/forwarder-generator/main.go
@@ -19,7 +19,7 @@ import (
// HACK - This command is for development use only
func main() {
- utils.InitLogger("forwarder-generator")
+ utils.InitStaticLogger("forwarder-generator")
yamlFile := flag.String("file", "", "ClusterLogForwarder yaml file. - for stdin")
debugOutput := flag.Bool("debug-output", false, "Generate config normally, but replace output plugins with @stdout plugin, so that records can be printed in collector logs.")
diff --git a/internal/cmd/functional-benchmarker/config/options.go b/internal/cmd/functional-benchmarker/config/options.go
index bc4fa512ca..95af38a62a 100644
--- a/internal/cmd/functional-benchmarker/config/options.go
+++ b/internal/cmd/functional-benchmarker/config/options.go
@@ -24,7 +24,6 @@ type Options struct {
Image string
TotalMessages int
MsgSize int
- Verbosity int
BaseLine bool
DoCleanup bool
Sample bool
@@ -53,7 +52,6 @@ func InitOptions() Options {
//fs.IntVar(&options.TotalMessages, "tot-messages", 10000, "The number of messages to write per stressor")
fs.IntVar(&options.MsgSize, "size", 1024, "The message size in bytes per stressor for 'synthetic' payload")
fs.IntVar(&options.LinesPerSecond, "lines-per-sec", 1, "The log lines per second per stressor")
- fs.IntVar(&options.Verbosity, "verbosity", 0, "The output log level")
fs.BoolVar(&options.DoCleanup, "do-cleanup", true, "set to false to preserve the namespace")
//fs.BoolVar(&options.BaseLine, "baseline", false, "run the test with a baseline config. This supercedes --collector-config")
//fs.StringVar(&options.Platform, "platform", "cluster", "The runtime environment: cluster, local. local requires podman")
diff --git a/internal/cmd/functional-benchmarker/main.go b/internal/cmd/functional-benchmarker/main.go
index aafd7bd216..e8f8b3c80f 100644
--- a/internal/cmd/functional-benchmarker/main.go
+++ b/internal/cmd/functional-benchmarker/main.go
@@ -12,7 +12,6 @@ import (
"github.com/openshift/cluster-logging-operator/internal/constants"
"github.com/openshift/cluster-logging-operator/test/helpers/oc"
- log "github.com/ViaQ/logerr/v2/log/static"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/config"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/reports"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/runners"
@@ -20,10 +19,16 @@ import (
"github.com/openshift/cluster-logging-operator/internal/utils"
)
+var (
+ log = utils.InitLogger("functional-benchmarker")
+)
+
// HACK - This command is for development use only
func main() {
utils.InitLogger("functional-benchmarker")
-
+ defer func() {
+ log.Info("Test complete")
+ }()
options := config.InitOptions()
options.CollectorConfig = config.ReadConfig(options.CollectorConfigPath, options.BaseLine)
@@ -42,6 +47,7 @@ func main() {
options.CollectorConfig = config
reporter := reports.NewReporter(options, artifactDir, metrics, statistics)
+ log.Info("Generating reports...")
reporter.Generate()
}
@@ -49,6 +55,7 @@ func RunBenchmark(artifactDir string, options config.Options) (*stats.ResourceMe
runDuration := config.MustParseDuration(options.RunDuration, "run-duration")
sampleDuration := config.MustParseDuration(options.SampleDuration, "resource-sample-duration")
runner := runners.NewRunner(options)
+ log.Info("Deploying collector, loaders, and receivers")
runner.Deploy()
if options.DoCleanup {
log.V(2).Info("Deferring cleanup", "DoCleanup", options.DoCleanup)
@@ -58,6 +65,7 @@ func RunBenchmark(artifactDir string, options config.Options) (*stats.ResourceMe
startTime := time.Now()
sampler := time.NewTicker(sampleDuration)
metrics := stats.NewResourceMetrics()
+ log.V(0).Info("Starting to sample metrics for the collector...")
go func() {
for {
select {
@@ -76,6 +84,8 @@ func RunBenchmark(artifactDir string, options config.Options) (*stats.ResourceMe
endTime := time.Now()
done <- true
sampler.Stop()
+ log.Info("Stopped sampling metrics")
+ log.Info("Fetching log data from receiver...")
if err := runner.FetchApplicationLogs(); err != nil {
return nil, nil, "", err
}
@@ -105,6 +115,7 @@ func fetchContainerLogs(runner runners.Runner, artifactDir string) {
}
func gatherStatistics(runner runners.Runner, sample bool, msgSize int, startTime, endTime time.Time) *stats.Statistics {
+ log.Info("Evaluating log data to calculate statistics")
logs, err := runner.ReadApplicationLogs()
if err != nil {
log.Error(err, "Error reading logs")
diff --git a/internal/cmd/functional-benchmarker/reports/gnuplot/plot_scripts.go b/internal/cmd/functional-benchmarker/reports/format_templates.go
similarity index 61%
rename from internal/cmd/functional-benchmarker/reports/gnuplot/plot_scripts.go
rename to internal/cmd/functional-benchmarker/reports/format_templates.go
index 4ec4cb5565..c896f77ea0 100644
--- a/internal/cmd/functional-benchmarker/reports/gnuplot/plot_scripts.go
+++ b/internal/cmd/functional-benchmarker/reports/format_templates.go
@@ -1,58 +1,6 @@
-package gnuplot
+package reports
const (
- cpuPlotPNG = `set term png size 1024,768
-set output 'cpu.png'
-set timefmt '%s'
-set xdata time
-set title 'CPU(Cores)'
-set xlabel 'Time'
-plot 'cpu.data' using 1:2 with lines`
-
- memPlotPNG = `set term png size 1024,768
-set output 'mem.png'
-set timefmt '%s'
-set xdata time
-set title 'Mem(Mb)'
-set xlabel 'Time'
-plot 'mem.data' using 1:2 with lines`
-
- latencyPlotPNG = `set term png size 1024,768
-set output 'latency.png'
-set title 'Latency(s)'
-set xlabel 'Message'
-f(x)=m*x+b
-fit f(x) 'latency.data' using 1:2 via m,b
-plot 'latency.data' using 1:2 with lines title 'Data', f(x) title 'Trend'`
-
- lossPlotPNG = `set term png size 1024,768
-set output 'loss.png';
-set xlabel 'SeqId';
-set ylabel 'Lost Count'`
-
- lossPlotDumb = `set term dumb
-set xlabel 'SeqId';
-set ylabel 'Lost Count'`
-
- cpuPlotDumb = `set term dumb
-set timefmt '%s'
-set xdata time
-set title 'CPU(Cores)'
-set xlabel 'Time'
-plot 'cpu.data' using 1:2 with lines`
-
- memPlotDumb = `set term dumb
-set timefmt '%s'
-set xdata time
-set title 'Mem(Mb)'
-set xlabel 'Time'
-plot 'mem.data' using 1:2 with lines`
-
- latencyPlotDumb = `set term dumb
-set title 'Latency(s)'
-set xlabel 'Message'
-plot 'latency.data' using 1:2 with lines`
-
html = `
@@ -98,15 +46,23 @@ plot 'latency.data' using 1:2 with lines`
+
+
+
+
+
+
+
+
diff --git a/internal/cmd/functional-benchmarker/reports/gnuplot/gnuplot.go b/internal/cmd/functional-benchmarker/reports/gnuplot/gnuplot.go
deleted file mode 100644
index 25d7113ae2..0000000000
--- a/internal/cmd/functional-benchmarker/reports/gnuplot/gnuplot.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package gnuplot
-
-import (
- "fmt"
- htmllib "html"
- "io"
- "os"
- "os/exec"
- "path"
- "strings"
- "text/tabwriter"
- "time"
-
- log "github.com/ViaQ/logerr/v2/log/static"
- "github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/config"
- "github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/stats"
-)
-
-type GNUPlotReporter struct {
- Options config.Options
- Metrics stats.ResourceMetrics
- Stats stats.Statistics
- ArtifactDir string
-}
-
-func exportResourceMetricTo(outDir string, rm stats.ResourceMetrics) {
- exportCPU(outDir, rm.Samples)
- exportMemory(outDir, rm.Samples)
-}
-
-/* #nosec G306*/
-func exportLatency(outDir string, logs stats.PerfLogs) {
- log.V(3).Info("Exporting latency")
- buffer := []string{}
- for i, log := range logs {
- value := log.ElapsedEpoc()
- buffer = append(buffer, fmt.Sprintf("%d %.3f", i, value))
- }
- log.V(3).Info("Writing latency data", "outDir", outDir, "data", buffer)
- err := os.WriteFile(path.Join(outDir, "latency.data"), []byte(strings.Join(buffer, "\n")), 0755)
- if err != nil {
- log.Error(err, "Error writing latency data")
- }
-}
-
-/* #nosec G306*/
-func exportMemory(outDir string, samples []stats.Sample) {
- log.V(3).Info("Exporting memory", "samples", samples)
- buffer := []string{}
- for _, sample := range samples {
- value := sample.MemoryBytesAsFloat()
- buffer = append(buffer, fmt.Sprintf("%d %.3f", sample.Time, value/1024/1024))
- }
- log.V(3).Info("Writing resource metric data", "outDir", outDir, "memoryInMb", buffer)
- err := os.WriteFile(path.Join(outDir, "mem.data"), []byte(strings.Join(buffer, "\n")), 0755)
- if err != nil {
- log.Error(err, "Error writing resource Memory Metrics")
- }
-}
-
-/* #nosec G306*/
-func exportCPU(outDir string, samples []stats.Sample) {
- log.V(3).Info("Exporting cpu", "samples", samples)
- buffer := []string{}
- for _, sample := range samples {
- cpu := sample.CPUCoresAsFloat()
- buffer = append(buffer, fmt.Sprintf("%d %.3f", sample.Time, cpu))
- }
- log.V(3).Info("Writing resource metric data", "outDir", outDir, "cpu", buffer)
- err := os.WriteFile(path.Join(outDir, "cpu.data"), []byte(strings.Join(buffer, "\n")), 0755)
- if err != nil {
- log.Error(err, "Error writing resource CPU Metrics")
- }
-}
-
-/* #nosec G306*/
-func exportLoss(outDir string, samples stats.LossStats) {
- log.V(3).Info("Exporting message losses", "samples", samples)
- buffer := []string{}
- for _, stream := range samples.Streams() {
- streamStats, err := samples.LossStatsFor(stream)
- if err != nil {
- log.Error(err, "Unable to generate stats", "stream", stream)
- return
- }
- if len(streamStats.Entries) == 0 {
- log.V(0).Info("No entries returned for stream", "stream", stream, "streamStats", streamStats)
- continue
- }
- lostLogs := 0
- i := 0
- for expSeqId := streamStats.MinSeqId; expSeqId <= streamStats.MaxSeqId; expSeqId++ {
- seqId := streamStats.Entries[i].SequenceId
- if seqId != expSeqId {
- lostLogs += 1
- } else {
- i += 1 //found entry
- }
- buffer = append(buffer, fmt.Sprintf("%d %d", expSeqId, lostLogs))
- }
-
- log.V(3).Info("Writing message losses data", "outDir", outDir, "losses", buffer)
- err = os.WriteFile(path.Join(outDir, fmt.Sprintf("%s-loss.data", stream)), []byte(strings.Join(buffer, "\n")), 0755)
- if err != nil {
- log.Error(err, "Error writing message loss metrics", "stream", stream)
- }
-
- }
-}
-
-func formatLossPlot(base string, samples stats.LossStats) string {
- buffer := base
- for i, stream := range samples.Streams() {
- if i == 0 {
- buffer = fmt.Sprintf("%s;plot '%s-loss.data' using 1:2 title '%s' with lines", buffer, stream, stream)
- } else {
- buffer = fmt.Sprintf("%s,'%s-loss.data' using 1:2 title '%s' with lines", buffer, stream, stream)
- }
- }
- return buffer
-}
-
-func (r *GNUPlotReporter) Generate() {
- exportResourceMetricTo(r.ArtifactDir, r.Metrics)
- exportLatency(r.ArtifactDir, r.Stats.Logs)
-
- for _, plot := range []string{memPlotPNG, cpuPlotPNG, latencyPlotPNG} {
- plotData(plot, r.ArtifactDir, nil)
- }
-
- for _, plot := range []string{memPlotDumb, cpuPlotDumb, latencyPlotDumb} {
- plotData(plot, r.ArtifactDir, os.Stdout)
- }
-
- exportLoss(r.ArtifactDir, r.Stats.Losses)
- plotData(formatLossPlot(lossPlotPNG, r.Stats.Losses), r.ArtifactDir, nil)
- plotData(formatLossPlot(lossPlotDumb, r.Stats.Losses), r.ArtifactDir, os.Stdout)
-
- r.generateStats()
-
-}
-
-func plotData(plot, dir string, writer io.Writer) {
- plot = strings.Join(strings.Split(plot, "\n"), ";")
- log.V(3).Info("running gnuplot", "cmd", plot)
- cmd := exec.Command("gnuplot", "-e", plot)
- cmd.Dir = dir
- if writer != nil {
- cmd.Stdout = writer
- }
-
- err := cmd.Run()
- if err != nil {
- log.Error(err, "Error starting command", "dir", cmd.Dir, "cmd", cmd.String())
- }
-}
-
-/* #nosec G306*/
-func (r *GNUPlotReporter) generateStats() {
- reports := map[string]string{
- "results.html": html,
- "readme.md": markdown,
- }
- s := r.Stats
- o := r.Options
-
- var lossFmtFun func() string
- var escapeFn func(content string) string
- for file, template := range reports {
- if template == html {
- escapeFn = htmllib.EscapeString
- lossFmtFun = func() string {
- losses := ""
- for _, name := range s.Losses.Streams() {
- streamLoss, _ := s.Losses.LossStatsFor(name)
- losses += fmt.Sprintf("
%s | %d | %d | %d | %d | %.1f%% |
",
- name,
- streamLoss.MinSeqId,
- streamLoss.MaxSeqId,
- streamLoss.Purged,
- streamLoss.Collected,
- streamLoss.PercentCollected())
- }
- return losses
- }
- }
- if template == markdown {
- escapeFn = func(content string) string {
- return "```\n" + content + "\n```"
- }
- lossFmtFun = func() string {
- losses := ""
- for _, name := range s.Losses.Streams() {
- streamLoss, _ := s.Losses.LossStatsFor(name)
- losses += fmt.Sprintf("| %s|%d|%d|%d|%d|%.1f%%\n",
- name,
- streamLoss.MinSeqId,
- streamLoss.MaxSeqId,
- streamLoss.Purged,
- streamLoss.Collected,
- streamLoss.PercentCollected())
- }
- return losses
- }
- }
- out := fmt.Sprintf(template,
- o.Image,
- o.TotalLogStressors,
- o.LinesPerSecond,
- o.RunDuration,
- o.PayloadSource,
- s.TotMessages(),
- s.MsgSize,
- s.Elapsed.Round(time.Second),
- s.Mean(),
- s.Min(),
- s.Max(),
- s.Median(),
- lossFmtFun(),
- escapeFn(o.CollectorConfig),
- )
- err := os.WriteFile(path.Join(r.ArtifactDir, file), []byte(out), 0755)
- if err != nil {
- log.Error(err, "Error writing file")
- }
- }
- writeStatsToConsole(s)
-}
-func writeStatsToConsole(s stats.Statistics) {
- w := new(tabwriter.Writer)
- // minwidth, tabwidth, padding, padchar, flags
- w.Init(os.Stdout, 3, 2, 2, ' ', tabwriter.AlignRight)
-
- defer w.Flush()
- div := "--------"
- headerFmt := "\n %s\t%s\t%s\t%s\t%s\t%s\t%s\t"
-
- fmt.Fprintf(w, "Latency of logs collected based on the time the log was generated and ingested")
- fmt.Fprintf(w, headerFmt, "Total", "Size", "Elapsed", "Mean", "Min", "Max", "Median")
- fmt.Fprintf(w, headerFmt, "Msg", "(bytes)", "", "(s)", "(s)", "(s)", "(s)")
- fmt.Fprintf(w, headerFmt, div, div, div, div, div, div, div)
-
- fmt.Fprintf(w, "\n %d\t%d\t%s\t%.3f\t%.3f\t%.3f\t%.3f\t",
- s.TotMessages(),
- s.MsgSize,
- s.Elapsed.Round(time.Second),
- s.Mean(),
- s.Min(),
- s.Max(),
- s.Median())
-
- fmt.Fprintf(w, "\n")
-
- headerFmt = "\n %s\t%s\t%s\t%s\t%s\t%s\t"
- fmt.Fprintf(w, "\nPercent logs lost between first and last collected sequence ids")
- fmt.Fprintf(w, headerFmt, "Stream", "Min", "Max", "Purged", "Collected", "Per. Coll.")
- fmt.Fprintf(w, headerFmt, div, div, div, div, div, div)
- for _, name := range s.Losses.Streams() {
- streamLoss, _ := s.Losses.LossStatsFor(name)
- fmt.Fprintf(w, "\n%s\t%d\t%d\t%d\t%d\t\t%.1f%%\n",
- name,
- streamLoss.MinSeqId,
- streamLoss.MaxSeqId,
- streamLoss.Purged,
- streamLoss.Collected,
- streamLoss.PercentCollected())
- }
- fmt.Fprintf(w, "\n")
-}
diff --git a/internal/cmd/functional-benchmarker/reports/gonumplot/init.go b/internal/cmd/functional-benchmarker/reports/gonumplot/init.go
new file mode 100644
index 0000000000..7de6bc1257
--- /dev/null
+++ b/internal/cmd/functional-benchmarker/reports/gonumplot/init.go
@@ -0,0 +1,9 @@
+package gonumplot
+
+import (
+ "github.com/openshift/cluster-logging-operator/internal/utils"
+)
+
+var (
+ log = utils.InitLogger("gonumplut")
+)
diff --git a/internal/cmd/functional-benchmarker/reports/gonumplot/plotter.go b/internal/cmd/functional-benchmarker/reports/gonumplot/plotter.go
new file mode 100644
index 0000000000..ec2bcbf6af
--- /dev/null
+++ b/internal/cmd/functional-benchmarker/reports/gonumplot/plotter.go
@@ -0,0 +1,191 @@
+package gonumplot
+
+import (
+ "fmt"
+ "github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/stats"
+ "github.com/vspaz/wls-go/pkg/models"
+ "gonum.org/v1/plot"
+ "gonum.org/v1/plot/plotter"
+ "gonum.org/v1/plot/plotutil"
+ "gonum.org/v1/plot/vg"
+ "path"
+)
+
+var (
+ defaultWidth = vg.Points(768)
+ defaultHeight = vg.Points(576)
+
+ megaBytesPerByte = 1.0 / float64(1024) / float64(1024)
+)
+
+type GoNumPlot struct {
+ Metrics stats.ResourceMetrics
+ Stats stats.Statistics
+ ArtifactDir string
+}
+
+func (p GoNumPlot) Plot() {
+ cpu, memory := extractPlotData(p.Metrics.Samples)
+ p.exportCpuPlot(cpu)
+ p.exportMemoryPlot(memory)
+ exportLatencyPlot(p.ArtifactDir, p.Stats.Losses)
+ exportLossStatsPlot(p.ArtifactDir, p.Stats.Losses)
+}
+
+func exportLatencyPlot(outDir string, stats stats.LossStats) {
+ aPlot := plot.New()
+
+ aPlot.Title.Text = "Latency"
+ aPlot.Legend.Top = true
+ aPlot.X.Label.Text = "Message"
+ aPlot.Y.Label.Text = "Seconds"
+
+ var data []interface{}
+ for i, stream := range stats.Streams() {
+ if streamState, err := stats.LossStatsFor(stream); err == nil {
+ var xs []float64
+ var ys []float64
+ var xys plotter.XYs
+ for i, entry := range streamState.Entries {
+ xs = append(xs, float64(i))
+ ys = append(ys, entry.ElapsedEpoc())
+ xys = append(xys, plotter.XY{
+ X: float64(i),
+ Y: entry.ElapsedEpoc(),
+ })
+ }
+ data = append(data, xys)
+
+ wls := models.NewWlsWithoutWeights(xs, ys)
+ point := wls.FitLinearRegression()
+ slope := point.GetSlope()
+ yIntercept := point.GetIntercept()
+
+ fnLinear := plotter.NewFunction(func(x float64) float64 {
+ return slope*x + yIntercept
+ })
+ fnLinear.Color = plotutil.Color(i)
+
+ aPlot.Add(fnLinear)
+ aPlot.Legend.Add(fmt.Sprintf("%s trend", stream), fnLinear)
+ } else {
+ log.V(0).Error(err, "Unable to calculate latency", "stream", stream)
+ }
+ }
+ if err := plotutil.AddLinePoints(aPlot, data...); err != nil {
+ panic(err)
+ }
+
+ if err := aPlot.Save(defaultWidth, defaultHeight, path.Join(outDir, "latency.png")); err != nil {
+ panic(err)
+ }
+}
+
+func (p GoNumPlot) exportMemoryPlot(data plotter.XYs) {
+ log.V(3).Info("Generating Memory Plot", "data", data)
+ aPlot := plot.New()
+
+ aPlot.Title.Text = "Mem"
+ aPlot.X.Label.Text = "Time(m)"
+ aPlot.Y.Label.Text = "Megabytes"
+
+ if err := plotutil.AddLinePoints(
+ aPlot,
+ "Mem",
+ data,
+ ); err != nil {
+ panic(err)
+ }
+
+ if err := aPlot.Save(defaultWidth, defaultHeight, path.Join(p.ArtifactDir, "mem.png")); err != nil {
+ panic(err)
+ }
+}
+
+func (p GoNumPlot) exportCpuPlot(data plotter.XYs) {
+ log.V(3).Info("Generating CPU Plot", "data", data)
+ aPlot := plot.New()
+
+ aPlot.Title.Text = "CPU"
+ aPlot.X.Label.Text = "Time(m)"
+ aPlot.Y.Label.Text = "Cores"
+
+ if err := plotutil.AddLinePoints(
+ aPlot,
+ "CPU",
+ data,
+ ); err != nil {
+ panic(err)
+ }
+
+ if err := aPlot.Save(defaultWidth, defaultHeight, path.Join(p.ArtifactDir, "cpu.png")); err != nil {
+ panic(err)
+ }
+}
+
+func extractPlotData(samples []stats.Sample) (cpu, memory plotter.XYs) {
+ var first int64
+ for i, sample := range samples {
+ if i == 0 {
+ first = sample.Time
+ }
+ timeSample := float64(sample.Time-first) / 60.0
+ cpu = append(cpu, plotter.XY{
+ X: timeSample,
+ Y: sample.CPUCoresAsFloat(),
+ })
+
+ memory = append(memory, plotter.XY{
+ X: timeSample,
+ Y: sample.MemoryBytesAsFloat() * megaBytesPerByte,
+ })
+ }
+ return cpu, memory
+}
+
+func exportLossStatsPlot(outDir string, samples stats.LossStats) {
+ log.Info("Exporting message losses")
+ aPlot := plot.New()
+ aPlot.Title.Text = "Percent Collected Per Stream"
+ aPlot.Legend.Top = true
+ aPlot.X.Label.Text = "SeqId"
+ aPlot.Y.Label.Text = "Per. Collected"
+ aPlot.Y.Min = 0
+
+ var data []interface{}
+ for _, stream := range samples.Streams() {
+ streamStats, err := samples.LossStatsFor(stream)
+ if err != nil {
+ log.Error(err, "Unable to generate stats", "stream", stream)
+ return
+ }
+ if len(streamStats.Entries) == 0 {
+ log.V(0).Info("No entries returned for stream", "stream", stream, "streamStats", streamStats)
+ continue
+ }
+ lostLogs := 0
+ i := 0
+ var xys plotter.XYs
+
+ minID := streamStats.MinSeqId
+
+ for expSeqId := streamStats.MinSeqId; expSeqId <= streamStats.MaxSeqId; expSeqId++ {
+ seqId := streamStats.Entries[i].SequenceId
+ if seqId != expSeqId {
+ lostLogs += 1
+ } else {
+ i += 1 //found entry
+ }
+ per := float64(i) / float64(expSeqId-minID+1) * 100.0
+ xys = append(xys, plotter.XY{X: float64(expSeqId), Y: per})
+ }
+ log.V(3).Info("Adding loss stats to plot", "xys", xys, "stream", "stream")
+ data = append(data, stream, xys)
+ }
+ if err := plotutil.AddLinePoints(aPlot, data...); err != nil {
+ panic(err)
+ }
+ if err := aPlot.Save(defaultWidth, defaultHeight, path.Join(outDir, "loss.png")); err != nil {
+ panic(err)
+ }
+}
diff --git a/internal/cmd/functional-benchmarker/reports/report.go b/internal/cmd/functional-benchmarker/reports/report.go
index 45e943e87f..4ba6822568 100644
--- a/internal/cmd/functional-benchmarker/reports/report.go
+++ b/internal/cmd/functional-benchmarker/reports/report.go
@@ -1,20 +1,122 @@
package reports
import (
+ "fmt"
+ log "github.com/ViaQ/logerr/v2/log/static"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/config"
- "github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/reports/gnuplot"
+ "github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/reports/gonumplot"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/stats"
+ htmllib "html"
+ "os"
+ "path"
+ "time"
)
type Report interface {
Generate()
}
+type Plotter interface {
+ Plot()
+}
+
func NewReporter(options config.Options, artifactDir string, metrics *stats.ResourceMetrics, statistics *stats.Statistics) Report {
- return &gnuplot.GNUPlotReporter{
+ return &Reporter{
Options: options,
+ Stats: *statistics,
+ ArtifactDir: artifactDir,
+ Plotter: NewPlotter(artifactDir, metrics, statistics),
+ }
+}
+
+func NewPlotter(artifactDir string, metrics *stats.ResourceMetrics, statistics *stats.Statistics) Plotter {
+ return &gonumplot.GoNumPlot{
Metrics: *metrics,
Stats: *statistics,
ArtifactDir: artifactDir,
}
}
+
+type Reporter struct {
+ Options config.Options
+ Stats stats.Statistics
+ Plotter Plotter
+ ArtifactDir string
+}
+
+func (r *Reporter) Generate() {
+ r.Plotter.Plot()
+ r.generateReports()
+}
+
+/* #nosec G306*/
+func (r *Reporter) generateReports() {
+ log.Info("Generating stats reports")
+ reports := map[string]string{
+ "results.html": html,
+ "readme.md": markdown,
+ }
+ s := r.Stats
+ o := r.Options
+
+ var lossFmtFun func() string
+ var escapeFn func(content string) string
+ for file, template := range reports {
+ if template == html {
+ escapeFn = htmllib.EscapeString
+ lossFmtFun = func() string {
+ losses := ""
+ for _, name := range s.Losses.Streams() {
+ streamLoss, _ := s.Losses.LossStatsFor(name)
+ losses += fmt.Sprintf("
%s | %d | %d | %d | %d | %.1f%% |
",
+ name,
+ streamLoss.MinSeqId,
+ streamLoss.MaxSeqId,
+ streamLoss.Purged,
+ streamLoss.Collected,
+ streamLoss.PercentCollected())
+ }
+ return losses
+ }
+ }
+ if template == markdown {
+ escapeFn = func(content string) string {
+ return "```\n" + content + "\n```"
+ }
+ lossFmtFun = func() string {
+ losses := ""
+ for _, name := range s.Losses.Streams() {
+ streamLoss, _ := s.Losses.LossStatsFor(name)
+ losses += fmt.Sprintf("| %s|%d|%d|%d|%d|%.1f%%\n",
+ name,
+ streamLoss.MinSeqId,
+ streamLoss.MaxSeqId,
+ streamLoss.Purged,
+ streamLoss.Collected,
+ streamLoss.PercentCollected())
+ }
+ return losses
+ }
+ }
+ out := fmt.Sprintf(template,
+ o.Image,
+ o.TotalLogStressors,
+ o.LinesPerSecond,
+ o.RunDuration,
+ o.PayloadSource,
+ s.TotMessages(),
+ s.MsgSize,
+ s.Elapsed.Round(time.Second),
+ s.Mean(),
+ s.Min(),
+ s.Max(),
+ s.Median(),
+ lossFmtFun(),
+ escapeFn(o.CollectorConfig),
+ )
+ err := os.WriteFile(path.Join(r.ArtifactDir, file), []byte(out), 0755)
+ if err != nil {
+ log.Error(err, "Error writing file")
+ }
+ }
+}
diff --git a/internal/cmd/functional-benchmarker/runners/cluster/cluster_runner.go b/internal/cmd/functional-benchmarker/runners/cluster/cluster_runner.go
index 4aa7ac219f..908888301b 100644
--- a/internal/cmd/functional-benchmarker/runners/cluster/cluster_runner.go
+++ b/internal/cmd/functional-benchmarker/runners/cluster/cluster_runner.go
@@ -14,7 +14,6 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
- log "github.com/ViaQ/logerr/v2/log/static"
obs "github.com/openshift/cluster-logging-operator/api/observability/v1"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/config"
"github.com/openshift/cluster-logging-operator/internal/cmd/functional-benchmarker/stats"
@@ -60,7 +59,7 @@ func (r *ClusterRunner) Deploy() {
testClient.Close()
}
}
- r.framework = functional.NewCollectorFunctionalFrameworkUsing(&testClient.Test, cleanup, r.Verbosity)
+ r.framework = functional.NewCollectorFunctionalFrameworkUsing(&testClient.Test, cleanup, 0)
r.framework.Conf = r.CollectorConfig
obsruntime.NewClusterLogForwarderBuilder(r.framework.Forwarder).
@@ -68,7 +67,17 @@ func (r *ClusterRunner) Deploy() {
spec.Type = obs.InputTypeApplication
spec.Application = &obs.Application{
Includes: []obs.NamespaceContainerSpec{
- {Namespace: r.Namespace()},
+ {
+ Namespace: r.Namespace(),
+ },
+ },
+ Excludes: []obs.NamespaceContainerSpec{
+ {
+ Container: "collector",
+ },
+ {
+ Container: "http",
+ },
},
}
}).
diff --git a/internal/cmd/functional-benchmarker/runners/cluster/init.go b/internal/cmd/functional-benchmarker/runners/cluster/init.go
new file mode 100644
index 0000000000..192b4a970b
--- /dev/null
+++ b/internal/cmd/functional-benchmarker/runners/cluster/init.go
@@ -0,0 +1,9 @@
+package cluster
+
+import (
+ "github.com/openshift/cluster-logging-operator/internal/utils"
+)
+
+var (
+ log = utils.InitLogger("cluster")
+)
diff --git a/internal/cmd/functional-benchmarker/stats/init.go b/internal/cmd/functional-benchmarker/stats/init.go
new file mode 100644
index 0000000000..65eee2b5f2
--- /dev/null
+++ b/internal/cmd/functional-benchmarker/stats/init.go
@@ -0,0 +1,9 @@
+package stats
+
+import (
+ "github.com/openshift/cluster-logging-operator/internal/utils"
+)
+
+var (
+ log = utils.InitLogger("stats")
+)
diff --git a/internal/cmd/functional-benchmarker/stats/sample.go b/internal/cmd/functional-benchmarker/stats/sample.go
index 79ba5b125c..bb5d5645a0 100644
--- a/internal/cmd/functional-benchmarker/stats/sample.go
+++ b/internal/cmd/functional-benchmarker/stats/sample.go
@@ -4,8 +4,6 @@ import (
"math"
"regexp"
"strconv"
-
- log "github.com/ViaQ/logerr/v2/log/static"
)
var (
diff --git a/internal/cmd/functional-benchmarker/stats/types.go b/internal/cmd/functional-benchmarker/stats/types.go
index 6410034902..df064b405c 100644
--- a/internal/cmd/functional-benchmarker/stats/types.go
+++ b/internal/cmd/functional-benchmarker/stats/types.go
@@ -1,30 +1,33 @@
package stats
import (
- log "github.com/ViaQ/logerr/v2/log/static"
+ "github.com/openshift/cluster-logging-operator/test"
"github.com/openshift/cluster-logging-operator/test/helpers/types"
- "regexp"
- "strconv"
- "strings"
-)
-
-var (
- perfLogPattern = regexp.MustCompile(`.*epoc_in\":(?P[0-9\.]*).*epoc_out\":(?P[0-9\.]*).*message\":\"(?P.*(?Pfunctional((\.0)?\.[0-9A-Z]*)?) - (?P\d{10}) -.*?\").*?`)
)
type PerfLog struct {
- Stream string
types.Timing
- SequenceId int
- // Bloat is the ratio of overall size / Message size
- bloat float64
+ // ContainerName is the name of the container producing the logstream
+ ContainerName string `json:"container_name,omitempty"`
+
+ // Message is the receiver processed messsage, not the original message
+ Message string `json:"message,omitempty"`
+
+ // MessageSize is the original message size before it was processed by the receiver
+ MessageSize int `json:"message_size,omitempty"`
+
+ // PayloadSize is the original payload size before it was processed by the receiver
+ PayloadSize int `json:"payload_size,omitempty"`
+
+ Stream string
+ SequenceId int `json:"seqid,omitempty"`
}
type PerfLogs []PerfLog
func (t *PerfLog) Bloat() float64 {
- return t.bloat
+ return float64(t.PayloadSize) / float64(t.MessageSize)
}
func (t *PerfLog) ElapsedEpoc() float64 {
return t.EpocOut - t.EpocIn
@@ -32,41 +35,13 @@ func (t *PerfLog) ElapsedEpoc() float64 {
// NewPerfLog creates a PerfLog from a line parsing it or returning nil if there is an error
func NewPerfLog(line string) *PerfLog {
- match := perfLogPattern.FindStringSubmatch(line)
- if len(match) > 0 {
- entry := PerfLog{}
- for i, name := range perfLogPattern.SubexpNames() {
- switch name {
- case "message":
- entry.bloat = float64(len(line)) / float64(len(match[i]))
- case "stream":
- entry.Stream = match[i]
- case "seqid":
- seqId, err := strconv.Atoi(strings.TrimSpace(match[i]))
- if err != nil {
- log.Error(err, "Skipping entry. Unable to parse sequence id", "match", match[i], "line", line)
- return nil
- }
- entry.SequenceId = seqId
- case "epoc_out":
- epocOut, err := strconv.ParseFloat(strings.TrimSpace(match[i]), 64)
- if err != nil {
- log.Error(err, "Skipping entry. Unable to parse epic_out", "match", match[i], "line", line)
- return nil
- }
- entry.EpocOut = epocOut
- case "epoc_in":
- epicIn, err := strconv.ParseFloat(strings.TrimSpace(match[i]), 64)
- if err != nil {
- log.Error(err, "Skipping entry. Unable to parse epic_in", "match", match[i], "line", line)
- return nil
- }
- entry.EpocIn = epicIn
- }
- }
-
- return &entry
+ entry := &PerfLog{}
+ log.V(4).Info("Unmarshalling", "line", line)
+ if err := test.Unmarshal(line, entry); err != nil {
+ log.V(4).Info("Failed to unmarshall perflog", "line", line)
+ return nil
}
- log.V(4).Info("Failed to match perflog", "line", line)
- return nil
+ entry.Stream = entry.ContainerName
+ log.V(4).Info("Returning", "perfLog", entry)
+ return entry
}
diff --git a/internal/cmd/functional-benchmarker/stats/types_test.go b/internal/cmd/functional-benchmarker/stats/types_test.go
index 79a1e4d705..784ae3894d 100644
--- a/internal/cmd/functional-benchmarker/stats/types_test.go
+++ b/internal/cmd/functional-benchmarker/stats/types_test.go
@@ -7,14 +7,14 @@ import (
var _ = Describe("Evaluating log loss stats", func() {
- var sample = `{"@timestamp":"2023-06-09T16:48:18.929938124+00:00","docker":{"container_id":"8d5fb743542b8c13afb0d5d3cf4cb52e724750d63de58006f16784c9c00da641"},"epoc_in":1682023305.6504774,"epoc_out":1686329299.934293,"hostname":"ip-10-0-173-26.us-east-2.compute.internal","kubernetes":{"container_image":"quay.io/openshift-logging/cluster-logging-load-client:latest","container_image_id":"quay.io/openshift-logging/cluster-logging-load-client@sha256:c8682432425be4b6f64821f0634fb1150b7cf805da0fa724b6047135b9d4d783","container_name":"loader-0","flat_labels":["test-client=true","testname=functional","testtype=functional"],"host":"ip-10-0-173-26.us-east-2.compute.internal","labels":{"test-client":"true","testname":"functional","testtype":"functional"},"master_url":"https://kubernetes.default.svc","namespace_id":"1dca9c0d-1365-4090-9bb3-80fda9b5fec6","namespace_labels":{"kubernetes_io_metadata_name":"testhack-imh2tzge","pod-security_kubernetes_io_enforce":"privileged","security_openshift_io_scc_podSecurityLabelSync":"false","test-client":"true"},"namespace_name":"testhack-imh2tzge","pod_id":"ca9b1dbf-84f3-4aa5-a876-46c0f4bba186","pod_ip":"10.131.0.21","pod_name":"functional"},"level":"unknown","log_type":"application","message":"goloader seq - functional.0.00000000000000002A536241AD427647 - 0000000123 - hvFtZpIOtnnhugEaqJqWWHqCmVCQXExRcOnXEaGpwWgIUlRjtCXLhmQUuqgnpStPjMudPrjUFRBBqolWCNCXdGrpvCqIclJzokNTrQgSUDKmrisDaohrCGDEHeihthYcAyUXmxlQHTkWEfViIVtQHoCQEBDFFWXJfKFqrgpIjgAdqBYeillNOikhURuwFZTEmwcWLElnrlBkZICapoGmFNeBxotMRQXGQLtntyCDiYjiihtvutkzbnHixjFuXKWkhWJbzHiVTuFJvYDlXBKfqGVQejokSwYueuDCdoAxyZCLglsVPijCEmjjGQaKLzlMYZApIOcZdeWVYIWZszhVDDfXArvuVxIdCtKSWMkQJXVuukvkSqKZbkQFcvaZdbDINbYgDAXOPMlYdGTULIwQdTSYyLIlSVyrxSZCnjZfAUhOTObIAXOZJhoJOaKmOpMqzLgYgSaZBaWiMcczEXVzVVXOsjdUKNJgjmdoyhvjcRbGQcLQNpRuTRsgaTbgnziKpEOVlngQEKDIkelRRhdErcIKisDQYNOxhIOysuJXDVYKILOLvritsLpqMJFGuBJjUHcJamedAMPGzkGidwrPWZeScywFftuevYThNNTzNqaQAAyYoSpHbmoZomqSYtDxAfnpCHAOBidVMwMXNLMHUuvrGVCdRwvEignmJOqaPCnYzFSbfZQFjFauIQfjCCnRvnQHPrCKPbnDWhuphjFIFJwjFKKqqmfDzaxizIoEjCHkBGWTEfEKfDYBKhwHfqLRBsGidLzdmAzUImEqWBUDFXWCHBhLIGlyQvGOLDSBymDfydqGoqxtlwVJNzjQdGTExPgBRxQZpVuqpOXGCHIGzjvBmggNSwWqHoxsxexAmjhtfIFrhHFkpkfYlcBTOyxetSvtVCmpAsAwGTRsFmkueLsgFeTqWYiLznDvYWtyXDRBLqwqepDsPPMRslWLYhIWuPRNTWXKsfNbWXpfigOtShXEIPCSEArirHpLLeamyQJOWkIsNWRdErHMpRpzHZXu","openshift":{"cluster_id":"functional","sequence":21526},"path":"/","pipeline_metadata":{"collector":{"inputname":"fluent-plugin-systemd","ipaddr4":"10.131.0.21","name":"fluentd","received_at":"2023-06-09T16:48:18.930687+00:00","version":"1.14.6 1.6.0"}},"source_type":"http_server","timestamp":"2023-06-09T16:48:19.933871646Z","viaq_msg_id":"NGFlNDVhNzItN2ZjZi00Nzc3LTliMzItOTlmZWEyODliYWJj"}`
+ var sample = `{"container_name":"loader-0","epoc_in":1742334136.8465972,"epoc_out":1742334154.0828154,"message":"goloader seq - functional.0000000000000000C08D75201BF50A40 - 0000000001","message_size":586,"payload_size":2616,"seqid":1}`
It("NewPerfLog", func() {
log := NewPerfLog(sample)
- Expect(log.Bloat()).To(BeNumerically("~", 2.4, 0.1))
- Expect(log.SequenceId).To(Equal(123))
- Expect(log.EpocIn).To(Equal(1682023305.6504774))
- Expect(log.EpocOut).To(Equal(1686329299.934293))
- Expect(log.Stream).To(Equal("functional.0.00000000000000002A536241AD427647"))
+ Expect(log.Bloat()).To(BeNumerically("~", 4.4, 0.1))
+ Expect(log.SequenceId).To(Equal(1))
+ Expect(log.EpocIn).To(Equal(1742334136.8465972))
+ Expect(log.EpocOut).To(Equal(1742334154.0828154))
+ Expect(log.Stream).To(Equal("loader-0"))
})
})
diff --git a/internal/utils/logger.go b/internal/utils/logger.go
index 00a13f7e6b..d7d31e69e1 100644
--- a/internal/utils/logger.go
+++ b/internal/utils/logger.go
@@ -16,8 +16,6 @@ const (
)
// InitLogger creates a logger and optionally initializes the verbosity with the value in LOG_LEVEL.
-//
-// It also replaces the static logger with the newly-created logger.
func InitLogger(component string) logr.Logger {
verbosity := defaultLoggerVerbosity
if rawVerbosity, ok := os.LookupEnv(envLogLevel); ok {
@@ -28,8 +26,13 @@ func InitLogger(component string) logr.Logger {
verbosity = envVerbosity
}
+ return log.NewLogger(component, log.WithVerbosity(verbosity))
+}
- logger := log.NewLogger(component, log.WithVerbosity(verbosity))
+// InitStaticLogger creates a logger and optionally initializes the verbosity with the value in LOG_LEVEL
+// and replaces the static logger with the newly-created logger.
+func InitStaticLogger(component string) logr.Logger {
+ logger := InitLogger(component)
static.SetLogger(logger)
return logger
}
diff --git a/test/framework/functional/output_http.go b/test/framework/functional/output_http.go
index fc0445e1fc..277b69a464 100644
--- a/test/framework/functional/output_http.go
+++ b/test/framework/functional/output_http.go
@@ -21,8 +21,8 @@ import (
)
const (
- VectorHttpSourceBenchmarkConfTemplate = "" +
- `[sources.my_source]
+ VectorHttpSourceBenchmarkConfTemplate = `
+[sources.my_source]
type = "http_server"
address = "127.0.0.1:8090"
decoding.codec = "json"
@@ -45,7 +45,7 @@ crt_file = "/tmp/secrets/http/tls.crt"
type = "remap"
inputs = ["my_source"]
source = '''
- .epoc_out = to_float(now())
+ epoc_out = to_float(now())
mytime, err = parse_timestamp(."@timestamp", format: "%Y-%m-%dT%H:%M:%S%.fZ")
if err != null {
mytime, err = parse_timestamp(."@timestamp", format: "%Y-%m-%dT%H:%M:%S%.f%z")
@@ -53,8 +53,23 @@ source = '''
log("Unable to parse @timestamp: " + err, level: "error")
}
}
- .epoc_in = to_float(mytime)
-
+ epoc_in = to_float(mytime)
+
+ content = parse_regex!(.message,r'(?goloader seq - functional\.[0-9A-Z]* - (?[0-9]{10}))')
+ message = to_string(content.sub)
+ container_name = .kubernetes.container_name
+ message_size = length!(.message)
+ payload_size = length(encode_json(.))
+
+ . = {
+ "epoc_in": epoc_in,
+ "epoc_out": epoc_out,
+ "message": to_string(message),
+ "container_name": container_name,
+ "message_size": message_size,
+ "payload_size": payload_size,
+ "seqid": to_int!(content.seqid)
+ }
'''
[sinks.my_sink]
@@ -227,7 +242,7 @@ func (f *CollectorFunctionalFramework) AddFluentdHttpOutput(b *runtime.PodBuilde
}
func (f *CollectorFunctionalFramework) AddBenchmarkForwardOutput(b *runtime.PodBuilder, output obs.OutputSpec, image string) error {
- if err := f.AddVectorHttpOutputWithConfig(b, output, "", nil, Option{"path", "/tmp/{{kubernetes.container_name}}.log"}, Option{"template", VectorHttpSourceBenchmarkConfTemplate}); err != nil {
+ if err := f.AddVectorHttpOutputWithConfig(b, output, "", nil, Option{"path", "/tmp/{{.container_name}}.log"}, Option{"template", VectorHttpSourceBenchmarkConfTemplate}); err != nil {
return err
}
b.GetContainer(string(obs.OutputTypeHTTP)).WithImage(image).Update()