Skip to content

Commit

Permalink
Begin implementation of OTLP/HTTP exporter
Browse files Browse the repository at this point in the history
This adds the initial config and factory boilerplate and corresponding tests.

Contributes to: open-telemetry#882

Testing: config and factory tests unit tests added.

Documentation: Added README.

The next PR will add the exporting logic.
  • Loading branch information
Tigran Najaryan committed Oct 9, 2020
1 parent 9aa0c5e commit 0cbf345
Show file tree
Hide file tree
Showing 9 changed files with 651 additions and 0 deletions.
35 changes: 35 additions & 0 deletions exporter/otlphttpexporter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# OTLP/HTTP Exporter

Exports traces and/or metrics via HTTP using
[OTLP](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/protocol/otlp.md) format.

The following settings are required:

- `endpoint` (no default): The target URL to send data to (e.g.: https://example.com:55681/v1/traces).

The following settings can be optionally configured:

- `insecure` (default = false): when set to true disables verifying the server's
certificate chain and host name. The connection is still encrypted but server identity
is not verified.
- `ca_file` path to the CA cert. For a client this verifies the server certificate. Should
only be used if `insecure` is set to false.
- `cert_file` path to the TLS cert to use for TLS required connections. Should
only be used if `insecure` is set to false.
- `key_file` path to the TLS key to use for TLS required connections. Should
only be used if `insecure` is set to false.
- `timeout` (default = 30s): How long to wait until the connection is close.
- `read_buffer_size` (default = 0): ReadBufferSize for HTTP client.
- `write_buffer_size` (default = 512 * 1024): WriteBufferSize for HTTP client.


Example:

```yaml
exporters:
otlphttp:
endpoint: https://example.com:55681/v1/traces
```
The full list of settings exposed for this exporter are documented [here](./config.go)
with detailed sample configurations [here](./testdata/config.yaml).
29 changes: 29 additions & 0 deletions exporter/otlphttpexporter/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright The OpenTelemetry Authors
//
// Licensed 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 otlphttpexporter

import (
"go.opentelemetry.io/collector/config/confighttp"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/exporter/exporterhelper"
)

// Config defines configuration for OTLP/HTTP exporter.
type Config struct {
configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct.
confighttp.HTTPClientSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct.
exporterhelper.QueueSettings `mapstructure:"sending_queue"`
exporterhelper.RetrySettings `mapstructure:"retry_on_failure"`
}
85 changes: 85 additions & 0 deletions exporter/otlphttpexporter/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright The OpenTelemetry Authors
//
// Licensed 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 otlphttpexporter

import (
"path"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/confighttp"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/config/configtest"
"go.opentelemetry.io/collector/config/configtls"
"go.opentelemetry.io/collector/exporter/exporterhelper"
)

func TestLoadConfig(t *testing.T) {
factories, err := componenttest.ExampleComponents()
assert.NoError(t, err)

factory := NewFactory()
factories.Exporters[typeStr] = factory
cfg, err := configtest.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories)

require.NoError(t, err)
require.NotNil(t, cfg)

e0 := cfg.Exporters["otlphttp"]
assert.Equal(t, e0, factory.CreateDefaultConfig())

e1 := cfg.Exporters["otlphttp/2"]
assert.Equal(t, e1,
&Config{
ExporterSettings: configmodels.ExporterSettings{
NameVal: "otlphttp/2",
TypeVal: "otlphttp",
},
RetrySettings: exporterhelper.RetrySettings{
Enabled: true,
InitialInterval: 10 * time.Second,
MaxInterval: 1 * time.Minute,
MaxElapsedTime: 10 * time.Minute,
},
QueueSettings: exporterhelper.QueueSettings{
Enabled: true,
NumConsumers: 2,
QueueSize: 10,
},
HTTPClientSettings: confighttp.HTTPClientSettings{
Headers: map[string]string{
"can you have a . here?": "F0000000-0000-0000-0000-000000000000",
"header1": "234",
"another": "somevalue",
},
Endpoint: "https://1.2.3.4:1234",
TLSSetting: configtls.TLSClientSetting{
TLSSetting: configtls.TLSSetting{
CAFile: "/var/lib/mycert.pem",
CertFile: "certfile",
KeyFile: "keyfile",
},
Insecure: true,
},
ReadBufferSize: 123,
WriteBufferSize: 345,
Timeout: time.Second * 10,
},
})
}
135 changes: 135 additions & 0 deletions exporter/otlphttpexporter/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright The OpenTelemetry Authors
//
// Licensed 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 otlphttpexporter

