Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add policies count to telemetry #5457

Merged
merged 12 commits into from
Apr 29, 2024
1 change: 1 addition & 0 deletions docs/content/overview/product-telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ These are the data points collected and reported by NGINX Ingress Controller:
- **Services** Number of Services referenced by VirtualServers, VirtualServerRoutes, TransportServers and Ingresses.
- **Ingresses** The number of Ingress resources managed by the NGINX Ingress Controller.
- **IngressClasses** Number of Ingress Classes in the cluster.
- **Policies** Number of policy resources managed by NGINX Ingress Controller
- **GlobalConfiguration** Represents the use of a GlobalConfiguration resource.

## Opt out
Expand Down
1 change: 1 addition & 0 deletions internal/k8s/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc
Namespace: os.Getenv("POD_NAMESPACE"),
Name: os.Getenv("POD_NAME"),
},
Policies: lbc.getAllPolicies,
}
collector, err := telemetry.NewCollector(
collectorConfig,
Expand Down
10 changes: 9 additions & 1 deletion internal/telemetry/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (c *Collector) ClusterID(ctx context.Context) (string, error) {
return string(cluster.UID), nil
}

// ClusterVersion returns a string respresenting the K8s version.
// ClusterVersion returns a string representing the K8s version.
// It returns an error if the underlying k8s API client errors.
func (c *Collector) ClusterVersion() (string, error) {
sv, err := c.Config.K8sClientReader.Discovery().ServerVersion()
Expand Down Expand Up @@ -145,6 +145,14 @@ func (c *Collector) IngressClassCount(ctx context.Context) (int, error) {
return len(ic.Items), nil
}

// PolicyCount returns number of Policies watched by NIC.
func (c *Collector) PolicyCount() int {
AlexFenlon marked this conversation as resolved.
Show resolved Hide resolved
if c.Config.Policies == nil {
return 0
}
return len(c.Config.Policies())
}

// lookupPlatform takes a string representing a K8s PlatformID
// retrieved from a cluster node and returns a string
// representing the platform name.
Expand Down
10 changes: 10 additions & 0 deletions internal/telemetry/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"runtime"
"time"

conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"

"github.com/nginxinc/kubernetes-ingress/internal/k8s/secrets"

tel "github.com/nginxinc/telemetry-exporter/pkg/telemetry"
Expand Down Expand Up @@ -66,6 +68,9 @@ type CollectorConfig struct {

// PodNSName represents NIC Pod's NamespacedName.
PodNSName types.NamespacedName

// Policies gets all policies
Policies func() []*conf_v1.Policy
}

// NewCollector takes 0 or more options and creates a new TraceReporter.
Expand Down Expand Up @@ -118,6 +123,7 @@ func (c *Collector) Collect(ctx context.Context) {
Services: int64(report.ServiceCount),
Ingresses: int64(report.IngressCount),
IngressClasses: int64(report.IngressClassCount),
Policies: int64(report.PolicyCount),
GlobalConfiguration: report.GlobalConfiguration,
},
}
Expand Down Expand Up @@ -149,6 +155,7 @@ type Report struct {
Secrets int
IngressCount int
IngressClassCount int
PolicyCount int
GlobalConfiguration bool
}

Expand Down Expand Up @@ -205,6 +212,8 @@ func (c *Collector) BuildReport(ctx context.Context) (Report, error) {
glog.Errorf("Error collecting telemetry data: Ingress Classes: %v", err)
}

policyCount := c.PolicyCount()

return Report{
Name: "NIC",
Version: c.Config.Version,
Expand All @@ -222,6 +231,7 @@ func (c *Collector) BuildReport(ctx context.Context) (Report, error) {
Secrets: secretCount,
IngressCount: ingressCount,
IngressClassCount: ingressClassCount,
PolicyCount: policyCount,
GlobalConfiguration: c.Config.GlobalConfiguration,
}, err
}
128 changes: 128 additions & 0 deletions internal/telemetry/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,94 @@ func TestCollectClusterVersion(t *testing.T) {
}
}

