From 219a95a2e711ccf81235462eba7f1240196ca28b Mon Sep 17 00:00:00 2001 From: Ashish Gaurav Date: Thu, 21 Jul 2022 20:10:15 +0530 Subject: [PATCH] add README and samples for v1 based slos Took 13 hours 59 minutes --- README.md | 2 +- cmd/root.go | 52 ++++-- go.mod | 4 +- go.sum | 23 +-- libs/gen.go | 169 +++++++++++++----- libs/spec.go | 54 ++++-- libs/sumologic/native.go | 150 +++++++++++++++- libs/sumologic/templates/slo-folders.tf.gotf | 14 +- libs/sumologic/templates/slo-monitors.tf.gotf | 31 ++-- libs/sumologic/templates/slo.tf.gotf | 26 +-- libs/sumologic/tf.go | 14 ++ .../terraform/sumologic/main.tf.gotf | 29 ++- .../terraform/sumologic/slo-folders.tf.gotf | 16 ++ .../logs/drift-calculation.yaml | 0 .../logs/ingest-lag-timeslice-budgeting.yaml | 0 .../logs/trend-calculation.yaml | 0 .../tracing/checkout-latency.yaml | 0 .../tracing/order-api-errors.yaml | 0 .../tracing/order-api-latency.yaml | 0 .../tracing/page-load-time.yaml | 0 .../tracing/payment-api-latency.yaml | 0 .../{ => sumologic}/tracing/user-journey.yaml | 0 samples/sumologic/v1/README.md | 19 ++ .../sumologic/v1/alert-policy/burn-rate.yaml | 36 ++++ .../{ => sumologic}/v1/logs-req-calendar.yaml | 6 +- .../{ => sumologic}/v1/logs-req-rolling.yaml | 8 +- .../v1/notification-target/email.yaml | 7 + 27 files changed, 515 insertions(+), 145 deletions(-) create mode 100644 libs/templates/terraform/sumologic/slo-folders.tf.gotf rename samples/{ => sumologic}/logs/drift-calculation.yaml (100%) rename samples/{ => sumologic}/logs/ingest-lag-timeslice-budgeting.yaml (100%) rename samples/{ => sumologic}/logs/trend-calculation.yaml (100%) rename samples/{ => sumologic}/tracing/checkout-latency.yaml (100%) rename samples/{ => sumologic}/tracing/order-api-errors.yaml (100%) rename samples/{ => sumologic}/tracing/order-api-latency.yaml (100%) rename samples/{ => sumologic}/tracing/page-load-time.yaml (100%) rename samples/{ => sumologic}/tracing/payment-api-latency.yaml (100%) rename samples/{ => sumologic}/tracing/user-journey.yaml (100%) create mode 100644 samples/sumologic/v1/README.md create mode 100644 samples/sumologic/v1/alert-policy/burn-rate.yaml rename samples/{ => sumologic}/v1/logs-req-calendar.yaml (93%) rename samples/{ => sumologic}/v1/logs-req-rolling.yaml (89%) create mode 100644 samples/sumologic/v1/notification-target/email.yaml diff --git a/README.md b/README.md index fe4ce5c..ec87449 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ wget -O - https://github.com/OpenSLO/slogen/releases/download/v0.7.11/slogen_0.7 --- -##### create the yaml config for the SLO. more [samples](samples/logs) based on real data. +##### create the yaml config for the SLO. more [samples](samples/sumologic/logs) based on real data. --- diff --git a/cmd/root.go b/cmd/root.go index a8ccfb0..109f83f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -115,6 +115,8 @@ const FlagCleanLong = "clean" const FlagCleanShort = "c" const FlagDashboardFolderLong = "dashboardFolder" const FlagDashboardFolderShort = "d" +const FlagSLORootFolder = "sloFolder" +const FlagSLOMonitorRootFolder = "sloMonitorFolder" const FlagMonitorFolderLong = "monitorFolder" const FlagMonitorFolderShort = "m" const FlagViewPrefixLong = "viewPrefix" @@ -123,6 +125,7 @@ const FlagViewDestroy = "viewDestroy" const FlagDestroy = "destroy" const FlagAsModule = "asModule" const FlagUseViewHash = "useViewHash" +const FlagOnlyNative = "onlyNative" func init() { cobra.OnInitialize(initConfig) @@ -140,11 +143,11 @@ func init() { ) rootCmd.Flags().StringP(FlagDashboardFolderLong, FlagDashboardFolderShort, "slogen-tf-dashboards", - "output directory where to create the terraform files", + "root dashboard folder where to organise the dashboards per service", ) rootCmd.Flags().StringP(FlagMonitorFolderLong, FlagMonitorFolderShort, "slogen-tf-monitors", - "output directory where to create the terraform files", + "root monitor folder where to organise the monitors per service", ) //rootCmd.Flags().StringP(FlagViewPrefixLong, FlagViewPrefixShort, libs.ViewPrefix, @@ -176,6 +179,11 @@ func init() { "old view is not used when the query for it changes", ) + rootCmd.Flags().Bool(FlagOnlyNative, false, "whether to generate only the native slo resources") + + rootCmd.Flags().String(FlagSLORootFolder, "slogen", `root slo folder where to organise native slos by service`) + rootCmd.Flags().String(FlagSLOMonitorRootFolder, "slogen", `root monitor folder where to organise native slo monitors by service`) + rootCmd.Flags().SortFlags = false } @@ -243,21 +251,43 @@ func GetGenConf(cmd *cobra.Command) (*libs.GenConf, error) { if err != nil { return nil, err } + useViewHash, err := cmd.Flags().GetBool(FlagUseViewHash) if err != nil { return nil, err } + onlyNative, err := cmd.Flags().GetBool(FlagOnlyNative) + + if err != nil { + return nil, err + } + + sloRootFolder, err := cmd.Flags().GetString(FlagSLORootFolder) + + if err != nil { + return nil, err + } + + sloMonitorRootFolder, err := cmd.Flags().GetString(FlagSLOMonitorRootFolder) + + if err != nil { + return nil, err + } + conf := &libs.GenConf{ - IgnoreError: ie, - OutDir: outDir, - Clean: clean, - DashFolder: dashDir, - MonitorFolder: monDir, - DoPlan: doPlan, - DoApply: doApply, - AsModule: asModule, - UseViewHash: useViewHash, + IgnoreError: ie, + OutDir: outDir, + Clean: clean, + DashFolder: dashDir, + MonitorFolder: monDir, + DoPlan: doPlan, + DoApply: doApply, + AsModule: asModule, + UseViewHash: useViewHash, + SLORootFolder: sloRootFolder, + SLOMonitorRootFolder: sloMonitorRootFolder, + OnlyNative: onlyNative, } return conf, nil diff --git a/go.mod b/go.mod index b806460..4336499 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/manifoldco/promptui v0.9.0 github.com/mattn/go-colorable v0.1.12 github.com/mitchellh/hashstructure/v2 v2.0.2 - github.com/spf13/cobra v1.4.0 + github.com/spf13/cobra v1.5.0 github.com/spf13/viper v1.12.0 go.uber.org/zap v1.21.0 gopkg.in/yaml.v3 v3.0.1 @@ -51,4 +51,4 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect ) -replace github.com/OpenSLO/oslo => github.com/agaurav/oslo v0.3.3-0.20220610112509-8297ce344784 +replace github.com/OpenSLO/oslo => github.com/agaurav/oslo v0.3.3-0.20220712184915-bc307d389cf4 diff --git a/go.sum b/go.sum index e26bbbe..b4f0ea3 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6 github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/agaurav/oslo v0.3.3-0.20220610112509-8297ce344784 h1:Yvk3PT/yVBXJbH0eciz+aW4RKH2LdKfTbAaGUx34knI= -github.com/agaurav/oslo v0.3.3-0.20220610112509-8297ce344784/go.mod h1:o1f/E73Ml7sTZeVmM0kes3vlP56YvImel/c22JGJ8tU= +github.com/agaurav/oslo v0.3.3-0.20220712184915-bc307d389cf4 h1:IsjTtq+lHQK77nSj533WZtuvtJ8dFfgnRMktdYaOFHA= +github.com/agaurav/oslo v0.3.3-0.20220712184915-bc307d389cf4/go.mod h1:QEy6FSCxj2DkXBtjCiCvQz2DG9CRhdGM/pNp+iZ1AcY= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= @@ -67,7 +67,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -100,10 +99,6 @@ github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -208,7 +203,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= @@ -243,7 +237,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -256,8 +249,8 @@ github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -270,11 +263,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -317,7 +308,6 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -389,7 +379,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -457,9 +446,7 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0= diff --git a/libs/gen.go b/libs/gen.go index 7db9a01..d392e81 100644 --- a/libs/gen.go +++ b/libs/gen.go @@ -4,9 +4,9 @@ import ( "bytes" "embed" "fmt" + oslo "github.com/OpenSLO/oslo/pkg/manifest/v1" "github.com/OpenSLO/slogen/libs/specs" "github.com/OpenSLO/slogen/libs/sumologic" - "github.com/kr/pretty" "os" "path/filepath" "sort" @@ -22,30 +22,37 @@ const NameMainTmpl = "main.tf.gotf" const NameModuleTmpl = "module_interface.tf.gotf" const NameDashFolderTmpl = "dash-folders.tf.gotf" const NameMonitorFolderTmpl = "monitor-folders.tf.gotf" +const NameSLOFolderTmpl = "slo-folders.tf.gotf" const NameGlobalTrackerTmpl = "global-tracker.tf.gotf" const NameServiceTrackerTmpl = "service-overview.tf.gotf" //go:embed templates/terraform/**/*.tf.gotf var tmplFiles embed.FS +var alertPolicyMap = map[string]oslo.AlertPolicy{} + const ( BuildFolder = "build" ViewsFolder = "views" MonitorsFolder = "monitors" DashboardsFolder = "dashboards" + NativeSLOFolder = "slos" ) type GenConf struct { - OutDir string - DashFolder string - MonitorFolder string - ViewPrefix string - DoPlan bool - DoApply bool - IgnoreError bool - Clean bool - AsModule bool - UseViewHash bool + OutDir string + DashFolder string + MonitorFolder string + ViewPrefix string + SLORootFolder string + SLOMonitorRootFolder string + DoPlan bool + DoApply bool + IgnoreError bool + Clean bool + AsModule bool + UseViewHash bool + OnlyNative bool } func init() { @@ -62,7 +69,7 @@ const ViewPrefix = "slogen_tf" // GenTerraform for all openslo files in the path func GenTerraform(slosMv map[string]*SLOMultiVerse, c GenConf) (string, error) { - slosAlpha, slosV1 := splitMultiVerse(slosMv) + slosAlpha, _ := splitMultiVerse(slosMv) err := SetupOutDir(c) if err != nil { BadResult("error setting up path : %s", err) @@ -71,7 +78,12 @@ func GenTerraform(slosMv map[string]*SLOMultiVerse, c GenConf) (string, error) { //pretty.Println(slosV1) - genTerraformForV1(slosV1, c) + err = genTerraformForV1(slosMv, c) + + if err != nil { + panic(err) + } + return genTerraformForAlpha(slosAlpha, c) } @@ -101,39 +113,72 @@ func genTerraformForAlpha(slosAlpha map[string]*SLOv1Alpha, c GenConf) (string, srvList := GiveKeys(srvMap) sort.Strings(srvList) - err = GenFoldersTF(srvList, c.OutDir) - if err != nil { - return "", err + if !c.OnlyNative { + err = GenFoldersTF(srvList, c) + if err != nil { + return "", err + } + + err = GenOverviewTF(slosAlpha, c) } - err = GenOverviewTF(slosAlpha, c) return "", err } -func genTerraformForV1(slos map[string]*specs.OpenSLOSpec, c GenConf) error { +func fillAlertPolicyMap(slos map[string]*SLOMultiVerse) { + for _, slo := range slos { + ap := slo.AlertPolicy + if ap != nil { + alertPolicyMap[ap.Metadata.Name] = *ap + } + } +} - v1Path := filepath.Join(c.OutDir, "sumologic") - err := EnsureDir(v1Path, c.Clean) +func genTerraformForV1(slos map[string]*SLOMultiVerse, c GenConf) error { - if err != nil { - return err - } + v1Path := filepath.Join(c.OutDir, NativeSLOFolder) - for _, slo := range slos { - sumoSLO, err := sumologic.GiveSLOTerraform(*slo) + fillAlertPolicyMap(slos) - if err != nil { - BadUResult(err.Error()) - return err - } + srvMap := map[string]bool{} - pretty.Println(sumoSLO) - err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_%s.tf", slo.Metadata.Name)), []byte(sumoSLO), 0755) - if err != nil { - return err + for _, sloM := range slos { + if sloM.V1 != nil { + slo := sloM.V1 + sumoSLO, err := sumologic.ConvertToSumoSLO(*slo) + sumoSLOStr, err := sumologic.GiveSLOTerraform(*slo) + + if err != nil { + BadUResult(err.Error() + fmt.Sprintf("| file : %s", sloM.ConfigPath)) + return err + } + + //pretty.Println(sumoSLO) + + err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_%s.tf", slo.Metadata.Name)), []byte(sumoSLOStr), 0755) + if err != nil { + return err + } + + srvMap[slo.Spec.Service] = true + + monitorsStr, err := sumologic.GenSLOMonitorsFromAPNames(alertPolicyMap, *sumoSLO, *slo.SLO) + + if err != nil { + return err + } + + if monitorsStr != "" { + err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_monitors_%s.tf", slo.Metadata.Name)), []byte(monitorsStr), 0755) + } } } + srvList := GiveKeys(srvMap) + sort.Strings(srvList) + + GenSLOFoldersTF(srvList, c) + return nil } @@ -185,8 +230,10 @@ func ExecSLOTmpl(tmplName string, slo SLOv1Alpha, outDir string) error { } const ( - VarNameMonRootFolder = "slo_mon_root_folder_id" - VarNameDashRootFolder = "slo_dash_root_folder_id" + VarNameMonRootFolder = "slo_mon_root_folder_id" + VarNameDashRootFolder = "slo_dash_root_folder_id" + VarNameNativeSLORootFolder = "slo_root_folder_id" + VarNameSLOMonitorRootFolder = "slo_monitor_root_folder_id" ) type TFModules struct { @@ -210,10 +257,19 @@ func SetupOutDir(c GenConf) error { return err } - modules := []TFModules{ - {Path: filepath.Join(c.OutDir, ViewsFolder), Vars: nil}, - {Path: filepath.Join(c.OutDir, MonitorsFolder), Vars: []string{VarNameMonRootFolder}}, - {Path: filepath.Join(c.OutDir, DashboardsFolder), Vars: []string{VarNameDashRootFolder}}, + var modules []TFModules + + if c.OnlyNative { + modules = []TFModules{ + {Path: filepath.Join(c.OutDir, NativeSLOFolder), Vars: []string{VarNameNativeSLORootFolder, VarNameSLOMonitorRootFolder}}, + } + } else { + modules = []TFModules{ + {Path: filepath.Join(c.OutDir, ViewsFolder), Vars: nil}, + {Path: filepath.Join(c.OutDir, MonitorsFolder), Vars: []string{VarNameMonRootFolder}}, + {Path: filepath.Join(c.OutDir, DashboardsFolder), Vars: []string{VarNameDashRootFolder}}, + {Path: filepath.Join(c.OutDir, NativeSLOFolder), Vars: []string{VarNameNativeSLORootFolder}}, + } } for _, p := range modules { @@ -243,16 +299,37 @@ func FileFromTmpl(name string, path string, data interface{}) error { return os.WriteFile(path, buff.Bytes(), 0755) } -func GenFoldersTF(srvList []string, outDir string) error { - path := filepath.Join(outDir, MonitorsFolder, "folders.tf") - err := FileFromTmpl(NameMonitorFolderTmpl, path, srvList) +func GenFoldersTF(srvList []string, conf GenConf) error { - if err != nil { - return err + outDir := conf.OutDir + + fmt.Println(srvList, "srvList") + + if !conf.OnlyNative { + path := filepath.Join(outDir, MonitorsFolder, "folders.tf") + err := FileFromTmpl(NameMonitorFolderTmpl, path, srvList) + + if err != nil { + return err + } + + path = filepath.Join(outDir, DashboardsFolder, "folders.tf") + err = FileFromTmpl(NameDashFolderTmpl, path, srvList) + + if err != nil { + return err + } } - path = filepath.Join(outDir, DashboardsFolder, "folders.tf") - err = FileFromTmpl(NameDashFolderTmpl, path, srvList) + return nil +} + +func GenSLOFoldersTF(srvList []string, conf GenConf) error { + + outDir := conf.OutDir + + path := filepath.Join(outDir, NativeSLOFolder, "folders.tf") + err := FileFromTmpl(NameSLOFolderTmpl, path, srvList) return err } diff --git a/libs/spec.go b/libs/spec.go index d69ac1b..939ed6d 100644 --- a/libs/spec.go +++ b/libs/spec.go @@ -36,18 +36,20 @@ func Parse(filename string) (*SLOMultiVerse, error) { return nil, err } - specVersion := giveOpenSLOVersion(fileContent) + sloHeaders := giveOpenSLOVersion(fileContent) - slo := &SLOMultiVerse{} + slo := &SLOMultiVerse{ + ConfigPath: filename, + } - switch specVersion { + switch sloHeaders.APIVersion { case oslo.APIVersion: - slo.V1, err = parseV1(fileContent) + err = parseV1(fileContent, sloHeaders, slo) case v1alpha.APIVersion: slo.Alpha, err = parseV1Alpha(fileContent) default: - return nil, fmt.Errorf("unsupported OpenSLO spec version %s", specVersion) + return nil, fmt.Errorf("unsupported OpenSLO spec version %s", sloHeaders.APIVersion) } return slo, err @@ -61,20 +63,32 @@ func parseV1Alpha(yamlBody []byte) (*SLOv1Alpha, error) { return &slo, err } -func parseV1(yamlBody []byte) (*specs.OpenSLOSpec, error) { - var spec specs.OpenSLOSpec - - err := yaml.Unmarshal(yamlBody, &spec) - - if err == nil { - //pretty.Println(spec) - //pretty.Println(sumologic.ConvertToSumoSLO(&spec)) +func parseV1(yamlBody []byte, headers oslo.ObjectGeneric, sloM *SLOMultiVerse) error { + + var err error + switch headers.Kind { + case oslo.KindSLO: + var spec specs.OpenSLOSpec + err = yaml.Unmarshal(yamlBody, &spec) + sloM.V1 = &spec + case oslo.KindAlertPolicy: + var spec oslo.AlertPolicy + err = yaml.Unmarshal(yamlBody, &spec) + sloM.AlertPolicy = &spec + case oslo.KindAlertCondition: + var spec oslo.AlertCondition + err = yaml.Unmarshal(yamlBody, &spec) + sloM.AlertCondition = &spec + case oslo.KindAlertNotificationTarget: + var spec oslo.AlertNotificationTarget + err = yaml.Unmarshal(yamlBody, &spec) + sloM.AlertNotificationTarget = &spec } - return &spec, err + return err } -func giveOpenSLOVersion(yamlBody []byte) string { +func giveOpenSLOVersion(yamlBody []byte) oslo.ObjectGeneric { var m oslo.ObjectGeneric err := yaml.Unmarshal(yamlBody, &m) @@ -83,7 +97,7 @@ func giveOpenSLOVersion(yamlBody []byte) string { panic(err) } - return m.APIVersion + return m } func (s SLOv1Alpha) Target() float64 { @@ -107,6 +121,10 @@ func (s SLOv1Alpha) TimesliceTarget() float64 { } type SLOMultiVerse struct { - Alpha *SLOv1Alpha - V1 *specs.OpenSLOSpec + ConfigPath string + Alpha *SLOv1Alpha + V1 *specs.OpenSLOSpec + AlertPolicy *oslo.AlertPolicy + AlertCondition *oslo.AlertCondition + AlertNotificationTarget *oslo.AlertNotificationTarget } diff --git a/libs/sumologic/native.go b/libs/sumologic/native.go index 3dd8a0d..6fe7f1a 100644 --- a/libs/sumologic/native.go +++ b/libs/sumologic/native.go @@ -2,13 +2,24 @@ package sumologic import ( "fmt" + oslo "github.com/OpenSLO/oslo/pkg/manifest/v1" "github.com/OpenSLO/slogen/libs/specs" "github.com/OpenSLO/slogen/libs/sumologic/sumotf" "log" "strconv" + "strings" +) + +const ( + MonitorKindBurnRate = "BurnRate" + MonitorKindSLI = "SLI" + ComplianceTypeCalendar = "Calendar" + ComplianceTypeRolling = "Rolling" ) type SLOMonitor struct { + Service string + SLOName string SloID string MonitorName string EvaluationDelay string @@ -25,6 +36,14 @@ type SLO struct { *sumotf.SLOLibrarySLO } +func (s SLO) TFResourceName() string { + return fmt.Sprintf("sumologic_slo_%s_%s", s.Service, s.Name) +} + +func (s SLOMonitor) TFResourceName() string { + return fmt.Sprintf("sumologic_monitor_%s", s.MonitorName) +} + type SLOFolder struct { *sumotf.SLOLibraryFolder } @@ -38,18 +57,18 @@ func ConvertToSumoSLO(slo specs.OpenSLOSpec) (*SLO, error) { } size := "" - timezone := "" + timezone := "America/New_York" startFrom := "" windowType := "" - complianceType := "Calendar" + complianceType := ComplianceTypeCalendar if len(slo.Spec.TimeWindow) == 1 { + timezone = slo.Spec.TimeWindow[0].Calendar.TimeZone if slo.Spec.TimeWindow[0].IsRolling { - complianceType = "Rolling" + complianceType = ComplianceTypeRolling size = slo.Spec.TimeWindow[0].Duration } else { windowType = slo.Spec.TimeWindow[0].Duration - timezone = slo.Spec.TimeWindow[0].Calendar.TimeZone startFrom = slo.Spec.TimeWindow[0].Calendar.StartTime } } else { @@ -60,7 +79,7 @@ func ConvertToSumoSLO(slo specs.OpenSLOSpec) (*SLO, error) { sumoSLO := &SLO{ &sumotf.SLOLibrarySLO{ - Name: slo.Spec.Indicator.Metadata.Name, + Name: slo.SLO.Metadata.Name, Description: slo.Spec.Description, Service: slo.Spec.Service, SignalType: signalType, @@ -194,3 +213,124 @@ func giveQueryGroup(spec map[string]string) sumotf.SLIQuery { UseRowCount: field == "", } } + +func ConvertToSumoMonitor(ap oslo.AlertPolicy, slo *SLO) ([]SLOMonitor, error) { + + var mons []SLOMonitor + + for _, c := range ap.Spec.Conditions { + + name := fmt.Sprintf("%s_%s_%s", slo.Service, slo.Name, c.Metadata.Name) + + m := SLOMonitor{ + SLOName: slo.Name, + Service: slo.Service, + MonitorName: name, + EvaluationDelay: c.AlertConditionInline.Spec.Condition.AlertAfter, + //TriggerType: "BurnRate", + //SliThresholdWarning: 0, + //SliThresholdCritical: 0, + //TimeRangeWarning: "", + //TimeRangeCritical: "", + //BurnRateThresholdWarning: 0, + //BurnRateThresholdCritical: 0, + } + + switch *c.AlertConditionInline.Spec.Condition.Kind { + case oslo.AlertConditionTypeBurnRate: + FillBurnRateAlert(c.AlertConditionInline.Spec, &m) + default: + panic(fmt.Sprintf("alert condition of this kind not supported : '%s'", c.Kind)) + } + + m.SloID = fmt.Sprintf("${sumologic_slo.%s.id}", slo.TFResourceName()) + + mons = append(mons, m) + } + + return MergeMonitors(mons), nil +} + +func FillBurnRateAlert(c oslo.AlertConditionSpec, m *SLOMonitor) error { + + m.TriggerType = MonitorKindBurnRate + m.EvaluationDelay = c.Condition.AlertAfter + + switch strings.ToLower(c.Severity) { + case "critical": + m.BurnRateThresholdCritical = float64(c.Condition.Threshold) + m.TimeRangeCritical = c.Condition.LookbackWindow + case "warning": + m.BurnRateThresholdWarning = float64(c.Condition.Threshold) + m.TimeRangeWarning = c.Condition.LookbackWindow + } + + return nil +} + +// MergeMonitors merges multiple OpenSLO monitors critical & warning into one sumo monitor +// based on the name of the monitor. +func MergeMonitors(mons []SLOMonitor) []SLOMonitor { + burnRateMonitors := make(map[string][]SLOMonitor) + + for _, m := range mons { + + switch m.TriggerType { + case MonitorKindBurnRate: + burnRateMonitors[m.MonitorName] = append(burnRateMonitors[m.MonitorName], m) + default: + panic(fmt.Sprintf("trigger type not supported : '%s'", m.TriggerType)) + } + } + + mergedMonitors := mergeBurnRateMonitors(burnRateMonitors) + + return mergedMonitors +} + +func mergeBurnRateMonitors(mons map[string][]SLOMonitor) []SLOMonitor { + var mergedMonitors []SLOMonitor + + for _, m := range mons { + if len(m) != 2 { + panic(fmt.Sprintf("monitor %s has %d monitors, expected 2", m[0].MonitorName, len(m))) + } + + iCrit := 0 + iWarn := 1 + if m[iCrit].BurnRateThresholdWarning != 0 { + iCrit, iWarn = iWarn, iCrit + } + + m[iCrit].BurnRateThresholdWarning = m[iWarn].BurnRateThresholdWarning + m[iCrit].TimeRangeWarning = m[iWarn].TimeRangeWarning + + mergedMonitors = append(mergedMonitors, m[iCrit]) + } + + return mergedMonitors +} + +func GenSLOMonitorsFromAPNames(apMap map[string]oslo.AlertPolicy, sumoSLO SLO, slo oslo.SLO) (string, error) { + + var sloMonitors []SLOMonitor + + sloAPs := slo.Spec.AlertPolicies + + for _, apName := range sloAPs { + + ap := apMap[apName] + + mons, err := ConvertToSumoMonitor(ap, &sumoSLO) + if err != nil { + return "", err + } + sloMonitors = append(sloMonitors, mons...) + } + + if len(sloMonitors) == 0 { + return "", nil + } + + return GiveMonitorTerraform(sloMonitors) +} diff --git a/libs/sumologic/templates/slo-folders.tf.gotf b/libs/sumologic/templates/slo-folders.tf.gotf index d2b5ce9..225b4f2 100644 --- a/libs/sumologic/templates/slo-folders.tf.gotf +++ b/libs/sumologic/templates/slo-folders.tf.gotf @@ -1,9 +1,9 @@ -resource "sumologic_slo_folder" "{{.Name}}" { - name = "slo-tf-folder" - description = "folder for SLO created for testing" - {{ if ne .ParentID "" }} - parent_id = "{{.ParentID}}" - {{ end }} -} +{{ range $m := . }} +resource "sumologic_slo_folder" "slo_folder_{{.}}" { + name = "slo-folder-{{.}}" + description = "SLO folder for service {{ . }}" + parent_id = var.slo_root_folder_id +} +{{ end }} diff --git a/libs/sumologic/templates/slo-monitors.tf.gotf b/libs/sumologic/templates/slo-monitors.tf.gotf index 5085896..7c0f451 100644 --- a/libs/sumologic/templates/slo-monitors.tf.gotf +++ b/libs/sumologic/templates/slo-monitors.tf.gotf @@ -1,36 +1,39 @@ -resource "sumologic_monitor" "tf_slo_monitor_2" { - name = "{{.MonitorName}}" +{{ range $m := . }} + +resource "sumologic_monitor" "{{ $m.TFResourceName }}" { + name = "{{$m.MonitorName}}" type = "MonitorsLibraryMonitor" is_disabled = false content_type = "Monitor" monitor_type = "Slo" - slo_id = "{{.SloID}}" - evaluation_delay = "{{.EvaluationDelay}}" + slo_id = "{{$m.SloID}}" + evaluation_delay = "{{$m.EvaluationDelay}}" trigger_conditions { - {{if eq .TriggerType "SLI"}} + {{- if eq $m.TriggerType "SLI"}} slo_sli_condition { critical { - sli_threshold = "{{.SliThresholdCritical}}" + sli_threshold = "{{$m.SliThresholdCritical}}" } warning { - sli_threshold = "{{.SliThresholdWarning}}" + sli_threshold = "{{$m.SliThresholdWarning}}" } } - {{end}} + {{end -}} - {{if eq .TriggerType "BurnRate"}} + {{- if eq $m.TriggerType "BurnRate"}} slo_burn_rate_condition { critical { - burn_rate_threshold = "{{.BurnRateThresholdCritical}}" - time_range = "{{.TimeRangeCritical}}" + burn_rate_threshold = "{{$m.BurnRateThresholdCritical}}" + time_range = "{{$m.TimeRangeCritical}}" } warning { - burn_rate_threshold = "{{.BurnRateThresholdWarning}}" - time_range = "{{.TimeRangeWarning}}" + burn_rate_threshold = "{{$m.BurnRateThresholdWarning}}" + time_range = "{{$m.TimeRangeWarning}}" } } - {{end}} + {{end -}} } } +{{ end }} diff --git a/libs/sumologic/templates/slo.tf.gotf b/libs/sumologic/templates/slo.tf.gotf index 37312c9..d355e94 100644 --- a/libs/sumologic/templates/slo.tf.gotf +++ b/libs/sumologic/templates/slo.tf.gotf @@ -1,14 +1,12 @@ -resource "sumologic_slo" "sumologic_slo_{{$.Service}}_{{$.Name}}" { +resource "sumologic_slo" "{{ .TFResourceName }}" { name = "{{.Name}}" description = "{{.Description}}" - {{- if ne .ParentID ""}} - parent_id = "{{.ParentID}}" - {{ end }} + parent_id = sumologic_slo_folder.slg_tf_{{.Service}}.id signal_type = "{{.SignalType}}" service = "{{.Service}}" application = "" - {{with .Compliance }} + {{with .Compliance -}} compliance { compliance_type = "{{.ComplianceType}}" {{- if eq .ComplianceType "Rolling" }} @@ -18,16 +16,18 @@ resource "sumologic_slo" "sumologic_slo_{{$.Service}}_{{$.Name}}" { size = "{{.WindowType}}" {{- end }} target = "{{.Target}}" + {{- if ne .Timezone ""}} timezone = "{{.Timezone}}" - {{if eq .ComplianceType "Calendar"}} + {{- end}} + {{- if eq .ComplianceType "Calendar"}} start_from = "{{.StartFrom}}" - {{end}} + {{- end}} } - {{end}} + {{- end}} - {{with $ind := .Indicator}} + {{with $ind := .Indicator -}} indicator { - {{ if eq $ind.EvaluationType "Window" }} + {{- if eq $ind.EvaluationType "Window" }} window_based_evaluation { op = "{{$ind.Op}}" query_type = "{{$ind.QueryType}}" @@ -51,9 +51,9 @@ QUERY } {{end}} } - {{ end }} + {{- end }} - {{ if eq .EvaluationType "Request" }} + {{- if eq .EvaluationType "Request" }} request_based_evaluation { op = "{{.Op}}" query_type = "{{.QueryType}}" @@ -76,7 +76,7 @@ QUERY } {{end}} } - {{ end }} + {{- end }} } {{end}} } diff --git a/libs/sumologic/tf.go b/libs/sumologic/tf.go index 04b89a5..ce29b34 100644 --- a/libs/sumologic/tf.go +++ b/libs/sumologic/tf.go @@ -46,3 +46,17 @@ func GiveSLOTerraform(s specs.OpenSLOSpec) (string, error) { return buff.String(), nil } + +func GiveMonitorTerraform(mons []SLOMonitor) (string, error) { + + tmpl := tfTemplates.Lookup(SLOMonitorTmplName) + + buff := &bytes.Buffer{} + err := tmpl.Execute(buff, mons) + + if err != nil { + return "", err + } + + return buff.String(), nil +} diff --git a/libs/templates/terraform/sumologic/main.tf.gotf b/libs/templates/terraform/sumologic/main.tf.gotf index f088b90..1c93ce5 100644 --- a/libs/templates/terraform/sumologic/main.tf.gotf +++ b/libs/templates/terraform/sumologic/main.tf.gotf @@ -1,11 +1,14 @@ terraform { required_providers { sumologic = { - source = "sumologic/sumologic" + source = "sumologic/sumologic" } } } + +{{- if not .OnlyNative }} + {{- if .AsModule }} variable "slogen_dashboards_parent_folder" {} {{else}} @@ -17,9 +20,9 @@ resource "sumologic_folder" "slo_dash_root_folder" { description = "Your SLO dashboards created with slogen" {{- if .AsModule }} - parent_id = var.slogen_dashboards_parent_folder + parent_id = var.slogen_dashboards_parent_folder {{else}} - parent_id = data.sumologic_personal_folder.personalFolder.id + parent_id = data.sumologic_personal_folder.personalFolder.id {{- end}} } @@ -38,8 +41,26 @@ module "slg_tf_dashboards" { depends_on = [module.slg_tf_views] } + module "slg_tf_monitors" { source = "./monitors" slo_mon_root_folder_id = sumologic_monitor_folder.slo_mon_root_folder.id - depends_on = [module.slg_tf_views] + depends_on = [module.slg_tf_views] +} +{{- end }} + +resource "sumologic_slo_folder" "slo_root_folder" { + name = "{{.SLORootFolder}}" + description = "Root folder for native SLOs created with slogen" +} + +resource "sumologic_monitor_folder" "slo_monitor_root_folder" { + name = "{{.SLOMonitorRootFolder}}" + description = "Root folder for SLO based monitors created with slogen" +} + +module "slos" { + source = "./slos" + slo_root_folder_id = sumologic_slo_folder.slo_root_folder.id + slo_monitor_root_folder_id = sumologic_monitor_folder.slo_monitor_root_folder.id } diff --git a/libs/templates/terraform/sumologic/slo-folders.tf.gotf b/libs/templates/terraform/sumologic/slo-folders.tf.gotf new file mode 100644 index 0000000..973002b --- /dev/null +++ b/libs/templates/terraform/sumologic/slo-folders.tf.gotf @@ -0,0 +1,16 @@ +{{range $folder := .}} +resource "sumologic_slo_folder" "slg_tf_{{$folder}}" { + name = "{{$folder}}" + description = "SLO folder for service {{$folder}}" + parent_id = var.slo_root_folder_id +} +{{end}} + +{{range $folder := .}} +resource "sumologic_monitor_folder" "slg_tf_monitor_{{$folder}}" { + name = "{{$folder}}" + description = "SLO monitor folder for service {{$folder}}" + parent_id = var.slo_monitor_root_folder_id +} +{{end}} + diff --git a/samples/logs/drift-calculation.yaml b/samples/sumologic/logs/drift-calculation.yaml similarity index 100% rename from samples/logs/drift-calculation.yaml rename to samples/sumologic/logs/drift-calculation.yaml diff --git a/samples/logs/ingest-lag-timeslice-budgeting.yaml b/samples/sumologic/logs/ingest-lag-timeslice-budgeting.yaml similarity index 100% rename from samples/logs/ingest-lag-timeslice-budgeting.yaml rename to samples/sumologic/logs/ingest-lag-timeslice-budgeting.yaml diff --git a/samples/logs/trend-calculation.yaml b/samples/sumologic/logs/trend-calculation.yaml similarity index 100% rename from samples/logs/trend-calculation.yaml rename to samples/sumologic/logs/trend-calculation.yaml diff --git a/samples/tracing/checkout-latency.yaml b/samples/sumologic/tracing/checkout-latency.yaml similarity index 100% rename from samples/tracing/checkout-latency.yaml rename to samples/sumologic/tracing/checkout-latency.yaml diff --git a/samples/tracing/order-api-errors.yaml b/samples/sumologic/tracing/order-api-errors.yaml similarity index 100% rename from samples/tracing/order-api-errors.yaml rename to samples/sumologic/tracing/order-api-errors.yaml diff --git a/samples/tracing/order-api-latency.yaml b/samples/sumologic/tracing/order-api-latency.yaml similarity index 100% rename from samples/tracing/order-api-latency.yaml rename to samples/sumologic/tracing/order-api-latency.yaml diff --git a/samples/tracing/page-load-time.yaml b/samples/sumologic/tracing/page-load-time.yaml similarity index 100% rename from samples/tracing/page-load-time.yaml rename to samples/sumologic/tracing/page-load-time.yaml diff --git a/samples/tracing/payment-api-latency.yaml b/samples/sumologic/tracing/payment-api-latency.yaml similarity index 100% rename from samples/tracing/payment-api-latency.yaml rename to samples/sumologic/tracing/payment-api-latency.yaml diff --git a/samples/tracing/user-journey.yaml b/samples/sumologic/tracing/user-journey.yaml similarity index 100% rename from samples/tracing/user-journey.yaml rename to samples/sumologic/tracing/user-journey.yaml diff --git a/samples/sumologic/v1/README.md b/samples/sumologic/v1/README.md new file mode 100644 index 0000000..fb4f381 --- /dev/null +++ b/samples/sumologic/v1/README.md @@ -0,0 +1,19 @@ +## Creating Sumologic native SLO's and monitors from OpenSLO yaml configs + +slogen support native sumologic slo creation for spec version v1 for OpenSLO. + +Samples can be found in the [samples/sumologic/v1/](samples/sumologic/v1/) directory. + + +#### OpenSLO SLI to Sumologic SLI fields mapping + +- the `name` value specified in `metadata:name` field of the OpenSLO spec is used as the SLO name +- Budgeting method `Occurrences` maps to `Request` based SLO's while `Timeslices` maps to `Window` based SLO's +- use `"sumologic-logs` as `metricSource:type` for logs based Indicators, while `"sumologic-metrics`` for metrics based Indicators + +#### Using Alerting Policies to create SLO monitors +slogen doesn't support inline alerting conditional in SLO config yaml. +Alerting policies need to specified separately as showed in the samples and then can be referred by name the SLO config. + +To specify the `critical` and `warning` threshold use the same condition `name` as done in the samples. + diff --git a/samples/sumologic/v1/alert-policy/burn-rate.yaml b/samples/sumologic/v1/alert-policy/burn-rate.yaml new file mode 100644 index 0000000..21d9573 --- /dev/null +++ b/samples/sumologic/v1/alert-policy/burn-rate.yaml @@ -0,0 +1,36 @@ +apiVersion: openslo/v1 +kind: AlertPolicy +metadata: + name: DoubleBurnRate + displayName: Alert Policy +spec: + description: Alert policy for cpu usage breaches, notifies on-call devops via email + alertWhenBreaching: true + alertWhenResolved: false + conditions: + - kind: AlertCondition + metadata: + name: cpu-usage-breach + displayName: CPU Usage breaching + spec: + description: SLO burn rate for cpu-usage-breach exceeds 2 + severity: warning + condition: + kind: burnrate + threshold: 2 + lookbackWindow: 1h + alertAfter: 5m + - kind: AlertCondition + metadata: + name: cpu-usage-breach + displayName: CPU Usage breaching + spec: + description: SLO burn rate for cpu-usage-breach exceeds 2 + severity: critical + condition: + kind: burnrate + threshold: 4 + lookbackWindow: 1h + alertAfter: 5m + notificationTargets: + - targetRef: OnCallDevopsMailNotification diff --git a/samples/v1/logs-req-calendar.yaml b/samples/sumologic/v1/logs-req-calendar.yaml similarity index 93% rename from samples/v1/logs-req-calendar.yaml rename to samples/sumologic/v1/logs-req-calendar.yaml index 5ba390b..2c05b8d 100644 --- a/samples/v1/logs-req-calendar.yaml +++ b/samples/sumologic/v1/logs-req-calendar.yaml @@ -1,13 +1,13 @@ apiVersion: openslo/v1 kind: SLO metadata: - name: TestSLO_Calendar + name: drift_gen_Calendar displayName: Test SLO annotations: sumologic/signal-type: Latency spec: description: test slo created from slogen - service: TheServiceName + service: tsat indicator: metadata: name: foo-error @@ -42,4 +42,4 @@ spec: - displayName: Foo Total Errors target: 0.98 alertPolicies: - - FooAlertPolicy + - DoubleBurnRate diff --git a/samples/v1/logs-req-rolling.yaml b/samples/sumologic/v1/logs-req-rolling.yaml similarity index 89% rename from samples/v1/logs-req-rolling.yaml rename to samples/sumologic/v1/logs-req-rolling.yaml index 9e66570..513e18d 100644 --- a/samples/v1/logs-req-rolling.yaml +++ b/samples/sumologic/v1/logs-req-rolling.yaml @@ -1,13 +1,13 @@ apiVersion: openslo/v1 kind: SLO metadata: - name: TestSLO_Rolling + name: drift_gen_Rolling displayName: Test SLO annotations: sumologic/signal-type: Latency spec: description: test slo created from slogen - service: TheServiceName + service: tsat indicator: metadata: name: foo-error @@ -32,8 +32,10 @@ spec: _sourceCategory=tsat-batcher | where msg="DriftGen query completed" timeWindow: - - duration: 1M + - duration: 7d isRolling: true + calendar: + timeZone: America/New_York budgetingMethod: Occurrences objectives: - displayName: Foo Total Errors diff --git a/samples/sumologic/v1/notification-target/email.yaml b/samples/sumologic/v1/notification-target/email.yaml new file mode 100644 index 0000000..a1dfe87 --- /dev/null +++ b/samples/sumologic/v1/notification-target/email.yaml @@ -0,0 +1,7 @@ +apiVersion: openslo/v1 +kind: AlertNotificationTarget +metadata: + name: OnCallDevopsMailNotification +spec: + description: Notifies by a mail message to the on-call devops mailing group + target: email