github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/protocol/decoder/opentelemetry/decoder.go (about)

     1  // Copyright 2022 iLogtail Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package opentelemetry
    16  
    17  import (
    18  	"errors"
    19  	"net/http"
    20  
    21  	"go.opentelemetry.io/collector/pdata/plog/plogotlp"
    22  	"go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp"
    23  	"go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp"
    24  
    25  	"github.com/alibaba/ilogtail/pkg/models"
    26  	"github.com/alibaba/ilogtail/pkg/protocol"
    27  	"github.com/alibaba/ilogtail/pkg/protocol/decoder/common"
    28  )
    29  
    30  const (
    31  	pbContentType   = "application/x-protobuf"
    32  	jsonContentType = "application/json"
    33  )
    34  
    35  const (
    36  	logEventName = "log_event"
    37  )
    38  
    39  // Decoder impl
    40  type Decoder struct {
    41  	Format string
    42  }
    43  
    44  // Decode impl
    45  func (d *Decoder) Decode(data []byte, req *http.Request, tags map[string]string) (logs []*protocol.Log, err error) {
    46  	switch d.Format {
    47  	case common.ProtocolOTLPLogV1:
    48  		otlpLogReq := plogotlp.NewExportRequest()
    49  		otlpLogReq, err = DecodeOtlpRequest(otlpLogReq, data, req)
    50  		if err != nil {
    51  			return logs, err
    52  		}
    53  		logs, err = ConvertOtlpLogRequestV1(otlpLogReq)
    54  	case common.ProtocolOTLPMetricV1:
    55  		otlpMetricReq := pmetricotlp.NewExportRequest()
    56  		otlpMetricReq, err = DecodeOtlpRequest(otlpMetricReq, data, req)
    57  		if err != nil {
    58  			return logs, err
    59  		}
    60  		logs, err = ConvertOtlpMetricRequestV1(otlpMetricReq)
    61  	case common.ProtocolOTLPTraceV1:
    62  		otlpTraceReq := ptraceotlp.NewExportRequest()
    63  		otlpTraceReq, err = DecodeOtlpRequest(otlpTraceReq, data, req)
    64  		if err != nil {
    65  			return logs, err
    66  		}
    67  		logs, err = ConvertOtlpTraceRequestV1(otlpTraceReq)
    68  	default:
    69  		err = errors.New("Invalid RequestURI: " + req.RequestURI)
    70  	}
    71  	return logs, err
    72  }
    73  
    74  // ParseRequest impl
    75  func (d *Decoder) ParseRequest(res http.ResponseWriter, req *http.Request, maxBodySize int64) (data []byte, statusCode int, err error) {
    76  	return common.CollectBody(res, req, maxBodySize)
    77  }
    78  
    79  // DecodeV2 impl
    80  func (d *Decoder) DecodeV2(data []byte, req *http.Request) (groups []*models.PipelineGroupEvents, err error) {
    81  	switch d.Format {
    82  	case common.ProtocolOTLPLogV1:
    83  		otlpLogReq := plogotlp.NewExportRequest()
    84  		otlpLogReq, err = DecodeOtlpRequest(otlpLogReq, data, req)
    85  		if err != nil {
    86  			return groups, err
    87  		}
    88  		groups, err = ConvertOtlpLogRequestToGroupEvents(otlpLogReq)
    89  	case common.ProtocolOTLPMetricV1:
    90  		otlpMetricReq := pmetricotlp.NewExportRequest()
    91  		otlpMetricReq, err = DecodeOtlpRequest(otlpMetricReq, data, req)
    92  		if err != nil {
    93  			return groups, err
    94  		}
    95  		groups, err = ConvertOtlpMetricRequestToGroupEvents(otlpMetricReq)
    96  	case common.ProtocolOTLPTraceV1:
    97  		otlpTraceReq := ptraceotlp.NewExportRequest()
    98  		otlpTraceReq, err = DecodeOtlpRequest(otlpTraceReq, data, req)
    99  		if err != nil {
   100  			return groups, err
   101  		}
   102  		groups, err = ConvertOtlpTraceRequestToGroupEvents(otlpTraceReq)
   103  	default:
   104  		err = errors.New("Invalid RequestURI: " + req.RequestURI)
   105  	}
   106  	return groups, err
   107  }
   108  
   109  // DecodeOtlpRequest decodes the data and fills into the otlp logs/metrics/traces export request.
   110  func DecodeOtlpRequest[P interface {
   111  	UnmarshalProto(data []byte) error
   112  	UnmarshalJSON(data []byte) error
   113  }](des P, data []byte, req *http.Request) (P, error) {
   114  	var err error
   115  	contentType := req.Header.Get("Content-Type")
   116  	switch contentType {
   117  	case pbContentType:
   118  		if err = des.UnmarshalProto(data); err != nil {
   119  			return des, err
   120  		}
   121  	case jsonContentType:
   122  		if err = des.UnmarshalJSON(data); err != nil {
   123  			return des, err
   124  		}
   125  	default:
   126  		err = errors.New("Invalid ContentType: " + contentType)
   127  	}
   128  	return des, err
   129  }