import (
"context"
"time"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/confighttp"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/exporter/exporterhelper"
)

const (
// The value of "type" key in configuration.
typeStr = "otlphttp"
)

// NewFactory creates a factory for OTLP exporter.
func NewFactory() component.ExporterFactory {
return exporterhelper.NewFactory(
typeStr,
createDefaultConfig,
exporterhelper.WithTraces(createTraceExporter),
exporterhelper.WithMetrics(createMetricsExporter),
exporterhelper.WithLogs(createLogsExporter))
}

func createDefaultConfig() configmodels.Exporter {
return &Config{
ExporterSettings: configmodels.ExporterSettings{
TypeVal: typeStr,
NameVal: typeStr,
},
RetrySettings: exporterhelper.CreateDefaultRetrySettings(),
QueueSettings: exporterhelper.CreateDefaultQueueSettings(),
HTTPClientSettings: confighttp.HTTPClientSettings{
Endpoint: "",
Timeout: 30 * time.Second,
Headers: map[string]string{},
// We almost read 0 bytes, so no need to tune ReadBufferSize.
WriteBufferSize: 512 * 1024,
},
}
}

func createTraceExporter(
_ context.Context,
_ component.ExporterCreateParams,
cfg configmodels.Exporter,
) (component.TraceExporter, error) {
oce, err := newExporter(cfg)
if err != nil {
return nil, err
}
oCfg := cfg.(*Config)
oexp, err := exporterhelper.NewTraceExporter(
cfg,
oce.pushTraceData,
// explicitly disable since we rely on http.Client timeout logic.
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}),
exporterhelper.WithRetry(oCfg.RetrySettings),
exporterhelper.WithQueue(oCfg.QueueSettings),
exporterhelper.WithShutdown(oce.shutdown))
if err != nil {
return nil, err
}

return oexp, nil
}

func createMetricsExporter(
_ context.Context,
_ component.ExporterCreateParams,
cfg configmodels.Exporter,
) (component.MetricsExporter, error) {
oce, err := newExporter(cfg)
if err != nil {
return nil, err
}
oCfg := cfg.(*Config)
oexp, err := exporterhelper.NewMetricsExporter(
cfg,
oce.pushMetricsData,
// explicitly disable since we rely on http.Client timeout logic.
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}),
exporterhelper.WithRetry(oCfg.RetrySettings),
exporterhelper.WithQueue(oCfg.QueueSettings),
exporterhelper.WithShutdown(oce.shutdown),
)
if err != nil {
return nil, err
}

return oexp, nil
}

func createLogsExporter(
_ context.Context,
_ component.ExporterCreateParams,
cfg configmodels.Exporter,
) (component.LogsExporter, error) {
oce, err := newExporter(cfg)
if err != nil {
return nil, err
}
oCfg := cfg.(*Config)
oexp, err := exporterhelper.NewLogsExporter(
cfg,
oce.pushLogData,
// explicitly disable since we rely on http.Client timeout logic.
exporterhelper.WithTimeout(exporterhelper.TimeoutSettings{Timeout: 0}),
exporterhelper.WithRetry(oCfg.RetrySettings),
exporterhelper.WithQueue(oCfg.QueueSettings),
exporterhelper.WithShutdown(oce.shutdown),
)
if err != nil {
return nil, err
}

return oexp, nil
}
Loading

0 comments on commit 0cbf345

Please sign in to comment.