code: func (mc *MetricsConfiguration) NewRootScopeReporter(
  	r tally.CachedStatsReporter,
  ) (tally.Scope, io.Closer) {
  	var (
  		prefix string
  		tags   map[string]string
  	)
  
  	if mc.RootScope != nil {
  		if mc.RootScope.Prefix != "" {
  			prefix = mc.RootScope.Prefix
  		}
  		if mc.RootScope.CommonTags != nil {
  			tags = mc.RootScope.CommonTags
  		}
  	}
  
  	var sanitizeOpts *tally.SanitizeOptions
  	if mc.Sanitization != nil {
  		sanitizeOpts = mc.Sanitization.NewOptions()
  	}
  
  	scopeOpts := tally.ScopeOptions{
  		Tags:            tags,
  		Prefix:          prefix,
  		CachedReporter:  r,
  		SanitizeOptions: sanitizeOpts,
  	}
  	reportInterval := mc.ReportInterval()
  	scope, closer := tally.NewRootScope(scopeOpts, reportInterval)
  	if mc.ExtendedMetrics != nil {
  		StartReportingExtendedMetrics(scope, reportInterval, *mc.ExtendedMetrics)
  	}
  
  	return scope, closer
  }
docs: // NewRootScopeReporter creates a new tally.Scope based on a given tally.CachedStatsReporter
  // and given root scope config. In most cases NewRootScope should be used, but for cases such
  // as hooking into the reporter to manually flush it.