mergeObservabilityConfigs takes a slice of observability config JSON strings (one per import), extracts all OTLP endpoint entries from each (supporting string, object, and array forms), deduplicates by URL (first occurrence wins), and returns a single merged observability JSON string with all endpoi
(configs []string)
| 939 | // attributes are also merged across imports (first occurrence wins per key). |
| 940 | // Returns "" when no valid endpoints or attributes are found. |
| 941 | func mergeObservabilityConfigs(configs []string) string { |
| 942 | seen := make(map[string]struct { |
| 943 | }) |
| 944 | var allEndpoints []observabilityImportEndpoint |
| 945 | mergedAttrs := make(map[string]string) |
| 946 | var mergedGitHubApp map[string]any |
| 947 | |
| 948 | for i, cfgJSON := range configs { |
| 949 | if cfgJSON == "" { |
| 950 | continue |
| 951 | } |
| 952 | var obs map[string]any |
| 953 | if err := json.Unmarshal([]byte(cfgJSON), &obs); err != nil { |
| 954 | parserLog.Printf("Failed to unmarshal observability config from import %d during merge: %v", i, err) |
| 955 | continue |
| 956 | } |
| 957 | for _, e := range extractOTLPEndpointsFromObsMap(obs) { |
| 958 | if !setutil.Contains(seen, e.URL) { |
| 959 | seen[e.URL] = struct { |
| 960 | }{} |
| 961 | allEndpoints = append(allEndpoints, e) |
| 962 | } |
| 963 | } |
| 964 | for k, v := range extractOTLPAttributesFromObsMap(obs) { |
| 965 | if _, exists := mergedAttrs[k]; !exists { |
| 966 | mergedAttrs[k] = v |
| 967 | } |
| 968 | } |
| 969 | if mergedGitHubApp == nil { |
| 970 | mergedGitHubApp = extractOTLPGitHubAppFromObsMap(obs) |
| 971 | } |
| 972 | } |
| 973 | |
| 974 | if len(allEndpoints) == 0 && len(mergedAttrs) == 0 && mergedGitHubApp == nil { |
| 975 | return "" |
| 976 | } |
| 977 | |
| 978 | // Produce a merged config with the endpoint field as an array so that the |
| 979 | // workflow package's collectAllOTLPEndpoints handles it uniformly. Include |
| 980 | // any merged custom attributes so the orchestrator can propagate them. |
| 981 | otlpMap := map[string]any{} |
| 982 | if len(allEndpoints) > 0 { |
| 983 | otlpMap["endpoint"] = allEndpoints |
| 984 | } |
| 985 | if len(mergedAttrs) > 0 { |
| 986 | otlpMap["attributes"] = mergedAttrs |
| 987 | } |
| 988 | if mergedGitHubApp != nil { |
| 989 | otlpMap["github-app"] = mergedGitHubApp |
| 990 | } |
| 991 | merged := map[string]any{"otlp": otlpMap} |
| 992 | b, err := json.Marshal(merged) |
| 993 | if err != nil { |
| 994 | parserLog.Printf("Failed to marshal %d merged OTLP endpoints: %v", len(allEndpoints), err) |
| 995 | return "" |
| 996 | } |
| 997 | return string(b) |
| 998 | } |