in exporter/metric/metric.go [171:210]
func (me *metricExporter) exportMetricDescriptor(ctx context.Context, rm *metricdata.ResourceMetrics) error {
// We only send metric descriptors if we're configured *and* we're not sending service timeseries.
if me.o.disableCreateMetricDescriptors {
return nil
}
me.mdLock.Lock()
defer me.mdLock.Unlock()
mds := make(map[key]*googlemetricpb.MetricDescriptor)
extraLabels := me.extraLabelsFromResource(rm.Resource)
for _, scope := range rm.ScopeMetrics {
for _, metrics := range scope.Metrics {
k := keyOf(metrics, scope.Scope)
if _, ok := me.mdCache[k]; ok {
continue
}
if _, localok := mds[k]; !localok {
md := me.recordToMdpb(metrics, extraLabels)
mds[k] = md
}
}
}
// TODO: This process is synchronous and blocks longer time if records in cps
// have many different descriptors. In the cps.ForEach above, it should spawn
// goroutines to send CreateMetricDescriptorRequest asynchronously in the case
// the descriptor does not exist in global cache (me.mdCache).
// See details in #26.
var errs []error
for kmd, md := range mds {
err := me.createMetricDescriptorIfNeeded(ctx, md)
if err == nil {
me.mdCache[kmd] = md
}
errs = append(errs, err)
}
return errors.Join(errs...)
}