func AddEvent()

in sharedlibraries/metricevents/metricevents.go [104:159]


func AddEvent(ctx context.Context, p Parameters) bool {
	mu.Lock()
	defer mu.Unlock()
	if events == nil {
		events = make(map[string]eventData)
	}
	if logDelayEvents == nil {
		logDelayEvents = make(map[string]eventData)
	}

	key := p.Path + p.Identifier
	stateChange := false
	if event, exists := events[key]; exists && event.lastValue != p.Value {
		stateChange = true
		// Some metric paths are sent multiple times - one for each service.
		// To avoid logging the same event multiple times, we will group labels
		// that share the same path and value and log after a short delay.
		logDelayKey := p.Path + p.Value
		if logEvent, exists := logDelayEvents[logDelayKey]; exists {
			for k, v := range event.labels {
				if logEvent.labels[k] != v {
					logEvent.labels[k] += ", " + v
				}
			}
		} else {
			logDelayEvents[logDelayKey] = event
			time.AfterFunc(defaultLogDelay, func() {
				// Lock the mutex as this runs in a separate goroutine.
				mu.Lock()
				defer mu.Unlock()
				logEvent := logDelayEvents[logDelayKey]
				// Sort and remove duplicate labels.
				for k, labels := range logEvent.labels {
					labelSlice := strings.Split(labels, ", ")
					sort.Strings(labelSlice)
					logEvent.labels[k] = strings.Join(slices.Compact(labelSlice), ", ")
				}
				logLevel, ok := logLevelMap[p.Path][p.Value]
				if !ok {
					logLevel = zapcore.InfoLevel
				}
				// NOTE: This log message has specific keys used in querying Cloud Logging.
				// Never change these keys since it would have downstream effects.
				log.CtxLogger(ctx).Logw(logLevel, p.Message, "metricEvent", true, "metric", p.Path, "previousValue", logEvent.lastValue, "currentValue", p.Value, "previousLabels", p.Labels, "currentLabels", logEvent.labels, "lastUpdated", logEvent.lastUpdated)
				delete(logDelayEvents, logDelayKey)
			})
		}
	}

	events[key] = eventData{
		labels:      p.Labels,
		lastValue:   p.Value,
		lastUpdated: time.Now(),
	}
	return stateChange
}