44package convert // import "go.opentelemetry.io/obi/internal/config/convert"
55
66import (
7+ "errors"
78 "fmt"
89 "reflect"
910 "slices"
@@ -39,6 +40,12 @@ func V2ToRuntime(src *schema.Extension) (*obi.Config, error) {
3940 if err := validateV2RulePatterns (src .Capture .Rules ); err != nil {
4041 return nil , err
4142 }
43+ if err := validateV2HTTPFilters (src .Capture .Instrumentation .HTTP .Filters ); err != nil {
44+ return nil , err
45+ }
46+ if err := validateV2HTTPPayloadExtraction (src .Capture .Instrumentation .HTTP .PayloadExtraction ); err != nil {
47+ return nil , err
48+ }
4249
4350 cfg := runtimeConfigDefaults ()
4451 applyV2Capture (& cfg , src )
@@ -187,6 +194,52 @@ func validateV2RulePatterns(rules []schema.Rule) error {
187194 return nil
188195}
189196
197+ func validateV2HTTPFilters (filters schema.SignalFilters ) error {
198+ if len (filters .Traces ) == 0 || len (filters .Metrics ) == 0 {
199+ return nil
200+ }
201+ if reflect .DeepEqual (filters .Traces , filters .Metrics ) {
202+ return nil
203+ }
204+ return errors .New ("capture.instrumentation.http.filters: trace and metric filters cannot differ" )
205+ }
206+
207+ func validateV2HTTPPayloadExtraction (payload schema.PayloadExtraction ) error {
208+ for i , extractor := range payload .Enabled {
209+ if ! validV2HTTPPayloadExtractor (extractor ) {
210+ return fmt .Errorf (
211+ "capture.instrumentation.http.payload_extraction.enabled[%d]: unknown payload extractor %q" ,
212+ i ,
213+ extractor ,
214+ )
215+ }
216+ }
217+ return nil
218+ }
219+
220+ func validV2HTTPPayloadExtractor (extractor string ) bool {
221+ switch extractor {
222+ case payloadExtractorGraphQL ,
223+ payloadExtractorElasticsearch ,
224+ payloadExtractorAWS ,
225+ payloadExtractorSQLPP ,
226+ payloadExtractorOpenAI ,
227+ payloadExtractorAnthropic ,
228+ payloadExtractorGemini ,
229+ payloadExtractorQwen ,
230+ payloadExtractorBedrock ,
231+ payloadExtractorMCP ,
232+ payloadExtractorEmbedding ,
233+ payloadExtractorRerank ,
234+ payloadExtractorRetrieval ,
235+ payloadExtractorJSONRPC ,
236+ payloadExtractorEnrichment :
237+ return true
238+ default :
239+ return false
240+ }
241+ }
242+
190243func validateV2RuleProcessGlobPatterns (path string , match schema.RuleProcessMatch ) error {
191244 if err := validateGlobAttr (path + ".language_glob" , match .LanguageGlob ); err != nil {
192245 return err
@@ -623,9 +676,7 @@ func applyV2Instrumentation(cfg *obi.Config, instrumentation schema.Instrumentat
623676}
624677
625678func applyFullV2Instrumentation (cfg * obi.Config , instrumentation schema.Instrumentation ) {
626- cfg .EBPF .TrackRequestHeaders = instrumentation .HTTP .TrackRequestHeaders
627- cfg .EBPF .HTTPRequestTimeout = instrumentation .HTTP .RequestTimeout .TimeDuration ()
628- cfg .EBPF .BufferSizes .HTTP = instrumentation .HTTP .BufferSize
679+ applyFullV2HTTPInstrumentation (cfg , instrumentation .HTTP )
629680
630681 cfg .EBPF .HeuristicSQLDetect = instrumentation .SQL .HeuristicDetect
631682 cfg .EBPF .BufferSizes .MySQL = instrumentation .SQL .MySQL .BufferSize
@@ -649,15 +700,7 @@ func applyFullV2Instrumentation(cfg *obi.Config, instrumentation schema.Instrume
649700
650701func applyPartialV2Instrumentation (cfg * obi.Config , instrumentation schema.Instrumentation ) {
651702 if ! zeroValue (instrumentation .HTTP ) {
652- if instrumentation .HTTP .TrackRequestHeaders {
653- cfg .EBPF .TrackRequestHeaders = true
654- }
655- if ! zeroValue (instrumentation .HTTP .RequestTimeout ) {
656- cfg .EBPF .HTTPRequestTimeout = instrumentation .HTTP .RequestTimeout .TimeDuration ()
657- }
658- if instrumentation .HTTP .BufferSize != 0 {
659- cfg .EBPF .BufferSizes .HTTP = instrumentation .HTTP .BufferSize
660- }
703+ applyPartialV2HTTPInstrumentation (cfg , instrumentation .HTTP )
661704 }
662705
663706 if ! zeroValue (instrumentation .SQL ) {
@@ -713,6 +756,214 @@ func applyPartialV2Instrumentation(cfg *obi.Config, instrumentation schema.Instr
713756 }
714757}
715758
759+ func applyFullV2HTTPInstrumentation (cfg * obi.Config , http schema.HTTPInstrumentation ) {
760+ cfg .EBPF .TrackRequestHeaders = http .TrackRequestHeaders
761+ cfg .EBPF .HTTPRequestTimeout = http .RequestTimeout .TimeDuration ()
762+ cfg .EBPF .BufferSizes .HTTP = http .BufferSize
763+
764+ applyV2HTTPFilters (cfg , http .Filters , true )
765+ applyFullV2HTTPRoutes (cfg , http .Routes )
766+ applyFullV2HTTPPayloadExtraction (cfg , http .PayloadExtraction )
767+ }
768+
769+ func applyPartialV2HTTPInstrumentation (cfg * obi.Config , http schema.HTTPInstrumentation ) {
770+ if http .TrackRequestHeaders {
771+ cfg .EBPF .TrackRequestHeaders = true
772+ }
773+ if ! zeroValue (http .RequestTimeout ) {
774+ cfg .EBPF .HTTPRequestTimeout = http .RequestTimeout .TimeDuration ()
775+ }
776+ if http .BufferSize != 0 {
777+ cfg .EBPF .BufferSizes .HTTP = http .BufferSize
778+ }
779+ applyV2HTTPFilters (cfg , http .Filters , false )
780+ applyPartialV2HTTPRoutes (cfg , http .Routes )
781+ applyPartialV2HTTPPayloadExtraction (cfg , http .PayloadExtraction )
782+ }
783+
784+ func applyV2HTTPFilters (cfg * obi.Config , filters schema.SignalFilters , complete bool ) {
785+ if zeroValue (filters ) && ! complete {
786+ return
787+ }
788+ cfg .Filters .Application = attributeFilterMap (v2HTTPFilterMap (filters ))
789+ }
790+
791+ func v2HTTPFilterMap (filters schema.SignalFilters ) schema.AttributeFilters {
792+ if len (filters .Traces ) != 0 {
793+ return filters .Traces
794+ }
795+ return filters .Metrics
796+ }
797+
798+ func applyFullV2HTTPRoutes (cfg * obi.Config , routes schema.HTTPRoutes ) {
799+ applyV2HTTPRouteDiscovery (cfg , routes .Discovery , true )
800+ if ! hasV2HTTPRouteConfig (routes ) {
801+ cfg .Routes = nil
802+ return
803+ }
804+
805+ cfg .Routes = & transform.RoutesConfig {}
806+ applyV2HTTPRouteConfig (cfg .Routes , routes )
807+ }
808+
809+ func applyPartialV2HTTPRoutes (cfg * obi.Config , routes schema.HTTPRoutes ) {
810+ if zeroValue (routes ) {
811+ return
812+ }
813+ applyV2HTTPRouteDiscovery (cfg , routes .Discovery , false )
814+ if ! hasV2HTTPRouteConfig (routes ) {
815+ return
816+ }
817+ if cfg .Routes == nil {
818+ cfg .Routes = & transform.RoutesConfig {}
819+ }
820+ applyV2HTTPRouteConfig (cfg .Routes , routes )
821+ }
822+
823+ func applyV2HTTPRouteDiscovery (cfg * obi.Config , discovery schema.HTTPRouteDiscovery , complete bool ) {
824+ if zeroValue (discovery ) && ! complete {
825+ return
826+ }
827+ if complete || ! zeroValue (discovery .Timeout ) {
828+ cfg .Discovery .RouteHarvesterTimeout = discovery .Timeout .TimeDuration ()
829+ }
830+ if complete || discovery .DisabledLanguages != nil {
831+ cfg .Discovery .DisabledRouteHarvesters = cloneRouteHarvesterLanguages (discovery .DisabledLanguages )
832+ }
833+ if complete || ! zeroValue (discovery .Java .Delay ) {
834+ cfg .Discovery .RouteHarvestConfig .JavaHarvestDelay = discovery .Java .Delay .TimeDuration ()
835+ }
836+ }
837+
838+ func hasV2HTTPRouteConfig (routes schema.HTTPRoutes ) bool {
839+ return routes .Unmatched != nil ||
840+ routes .Patterns != nil ||
841+ routes .IgnoredPatterns != nil ||
842+ routes .IgnoreMode != nil ||
843+ routes .WildcardChar != nil ||
844+ routes .MaxPathSegmentCardinality != nil
845+ }
846+
847+ func applyV2HTTPRouteConfig (dst * transform.RoutesConfig , routes schema.HTTPRoutes ) {
848+ if routes .Unmatched != nil {
849+ dst .Unmatch = * routes .Unmatched
850+ }
851+ if routes .Patterns != nil {
852+ dst .Patterns = cloneStrings (* routes .Patterns )
853+ }
854+ if routes .IgnoredPatterns != nil {
855+ dst .IgnorePatterns = cloneStrings (* routes .IgnoredPatterns )
856+ }
857+ if routes .IgnoreMode != nil {
858+ dst .IgnoredEvents = * routes .IgnoreMode
859+ }
860+ if routes .WildcardChar != nil {
861+ dst .WildcardChar = * routes .WildcardChar
862+ }
863+ if routes .MaxPathSegmentCardinality != nil {
864+ dst .MaxPathSegmentCardinality = * routes .MaxPathSegmentCardinality
865+ }
866+ }
867+
868+ func applyFullV2HTTPPayloadExtraction (cfg * obi.Config , payload schema.PayloadExtraction ) {
869+ http := & cfg .EBPF .PayloadExtraction .HTTP
870+ applyV2HTTPPayloadExtractorMembership (http , payload .Enabled )
871+ http .SQLPP .EndpointPatterns = cloneStrings (payload .SQLPP .EndpointPatterns )
872+ applyFullV2HTTPEnrichment (http , payload .Enrichment )
873+ }
874+
875+ func applyPartialV2HTTPPayloadExtraction (cfg * obi.Config , payload schema.PayloadExtraction ) {
876+ if zeroValue (payload ) {
877+ return
878+ }
879+
880+ http := & cfg .EBPF .PayloadExtraction .HTTP
881+ if payload .Enabled != nil {
882+ applyV2HTTPPayloadExtractorMembership (http , payload .Enabled )
883+ }
884+ if payload .SQLPP .EndpointPatterns != nil {
885+ http .SQLPP .EndpointPatterns = cloneStrings (payload .SQLPP .EndpointPatterns )
886+ }
887+ if ! zeroValue (payload .Enrichment ) {
888+ applyPartialV2HTTPEnrichment (http , payload .Enrichment )
889+ }
890+ }
891+
892+ func applyV2HTTPPayloadExtractorMembership (http * obiconfig.HTTPConfig , enabled []string ) {
893+ http .GraphQL .Enabled = false
894+ http .Elasticsearch .Enabled = false
895+ http .AWS .Enabled = false
896+ http .SQLPP .Enabled = false
897+ http .GenAI .OpenAI .Enabled = false
898+ http .GenAI .Anthropic .Enabled = false
899+ http .GenAI .Gemini .Enabled = false
900+ http .GenAI .Qwen .Enabled = false
901+ http .GenAI .Bedrock .Enabled = false
902+ http .GenAI .MCP .Enabled = false
903+ http .GenAI .Embedding .Enabled = false
904+ http .GenAI .Rerank .Enabled = false
905+ http .GenAI .Retrieval .Enabled = false
906+ http .JSONRPC .Enabled = false
907+ http .Enrichment .Enabled = false
908+
909+ for _ , extractor := range enabled {
910+ switch extractor {
911+ case payloadExtractorGraphQL :
912+ http .GraphQL .Enabled = true
913+ case payloadExtractorElasticsearch :
914+ http .Elasticsearch .Enabled = true
915+ case payloadExtractorAWS :
916+ http .AWS .Enabled = true
917+ case payloadExtractorSQLPP :
918+ http .SQLPP .Enabled = true
919+ case payloadExtractorOpenAI :
920+ http .GenAI .OpenAI .Enabled = true
921+ case payloadExtractorAnthropic :
922+ http .GenAI .Anthropic .Enabled = true
923+ case payloadExtractorGemini :
924+ http .GenAI .Gemini .Enabled = true
925+ case payloadExtractorQwen :
926+ http .GenAI .Qwen .Enabled = true
927+ case payloadExtractorBedrock :
928+ http .GenAI .Bedrock .Enabled = true
929+ case payloadExtractorMCP :
930+ http .GenAI .MCP .Enabled = true
931+ case payloadExtractorEmbedding :
932+ http .GenAI .Embedding .Enabled = true
933+ case payloadExtractorRerank :
934+ http .GenAI .Rerank .Enabled = true
935+ case payloadExtractorRetrieval :
936+ http .GenAI .Retrieval .Enabled = true
937+ case payloadExtractorJSONRPC :
938+ http .JSONRPC .Enabled = true
939+ case payloadExtractorEnrichment :
940+ http .Enrichment .Enabled = true
941+ }
942+ }
943+ }
944+
945+ func applyFullV2HTTPEnrichment (http * obiconfig.HTTPConfig , enrichment schema.HTTPEnrichment ) {
946+ http .Enrichment .Policy .DefaultAction .Headers = enrichment .Policy .DefaultAction .Headers
947+ http .Enrichment .Policy .DefaultAction .Body = enrichment .Policy .DefaultAction .Body
948+ http .Enrichment .Policy .ObfuscationString = enrichment .Policy .ObfuscationString
949+ http .Enrichment .Rules = cloneHTTPParsingRules (enrichment .Rules )
950+ }
951+
952+ func applyPartialV2HTTPEnrichment (http * obiconfig.HTTPConfig , enrichment schema.HTTPEnrichment ) {
953+ if ! zeroValue (enrichment .Policy .DefaultAction .Headers ) {
954+ http .Enrichment .Policy .DefaultAction .Headers = enrichment .Policy .DefaultAction .Headers
955+ }
956+ if ! zeroValue (enrichment .Policy .DefaultAction .Body ) {
957+ http .Enrichment .Policy .DefaultAction .Body = enrichment .Policy .DefaultAction .Body
958+ }
959+ if enrichment .Policy .ObfuscationString != "" {
960+ http .Enrichment .Policy .ObfuscationString = enrichment .Policy .ObfuscationString
961+ }
962+ if enrichment .Rules != nil {
963+ http .Enrichment .Rules = cloneHTTPParsingRules (enrichment .Rules )
964+ }
965+ }
966+
716967func applyProtocolEnablement (cfg * obi.Config , instrumentation schema.Instrumentation , complete bool ) {
717968 cfg .Traces .Instrumentations = applySignalEnablement (cfg .Traces .Instrumentations , instrumentation , "traces" , complete )
718969 cfg .OTELMetrics .Instrumentations = applySignalEnablement (cfg .OTELMetrics .Instrumentations , instrumentation , "metrics" , complete )
@@ -1437,6 +1688,20 @@ func cloneStrings(values []string) []string {
14371688 return append ([]string (nil ), values ... )
14381689}
14391690
1691+ func cloneRouteHarvesterLanguages (values []services.RouteHarvesterLanguage ) []services.RouteHarvesterLanguage {
1692+ if values == nil {
1693+ return nil
1694+ }
1695+ return append ([]services.RouteHarvesterLanguage (nil ), values ... )
1696+ }
1697+
1698+ func cloneHTTPParsingRules (values []obiconfig.HTTPParsingRule ) []obiconfig.HTTPParsingRule {
1699+ if values == nil {
1700+ return nil
1701+ }
1702+ return append ([]obiconfig.HTTPParsingRule (nil ), values ... )
1703+ }
1704+
14401705type runtimeCIDRDefinition interface {
14411706 ~ struct {
14421707 CIDR string `yaml:"cidr" json:"cidr"`
0 commit comments