func GenerateHints()

in utils/hints.go [208:341]


func GenerateHints(annotations mapstr.M, container, prefix string, validate bool, allSupportedHints []string) (mapstr.M, []string) {
	hints := mapstr.M{}
	var incorrecthints []string
	var incorrecthint string
	var digitCheck = regexp.MustCompile(`^[0-9]+$`)

	if rawEntries, err := annotations.GetValue(prefix); err == nil {
		if entries, ok := rawEntries.(mapstr.M); ok {

			if validate {
				//Start of Annotation Check: whether the annotation follows the supported format and vocabulary. The check happens for annotations that have prefix co.elastic
				datastreamlist := GetHintAsList(entries, logName+"/"+"data_streams", "")
				// We check if multiple data_streams are defined and we retrieve the hints per data_stream. Only applicable in elastic-agent
				// See Metrics_apache_package_and_specific_config_per_datastream test case in hints_test.go
				for _, stream := range datastreamlist {
					allSupportedHints = append(allSupportedHints, stream)
					incorrecthints = checkSupportedHintsSets(annotations, prefix, stream, logName, allSupportedHints, incorrecthints)
				}
				metricsetlist := GetHintAsList(entries, "metrics"+"/"+"metricsets", "")
				// We check if multiple metrcisets are defined and we retrieve the hints per metricset. Only applicable in beats
				//See Metrics_istio_module_and_specific_config_per_metricset test case in hints_test.go
				for _, metric := range metricsetlist {
					allSupportedHints = append(allSupportedHints, metric)
					incorrecthints = checkSupportedHintsSets(annotations, prefix, metric, "metrics", allSupportedHints, incorrecthints)
				}
			} //end of annotation check

			for key, rawValue := range entries {
				enumeratedmodules := []string{}
				// If there are top level hints like co.elastic.logs/ then just add the values after the /
				// Only consider namespaced annotations
				parts := strings.Split(key, "/")
				if len(parts) == 2 {
					hintKey := fmt.Sprintf("%s.%s", parts[0], parts[1])

					if validate {
						checkdigit := digitCheck.MatchString(parts[1]) // With this regex we check if enumeration for modules is provided
						if checkdigit {
							allSupportedHints = append(allSupportedHints, parts[1])

							specificlist, _ := entries.GetValue(key)
							if specificentries, ok := specificlist.(mapstr.M); ok {
								for keyspec := range specificentries {
									// enumeratedmodules will be populated only in cases we have module enumeration, like:
									// "co.elastic.metrics/1.module":  "prometheus",
									// "co.elastic.metrics/2.module":  "istiod",
									enumeratedmodules = append(enumeratedmodules, keyspec)
								}
							}
						}
						// We check if multiple metrcisets are defined and we retrieve the hints per metricset. Only applicable in beats
						// See Metrics_multiple_modules_and_specific_config_per_module test case in hints_test.go
						for _, metric := range enumeratedmodules {
							_, incorrecthint = checkSupportedHints(metric, fmt.Sprintf("%s.%s", key, metric), allSupportedHints)
							if incorrecthint != "" {
								incorrecthints = append(incorrecthints, incorrecthint)
							}

						}
						//We check whether the provided annotation follows the supported format and vocabulary. The check happens for annotations that have prefix co.elastic
						_, incorrecthint = checkSupportedHints(parts[1], key, allSupportedHints)
					} //end of annotation check

					// Insert only if there is no entry already. container level annotations take
					// higher priority.
					if _, err := hints.GetValue(hintKey); err != nil {
						_, err = hints.Put(hintKey, rawValue)
						if err != nil {
							continue
						}
					}
				} else if container != "" {
					// Only consider annotations that are of type mapstr.M as we are looking for
					// container level nesting
					builderHints, ok := rawValue.(mapstr.M)
					if !ok {
						continue
					}

					// Check for <containerName>/ prefix
					for hintKey, rawVal := range builderHints {
						if strings.HasPrefix(hintKey, container) {
							// Split the key to get part[1] to be the hint
							parts := strings.Split(hintKey, "/")

							if validate {
								checkdigit := digitCheck.MatchString(parts[1]) // With this regex we check if enumeration for modules is provided
								if checkdigit {
									allSupportedHints = append(allSupportedHints, parts[1])

									specificlist, _ := entries.GetValue(key)
									if specificentries, ok := specificlist.(mapstr.M); ok {
										for keyspec := range specificentries {
											// enumeratedmodules will be populated only in cases we have module enumeration, like:
											// "co.elastic.metrics/1.module":  "prometheus",
											// "co.elastic.metrics/2.module":  "istiod",
											enumeratedmodules = append(enumeratedmodules, keyspec)
										}
									}
								}

								// We check if multiple metrcisets are defined and we retrieve the hints per metricset. Only applicable in beats
								// See Metrics_multiple_modules_and_specific_config_per_module test case in hints_test.go
								for _, metric := range enumeratedmodules {
									_, incorrecthint = checkSupportedHints(metric, fmt.Sprintf("%s.%s", key, metric), allSupportedHints)
									if incorrecthint != "" {
										incorrecthints = append(incorrecthints, incorrecthint)
									}

								}
								//We check whether the provided annotation follows the supported format and vocabulary. The check happens for annotations that have prefix co.elastic
								_, incorrecthint = checkSupportedHints(parts[1], key, allSupportedHints)
							} //end of annotation check

							if len(parts) == 2 {
								// key will be the hint type
								hintKey := fmt.Sprintf("%s.%s", key, parts[1])
								_, err := hints.Put(hintKey, rawVal)
								if err != nil {
									continue
								}
							}
						}
					}
				}
				if validate && incorrecthint != "" {
					incorrecthints = append(incorrecthints, incorrecthint)
				}
			}
		}
	}

	return hints, incorrecthints
}