input/elasticapm/internal/modeldecoder/modeldecoderutil/http.go (66 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package modeldecoderutil import ( "encoding/json" "net/http" "github.com/elastic/apm-data/model/modelpb" "google.golang.org/protobuf/types/known/structpb" ) // HTTPHeadersToStructPb converts h to a *structpb.Struct, suitable for // use in modelpb.HTTP.{Request,Response}.Headers. func HTTPHeadersToStructPb(h http.Header) *structpb.Struct { if len(h) == 0 { return nil } m := make(map[string]any, len(h)) for k, v := range h { arr := make([]any, 0, len(v)) for _, s := range v { arr = append(arr, s) } m[k] = arr } if str, err := structpb.NewStruct(m); err == nil { return str } return nil } func HTTPHeadersToModelpb(h http.Header, out []*modelpb.HTTPHeader) []*modelpb.HTTPHeader { if len(h) == 0 { return nil } out = ResliceAndPopulateNil(out, len(h), NewType[modelpb.HTTPHeader]) i := 0 for k, v := range h { out[i].Key = k out[i].Value = v i++ } return out } // NormalizeHTTPRequestBody recurses through v, replacing any instance of // a json.Number with float64. // // TODO(axw) define a more restrictive schema for context.request.body // so this is unnecessary. Agents are unlikely to send numbers, but // seeing as the schema does not prevent it we need this. func NormalizeHTTPRequestBody(v interface{}) interface{} { switch v := v.(type) { case []interface{}: for i, elem := range v { v[i] = NormalizeHTTPRequestBody(elem) } if len(v) == 0 { return nil } case map[string]interface{}: m := v for k, v := range v { v := NormalizeHTTPRequestBody(v) if v != nil { m[k] = v } else { delete(m, k) } } if len(m) == 0 { return nil } case json.Number: if floatVal, err := v.Float64(); err == nil { return floatVal } } return v }