@@ -28,7 +28,7 @@ import (
2828 v1 "github.com/containerd/containerd/metrics/types/v1"
2929 "github.com/containerd/containerd/namespaces"
3030 "github.com/containerd/typeurl"
31- metrics "github.com/docker/go-metrics"
31+ "github.com/docker/go-metrics"
3232 "github.com/gogo/protobuf/types"
3333 "github.com/prometheus/client_golang/prometheus"
3434)
@@ -53,7 +53,7 @@ func NewCollector(ns *metrics.Namespace) *Collector {
5353 // add machine cpus and memory info
5454 c := & Collector {
5555 ns : ns ,
56- tasks : make (map [string ]Statable ),
56+ tasks : make (map [string ]entry ),
5757 }
5858 c .metrics = append (c .metrics , pidMetrics ... )
5959 c .metrics = append (c .metrics , cpuMetrics ... )
@@ -69,12 +69,19 @@ func taskID(id, namespace string) string {
6969 return fmt .Sprintf ("%s-%s" , id , namespace )
7070}
7171
72+ type entry struct {
73+ task Statable
74+ // ns is an optional child namespace that contains additional to parent labels.
75+ // This can be used to append task specific labels to be able to differentiate the different containerd metrics.
76+ ns * metrics.Namespace
77+ }
78+
7279// Collector provides the ability to collect container stats and export
7380// them in the prometheus format
7481type Collector struct {
7582 mu sync.RWMutex
7683
77- tasks map [string ]Statable
84+ tasks map [string ]entry
7885 ns * metrics.Namespace
7986 metrics []* metric
8087 storedMetrics chan prometheus.Metric
@@ -109,10 +116,11 @@ storedLoop:
109116 wg .Wait ()
110117}
111118
112- func (c * Collector ) collect (t Statable , ch chan <- prometheus.Metric , block bool , wg * sync.WaitGroup ) {
119+ func (c * Collector ) collect (entry entry , ch chan <- prometheus.Metric , block bool , wg * sync.WaitGroup ) {
113120 if wg != nil {
114121 defer wg .Done ()
115122 }
123+ t := entry .task
116124 ctx := namespaces .WithNamespace (context .Background (), t .Namespace ())
117125 stats , err := t .Stats (ctx )
118126 if err != nil {
@@ -129,13 +137,17 @@ func (c *Collector) collect(t Statable, ch chan<- prometheus.Metric, block bool,
129137 log .L .WithError (err ).Errorf ("invalid metric type for %s" , t .ID ())
130138 return
131139 }
140+ ns := entry .ns
141+ if ns == nil {
142+ ns = c .ns
143+ }
132144 for _ , m := range c .metrics {
133- m .collect (t .ID (), t .Namespace (), s , c . ns , ch , block )
145+ m .collect (t .ID (), t .Namespace (), s , ns , ch , block )
134146 }
135147}
136148
137149// Add adds the provided cgroup and id so that metrics are collected and exported
138- func (c * Collector ) Add (t Statable ) error {
150+ func (c * Collector ) Add (t Statable , labels map [ string ] string ) error {
139151 if c .ns == nil {
140152 return nil
141153 }
@@ -145,7 +157,11 @@ func (c *Collector) Add(t Statable) error {
145157 if _ , ok := c .tasks [id ]; ok {
146158 return nil // requests to collect metrics should be idempotent
147159 }
148- c .tasks [id ] = t
160+ entry := entry {task : t }
161+ if labels != nil {
162+ entry .ns = c .ns .WithConstLabels (labels )
163+ }
164+ c .tasks [id ] = entry
149165 return nil
150166}
151167
@@ -165,6 +181,6 @@ func (c *Collector) RemoveAll() {
165181 return
166182 }
167183 c .mu .Lock ()
168- c .tasks = make (map [string ]Statable )
184+ c .tasks = make (map [string ]entry )
169185 c .mu .Unlock ()
170186}
0 commit comments