1// Copyright The OpenTelemetry 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 15package otlphttpexporter 16 17import ( 18 "context" 19 "fmt" 20 "net/url" 21 "time" 22 23 "go.opentelemetry.io/collector/component" 24 "go.opentelemetry.io/collector/config" 25 "go.opentelemetry.io/collector/config/confighttp" 26 "go.opentelemetry.io/collector/consumer" 27 "go.opentelemetry.io/collector/exporter/exporterhelper" 28) 29 30const ( 31 // The value of "type" key in configuration. 32 typeStr = "otlphttp" 33) 34 35// NewFactory creates a factory for OTLP exporter. 36func NewFactory() component.ExporterFactory { 37 return exporterhelper.NewFactory( 38 typeStr, 39 createDefaultConfig, 40 exporterhelper.WithTraces(createTracesExporter), 41 exporterhelper.WithMetrics(createMetricsExporter), 42 exporterhelper.WithLogs(createLogsExporter)) 43} 44 45func createDefaultConfig() config.Exporter { 46 return &Config{ 47 ExporterSettings: config.NewExporterSettings(config.NewID(typeStr)), 48 RetrySettings: exporterhelper.DefaultRetrySettings(), 49 QueueSettings: exporterhelper.DefaultQueueSettings(), 50 HTTPClientSettings: confighttp.HTTPClientSettings{ 51 Endpoint: "", 52 Timeout: 30 * time.Second, 53 Headers: map[string]string{}, 54 // We almost read 0 bytes, so no need to tune ReadBufferSize. 55 WriteBufferSize: 512 * 1024, 56 }, 57 } 58} 59 60func composeSignalURL(oCfg *Config, signalOverrideURL string, signalName string) (string, error) { 61 switch { 62 case signalOverrideURL != "": 63 _, err := url.Parse(signalOverrideURL) 64 if err != nil { 65 return "", fmt.Errorf("%s_endpoint must be a valid URL", signalName) 66 } 67 return signalOverrideURL, nil 68 case oCfg.Endpoint == "": 69 return "", fmt.Errorf("either endpoint or %s_endpoint must be specified", signalName) 70 default: 71 return oCfg.Endpoint + "/v1/" + signalName, nil 72 } 73} 74 75func createTracesExporter( 76 _ context.Context, 77 set component.ExporterCreateSettings, 78 cfg config.Exporter, 79) (component.TracesExporter, error) { 80 oce, err := newExporter(cfg, set.Logger) 81 if err != nil { 82 return nil, err 83 } 84 oCfg := cfg.(*Config) 85 86 oce.tracesURL, err = composeSignalURL(oCfg, oCfg.TracesEndpoint, "traces") 87 if err != nil { 88 return nil, err 89 } 90 91 return exporterhelper.NewTracesExporter( 92 cfg, 93 set, 94 oce.pushTraces, 95 exporterhelper.WithStart(oce.start), 96 exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), 97 // explicitly disable since we rely on http.Client timeout logic. 98 exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), 99 exporterhelper.WithRetry(oCfg.RetrySettings), 100 exporterhelper.WithQueue(oCfg.QueueSettings)) 101} 102 103func createMetricsExporter( 104 _ context.Context, 105 set component.ExporterCreateSettings, 106 cfg config.Exporter, 107) (component.MetricsExporter, error) { 108 oce, err := newExporter(cfg, set.Logger) 109 if err != nil { 110 return nil, err 111 } 112 oCfg := cfg.(*Config) 113 114 oce.metricsURL, err = composeSignalURL(oCfg, oCfg.MetricsEndpoint, "metrics") 115 if err != nil { 116 return nil, err 117 } 118 119 return exporterhelper.NewMetricsExporter( 120 cfg, 121 set, 122 oce.pushMetrics, 123 exporterhelper.WithStart(oce.start), 124 exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), 125 // explicitly disable since we rely on http.Client timeout logic. 126 exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), 127 exporterhelper.WithRetry(oCfg.RetrySettings), 128 exporterhelper.WithQueue(oCfg.QueueSettings)) 129} 130 131func createLogsExporter( 132 _ context.Context, 133 set component.ExporterCreateSettings, 134 cfg config.Exporter, 135) (component.LogsExporter, error) { 136 oce, err := newExporter(cfg, set.Logger) 137 if err != nil { 138 return nil, err 139 } 140 oCfg := cfg.(*Config) 141 142 oce.logsURL, err = composeSignalURL(oCfg, oCfg.LogsEndpoint, "logs") 143 if err != nil { 144 return nil, err 145 } 146 147 return exporterhelper.NewLogsExporter( 148 cfg, 149 set, 150 oce.pushLogs, 151 exporterhelper.WithStart(oce.start), 152 exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}), 153 // explicitly disable since we rely on http.Client timeout logic. 154 exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}), 155 exporterhelper.WithRetry(oCfg.RetrySettings), 156 exporterhelper.WithQueue(oCfg.QueueSettings)) 157} 158