func TestCollectMultiplePolicies(t *testing.T) {
t.Parallel()

fn := func() []*conf_v1.Policy {
return []*conf_v1.Policy{&policy1, &policy2, &policy3}
}

cfg := telemetry.CollectorConfig{
Policies: fn,
}
collector, err := telemetry.NewCollector(cfg)
if err != nil {
t.Fatal(err)
}
got := collector.PolicyCount()

want := 3

if want != got {
t.Errorf("want %d, got %d", want, got)
}
}

func TestCollectSinglePolicy(t *testing.T) {
t.Parallel()

fn := func() []*conf_v1.Policy {
return []*conf_v1.Policy{&policy1}
}

cfg := telemetry.CollectorConfig{
Policies: fn,
}
collector, err := telemetry.NewCollector(cfg)
if err != nil {
t.Fatal(err)
}
got := collector.PolicyCount()

want := 1

if want != got {
t.Errorf("want %d, got %d", want, got)
}
}

func TestCollectNoPolicies(t *testing.T) {
t.Parallel()

fn := func() []*conf_v1.Policy {
return []*conf_v1.Policy{}
}

cfg := telemetry.CollectorConfig{
Policies: fn,
}
collector, err := telemetry.NewCollector(cfg)
if err != nil {
t.Fatal(err)
}
got := collector.PolicyCount()

want := 0

if want != got {
t.Errorf("want %d, got %d", want, got)
}
}

func TestCollectPolicyWithNilFunction(t *testing.T) {
t.Parallel()

cfg := telemetry.CollectorConfig{
Policies: nil,
}
collector, err := telemetry.NewCollector(cfg)
if err != nil {
t.Fatal(err)
}
got := collector.PolicyCount()

want := 0

if want != got {
t.Errorf("want %d, got %d", want, got)
}
}

func TestIngressCountReportsNoDeployedIngresses(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1578,3 +1666,43 @@ var telemetryNICData = tel.Data{
ClusterNodeCount: 1,
ClusterPlatform: "other",
}

// Policies used for testing for PolicyCount method
var (
policy1 = conf_v1.Policy{
TypeMeta: metaV1.TypeMeta{
Kind: "Policy",
APIVersion: "k8s.nginx.org/v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "rate-limit-policy1",
Namespace: "default",
},
Spec: conf_v1.PolicySpec{},
Status: conf_v1.PolicyStatus{},
}
policy2 = conf_v1.Policy{
TypeMeta: metaV1.TypeMeta{
Kind: "Policy",
APIVersion: "k8s.nginx.org/v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "rate-limit-policy2",
Namespace: "default",
},
Spec: conf_v1.PolicySpec{},
Status: conf_v1.PolicyStatus{},
}
policy3 = conf_v1.Policy{
TypeMeta: metaV1.TypeMeta{
Kind: "Policy",
APIVersion: "k8s.nginx.org/v1",
},
ObjectMeta: metaV1.ObjectMeta{
Name: "rate-limit-policy3",
Namespace: "default",
},
Spec: conf_v1.PolicySpec{},
Status: conf_v1.PolicyStatus{},
}
)
3 changes: 3 additions & 0 deletions internal/telemetry/data.avdl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ It is the UID of the `kube-system` Namespace. */
/** IngressClasses is the number of Ingress Classes. */
long? IngressClasses = null;

/** Policies is the number of policy resources managed by the NGINX Ingress Controller */
long? Policies = null;

/** GlobalConfiguration indicates if a GlobalConfiguration resource is used. */
boolean? GlobalConfiguration = null;

Expand Down
2 changes: 2 additions & 0 deletions internal/telemetry/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type NICResourceCounts struct {
Ingresses int64
// IngressClasses is the number of Ingress Classes.
IngressClasses int64
// Policies is the number of policy resources managed by NGINX Ingress Controller
Policies int64
// GlobalConfiguration indicates if a GlobalConfiguration resource is used.
GlobalConfiguration bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func (d *NICResourceCounts) Attributes() []attribute.KeyValue {
attrs = append(attrs, attribute.Int64("Services", d.Services))
attrs = append(attrs, attribute.Int64("Ingresses", d.Ingresses))
attrs = append(attrs, attribute.Int64("IngressClasses", d.IngressClasses))
attrs = append(attrs, attribute.Int64("Policies", d.Policies))
attrs = append(attrs, attribute.Bool("GlobalConfiguration", d.GlobalConfiguration))

return attrs
Expand Down
Loading