func NewConcurrentObserver(observers []Observer, log logr.Logger) Observer {
	return &ConcurrentObserver{observers, log}
}
NewConcurrentObserver creates a ConcurrentObserver
package observe
import (
	"context"
	picchuv1alpha1 "go.medium.engineering/picchu/pkg/apis/picchu/v1alpha1"
	"github.com/go-logr/logr"
	"golang.org/x/sync/errgroup"
	appsv1 "k8s.io/api/apps/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)
type Observer interface {
	Observe(context.Context, string) (*Observation, error)
}
type ClusterObserver struct {
	cluster Cluster
	cli     client.Client
	log     logr.Logger
}
func NewClusterObserver(cluster Cluster, cli client.Client, log logr.Logger) Observer {
	return &ClusterObserver{cluster, cli, log}
}
func (o *ClusterObserver) Observe(ctx context.Context, namespace string) (*Observation, error) {
	replicaSetList := &appsv1.ReplicaSetList{}
	listOpts := &client.ListOptions{Namespace: namespace}
	err := o.cli.List(ctx, replicaSetList, listOpts)
	if err != nil {
		return nil, err
	}
	replicaSets := []replicaSet{}
	for _, rs := range replicaSetList.Items {
		tag, ok := rs.Labels[picchuv1alpha1.LabelTag]
		if !ok {
			continue
		}
		replicaSets = append(replicaSets, replicaSet{
			Cluster: o.cluster,
			Tag:     tag,
			Desired: *rs.Spec.Replicas,
			Current: rs.Status.AvailableReplicas,
		})
	}
	obs := &Observation{
		ReplicaSets: replicaSets,
	}
	o.log.Info("Cluster state", "Observation", obs)
	return obs, nil
}
type ConcurrentObserver struct {
	observers []Observer
	log       logr.Logger
}