Skip to content

Commit

Permalink
Add profiles support to OTLP HTTP exporter (#11450)
Browse files Browse the repository at this point in the history
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description

This uses the profiles internal packages that were implemented in
previous PRs to provide profiles support to the OTLP HTTP exporter.

This PR requires #11226✅  to be merged first.
  • Loading branch information
dmathieu authored Oct 18, 2024
1 parent 9cb0761 commit f330cfb
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 19 deletions.
25 changes: 25 additions & 0 deletions .chloggen/otlp-http-exporter-profiles.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: otlphttpexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add profiles support to OTLP HTTP exporter

# One or more tracking issues or pull requests related to the change
issues: [11450]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [api]
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,13 @@ check-contrib:
-replace go.opentelemetry.io/collector/connector/connectorprofiles=$(CURDIR)/connector/connectorprofiles \
-replace go.opentelemetry.io/collector/connector/forwardconnector=$(CURDIR)/connector/forwardconnector \
-replace go.opentelemetry.io/collector/consumer=$(CURDIR)/consumer \
-replace go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles=$(CURDIR)/consumer/consumererror/consumererrorprofiles \
-replace go.opentelemetry.io/collector/consumer/consumerprofiles=$(CURDIR)/consumer/consumerprofiles \
-replace go.opentelemetry.io/collector/consumer/consumertest=$(CURDIR)/consumer/consumertest \
-replace go.opentelemetry.io/collector/exporter=$(CURDIR)/exporter \
-replace go.opentelemetry.io/collector/exporter/debugexporter=$(CURDIR)/exporter/debugexporter \
-replace go.opentelemetry.io/collector/exporter/exporterprofiles=$(CURDIR)/exporter/exporterprofiles \
-replace go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles=$(CURDIR)/exporter/exporterhelper/exporterhelperprofiles \
-replace go.opentelemetry.io/collector/exporter/nopexporter=$(CURDIR)/exporter/nopexporter \
-replace go.opentelemetry.io/collector/exporter/otlpexporter=$(CURDIR)/exporter/otlpexporter \
-replace go.opentelemetry.io/collector/exporter/otlphttpexporter=$(CURDIR)/exporter/otlphttpexporter \
Expand Down Expand Up @@ -360,9 +362,11 @@ restore-contrib:
-dropreplace go.opentelemetry.io/collector/connector/connectorprofiles \
-dropreplace go.opentelemetry.io/collector/connector/forwardconnector \
-dropreplace go.opentelemetry.io/collector/consumer \
-dropreplace go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles \
-dropreplace go.opentelemetry.io/collector/consumer/consumerprofiles \
-dropreplace go.opentelemetry.io/collector/consumer/consumertest \
-dropreplace go.opentelemetry.io/collector/exporter \
-dropreplace go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles \
-dropreplace go.opentelemetry.io/collector/exporter/debugexporter \
-dropreplace go.opentelemetry.io/collector/exporter/nopexporter \
-dropreplace go.opentelemetry.io/collector/exporter/otlpexporter \
Expand Down
2 changes: 2 additions & 0 deletions cmd/builder/internal/builder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ var (
"/confmap/provider/httpsprovider",
"/confmap/provider/yamlprovider",
"/consumer",
"/consumer/consumererror/consumererrorprofiles",
"/consumer/consumerprofiles",
"/consumer/consumertest",
"/connector",
Expand All @@ -68,6 +69,7 @@ var (
"/exporter",
"/exporter/debugexporter",
"/exporter/exporterprofiles",
"/exporter/exporterhelper/exporterhelperprofiles",
"/exporter/nopexporter",
"/exporter/otlpexporter",
"/exporter/otlphttpexporter",
Expand Down
1 change: 1 addition & 0 deletions cmd/builder/test/core.builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ replaces:
- go.opentelemetry.io/collector/exporter => ${WORKSPACE_DIR}/exporter
- go.opentelemetry.io/collector/exporter/debugexporter => ${WORKSPACE_DIR}/exporter/debugexporter
- go.opentelemetry.io/collector/exporter/exporterprofiles => ${WORKSPACE_DIR}/exporter/exporterprofiles
- go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles => ${WORKSPACE_DIR}/exporter/exporterhelper/exporterhelperprofiles
- go.opentelemetry.io/collector/extension => ${WORKSPACE_DIR}/extension
- go.opentelemetry.io/collector/extension/auth => ${WORKSPACE_DIR}/extension/auth
- go.opentelemetry.io/collector/extension/experimental/storage => ${WORKSPACE_DIR}/extension/experimental/storage
Expand Down
2 changes: 2 additions & 0 deletions cmd/otelcorecol/builder-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ replaces:
- go.opentelemetry.io/collector/confmap/provider/yamlprovider => ../../confmap/provider/yamlprovider
- go.opentelemetry.io/collector/consumer => ../../consumer
- go.opentelemetry.io/collector/consumer/consumerprofiles => ../../consumer/consumerprofiles
- go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles => ../../consumer/consumererror/consumererrorprofiles
- go.opentelemetry.io/collector/consumer/consumertest => ../../consumer/consumertest
- go.opentelemetry.io/collector/connector => ../../connector
- go.opentelemetry.io/collector/connector/connectortest => ../../connector/connectortest
Expand All @@ -68,6 +69,7 @@ replaces:
- go.opentelemetry.io/collector/exporter => ../../exporter
- go.opentelemetry.io/collector/exporter/debugexporter => ../../exporter/debugexporter
- go.opentelemetry.io/collector/exporter/exporterprofiles => ../../exporter/exporterprofiles
- go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles => ../../exporter/exporterhelper/exporterhelperprofiles
- go.opentelemetry.io/collector/exporter/nopexporter => ../../exporter/nopexporter
- go.opentelemetry.io/collector/exporter/otlpexporter => ../../exporter/otlpexporter
- go.opentelemetry.io/collector/exporter/otlphttpexporter => ../../exporter/otlphttpexporter
Expand Down
6 changes: 6 additions & 0 deletions cmd/otelcorecol/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ require (
go.opentelemetry.io/collector/connector/connectorprofiles v0.111.0 // indirect
go.opentelemetry.io/collector/connector/connectortest v0.111.0 // indirect
go.opentelemetry.io/collector/consumer v0.111.0 // indirect
go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles v0.0.0-00010101000000-000000000000 // indirect
go.opentelemetry.io/collector/consumer/consumerprofiles v0.111.0 // indirect
go.opentelemetry.io/collector/consumer/consumertest v0.111.0 // indirect
go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles v0.0.0-00010101000000-000000000000 // indirect
go.opentelemetry.io/collector/exporter/exporterprofiles v0.111.0 // indirect
go.opentelemetry.io/collector/extension/auth v0.111.0 // indirect
go.opentelemetry.io/collector/extension/experimental/storage v0.111.0 // indirect
Expand Down Expand Up @@ -193,6 +195,8 @@ replace go.opentelemetry.io/collector/consumer => ../../consumer

replace go.opentelemetry.io/collector/consumer/consumerprofiles => ../../consumer/consumerprofiles

replace go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles => ../../consumer/consumererror/consumererrorprofiles

replace go.opentelemetry.io/collector/consumer/consumertest => ../../consumer/consumertest

replace go.opentelemetry.io/collector/connector => ../../connector
Expand All @@ -209,6 +213,8 @@ replace go.opentelemetry.io/collector/exporter/debugexporter => ../../exporter/d

replace go.opentelemetry.io/collector/exporter/exporterprofiles => ../../exporter/exporterprofiles

replace go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles => ../../exporter/exporterhelper/exporterhelperprofiles

replace go.opentelemetry.io/collector/exporter/nopexporter => ../../exporter/nopexporter

replace go.opentelemetry.io/collector/exporter/otlpexporter => ../../exporter/otlpexporter
Expand Down
4 changes: 3 additions & 1 deletion exporter/otlphttpexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
<!-- status autogenerated section -->
| Status | |
| ------------- |-----------|
| Stability | [beta]: logs |
| Stability | [development]: profiles |
| | [beta]: logs |
| | [stable]: traces, metrics |
| Distributions | [core], [contrib], [k8s] |
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector?query=is%3Aissue%20is%3Aopen%20label%3Aexporter%2Fotlphttp%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fotlphttp) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector?query=is%3Aissue%20is%3Aclosed%20label%3Aexporter%2Fotlphttp%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fotlphttp) |

[development]: https://github.com/open-telemetry/opentelemetry-collector#development
[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta
[stable]: https://github.com/open-telemetry/opentelemetry-collector#stable
[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol
Expand Down
37 changes: 33 additions & 4 deletions exporter/otlphttpexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ import (
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/exporter/exporterhelper"
"go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles"
"go.opentelemetry.io/collector/exporter/exporterprofiles"
"go.opentelemetry.io/collector/exporter/otlphttpexporter/internal/metadata"
)

// NewFactory creates a factory for OTLP exporter.
func NewFactory() exporter.Factory {
return exporter.NewFactory(
return exporterprofiles.NewFactory(
metadata.Type,
createDefaultConfig,
exporter.WithTraces(createTraces, metadata.TracesStability),
exporter.WithMetrics(createMetrics, metadata.MetricsStability),
exporter.WithLogs(createLogs, metadata.LogsStability),
exporterprofiles.WithTraces(createTraces, metadata.TracesStability),
exporterprofiles.WithMetrics(createMetrics, metadata.MetricsStability),
exporterprofiles.WithLogs(createLogs, metadata.LogsStability),
exporterprofiles.WithProfiles(createProfiles, metadata.ProfilesStability),
)
}

Expand Down Expand Up @@ -146,3 +149,29 @@ func createLogs(
exporterhelper.WithRetry(oCfg.RetryConfig),
exporterhelper.WithQueue(oCfg.QueueConfig))
}

func createProfiles(
ctx context.Context,
set exporter.Settings,
cfg component.Config,
) (exporterprofiles.Profiles, error) {
oce, err := newExporter(cfg, set)
if err != nil {
return nil, err
}
oCfg := cfg.(*Config)

oce.profilesURL, err = composeSignalURL(oCfg, "", "profiles", "v1development")
if err != nil {
return nil, err
}

return exporterhelperprofiles.NewProfilesExporter(ctx, set, cfg,
oce.pushProfiles,
exporterhelper.WithStart(oce.start),
exporterhelper.WithCapabilities(consumer.Capabilities{MutatesData: false}),
// explicitly disable since we rely on http.Client timeout logic.
exporterhelper.WithTimeout(exporterhelper.TimeoutConfig{Timeout: 0}),
exporterhelper.WithRetry(oCfg.RetryConfig),
exporterhelper.WithQueue(oCfg.QueueConfig))
}
12 changes: 12 additions & 0 deletions exporter/otlphttpexporter/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"go.opentelemetry.io/collector/config/confighttp"
"go.opentelemetry.io/collector/config/configopaque"
"go.opentelemetry.io/collector/config/configtls"
"go.opentelemetry.io/collector/exporter/exporterprofiles"
"go.opentelemetry.io/collector/exporter/exportertest"
"go.opentelemetry.io/collector/internal/testutil"
)
Expand Down Expand Up @@ -198,6 +199,17 @@ func TestCreateLogs(t *testing.T) {
require.NotNil(t, oexp)
}

func TestCreateProfiles(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = "http://" + testutil.GetAvailableLocalAddress(t)

set := exportertest.NewNopSettings()
oexp, err := factory.(exporterprofiles.Factory).CreateProfiles(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

func TestComposeSignalURL(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig().(*Config)
Expand Down
13 changes: 11 additions & 2 deletions exporter/otlphttpexporter/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ require (
go.opentelemetry.io/collector/confmap v1.17.0
go.opentelemetry.io/collector/consumer v0.111.0
go.opentelemetry.io/collector/exporter v0.111.0
go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles v0.0.0-00010101000000-000000000000
go.opentelemetry.io/collector/exporter/exporterprofiles v0.111.0
go.opentelemetry.io/collector/pdata v1.17.0
go.opentelemetry.io/collector/pdata/pprofile v0.111.0
go.uber.org/goleak v1.3.0
go.uber.org/zap v1.27.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd
Expand Down Expand Up @@ -49,14 +52,14 @@ require (
go.opentelemetry.io/collector/config/configauth v0.111.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.111.0 // indirect
go.opentelemetry.io/collector/config/internal v0.111.0 // indirect
go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles v0.0.0-00010101000000-000000000000 // indirect
go.opentelemetry.io/collector/consumer/consumerprofiles v0.111.0 // indirect
go.opentelemetry.io/collector/consumer/consumertest v0.111.0 // indirect
go.opentelemetry.io/collector/exporter/exporterprofiles v0.111.0 // indirect
go.opentelemetry.io/collector/extension v0.111.0 // indirect
go.opentelemetry.io/collector/extension/auth v0.111.0 // indirect
go.opentelemetry.io/collector/extension/experimental/storage v0.111.0 // indirect
go.opentelemetry.io/collector/pdata/pprofile v0.111.0 // indirect
go.opentelemetry.io/collector/pipeline v0.111.0 // indirect
go.opentelemetry.io/collector/pipeline/pipelineprofiles v0.0.0-00010101000000-000000000000 // indirect
go.opentelemetry.io/collector/receiver v0.111.0 // indirect
go.opentelemetry.io/collector/receiver/receiverprofiles v0.111.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
Expand Down Expand Up @@ -122,6 +125,12 @@ replace go.opentelemetry.io/collector/component/componentstatus => ../../compone

replace go.opentelemetry.io/collector/receiver/receiverprofiles => ../../receiver/receiverprofiles

replace go.opentelemetry.io/collector/pipeline/pipelineprofiles => ../../pipeline/pipelineprofiles

replace go.opentelemetry.io/collector/consumer/consumererror/consumererrorprofiles => ../../consumer/consumererror/consumererrorprofiles

replace go.opentelemetry.io/collector/exporter/exporterhelper/exporterhelperprofiles => ../exporterhelper/exporterhelperprofiles

replace go.opentelemetry.io/collector/exporter/exporterprofiles => ../exporterprofiles

replace go.opentelemetry.io/collector/pipeline => ../../pipeline
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion exporter/otlphttpexporter/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ status:
stability:
stable: [traces, metrics]
beta: [logs]
development: [profiles]
distributions: [core, contrib, k8s]

tests:
config:
endpoint: "https://1.2.3.4:1234"

68 changes: 61 additions & 7 deletions exporter/otlphttpexporter/otlp.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ import (
"go.opentelemetry.io/collector/pdata/plog/plogotlp"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp"
"go.opentelemetry.io/collector/pdata/pprofile"
"go.opentelemetry.io/collector/pdata/pprofile/pprofileotlp"
"go.opentelemetry.io/collector/pdata/ptrace"
"go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp"
)

type baseExporter struct {
// Input configuration.
config *Config
client *http.Client
tracesURL string
metricsURL string
logsURL string
logger *zap.Logger
settings component.TelemetrySettings
config *Config
client *http.Client
tracesURL string
metricsURL string
logsURL string
profilesURL string
logger *zap.Logger
settings component.TelemetrySettings
// Default user-agent header.
userAgent string
}
Expand Down Expand Up @@ -149,6 +152,27 @@ func (e *baseExporter) pushLogs(ctx context.Context, ld plog.Logs) error {
return e.export(ctx, e.logsURL, request, e.logsPartialSuccessHandler)
}

func (e *baseExporter) pushProfiles(ctx context.Context, td pprofile.Profiles) error {
tr := pprofileotlp.NewExportRequestFromProfiles(td)

var err error
var request []byte
switch e.config.Encoding {
case EncodingJSON:
request, err = tr.MarshalJSON()
case EncodingProto:
request, err = tr.MarshalProto()
default:
err = fmt.Errorf("invalid encoding: %s", e.config.Encoding)
}

if err != nil {
return consumererror.NewPermanent(err)
}

return e.export(ctx, e.profilesURL, request, e.profilesPartialSuccessHandler)
}

func (e *baseExporter) export(ctx context.Context, url string, request []byte, partialSuccessHandler partialSuccessHandler) error {
e.logger.Debug("Preparing to make HTTP request", zap.String("url", url))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(request))
Expand Down Expand Up @@ -392,3 +416,33 @@ func (e *baseExporter) logsPartialSuccessHandler(protoBytes []byte, contentType
}
return nil
}

func (e *baseExporter) profilesPartialSuccessHandler(protoBytes []byte, contentType string) error {
if protoBytes == nil {
return nil
}
exportResponse := pprofileotlp.NewExportResponse()
switch contentType {
case protobufContentType:
err := exportResponse.UnmarshalProto(protoBytes)
if err != nil {
return fmt.Errorf("error parsing protobuf response: %w", err)
}
case jsonContentType:
err := exportResponse.UnmarshalJSON(protoBytes)
if err != nil {
return fmt.Errorf("error parsing json response: %w", err)
}
default:
return nil
}

partialSuccess := exportResponse.PartialSuccess()
if !(partialSuccess.ErrorMessage() == "" && partialSuccess.RejectedProfiles() == 0) {
e.logger.Warn("Partial success response",
zap.String("message", exportResponse.PartialSuccess().ErrorMessage()),
zap.Int64("dropped_samples", exportResponse.PartialSuccess().RejectedProfiles()),
)
}
return nil
}
Loading

0 comments on commit f330cfb

Please sign in to comment.