Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .chloggen/otlp-grpc-alias.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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. receiver/otlp)
component: exporter/otlp

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add `otlp_grpc` alias for `otlp` exporter to make the protocol explicit and distinguish it from `otlphttp`.

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

# (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: |
The OTLP gRPC exporter can now be configured using either `otlp` or `otlp_grpc` as the exporter type.
Both are equivalent and refer to the same OTLP gRPC exporter. The `otlp_grpc` alias makes the protocol
explicit and helps distinguish it from the `otlphttp` exporter.

# 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: [user]

3 changes: 3 additions & 0 deletions cmd/otelcorecol/components.go

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

7 changes: 7 additions & 0 deletions exporter/otlpexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Export data via gRPC using [OTLP](
https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md)
format. By default, this exporter requires TLS and offers queued retry capabilities.

This exporter can be configured using either `otlp` or `otlp_grpc` as the exporter type. Both are equivalent and refer to the same OTLP gRPC exporter. The `otlp_grpc` alias makes the protocol explicit and helps distinguish it from the `otlphttp` exporter.

## Getting Started

The following settings are required:
Expand All @@ -46,6 +48,11 @@ exporters:
endpoint: otelcol2:4317
tls:
insecure: true
# Alternative: using the otlp_grpc alias
otlp_grpc:
endpoint: otelcol2:4317
tls:
insecure: true
```

By default, `gzip` compression is enabled. See [compression comparison](../../config/configgrpc/README.md#compression-comparison) for details benchmark information. To disable, configure as follows:
Expand Down
35 changes: 35 additions & 0 deletions exporter/otlpexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,41 @@ func NewFactory() exporter.Factory {
)
}

// NewFactoryWithAlias creates a factory for OTLP exporter with the otlp_grpc alias type and wraps the original factory.
func NewFactoryWithAlias() exporter.Factory {
originalFactory := NewFactory().(xexporter.Factory)
aliasType := component.MustNewType("otlp_grpc")

// Helper function to adjust the ID from otlp_grpc to otlp while preserving the name
adjustID := func(id component.ID) component.ID {
if id.Name() == "" {
return component.NewID(metadata.Type)
}
return component.NewIDWithName(metadata.Type, id.Name())
}

return xexporter.NewFactory(
aliasType,
createDefaultConfig,
xexporter.WithTraces(func(ctx context.Context, set exporter.Settings, cfg component.Config) (exporter.Traces, error) {
set.ID = adjustID(set.ID) // transform otlp_grpc to otlp
return originalFactory.CreateTraces(ctx, set, cfg)
}, metadata.TracesStability),
xexporter.WithMetrics(func(ctx context.Context, set exporter.Settings, cfg component.Config) (exporter.Metrics, error) {
set.ID = adjustID(set.ID)
return originalFactory.CreateMetrics(ctx, set, cfg)
}, metadata.MetricsStability),
xexporter.WithLogs(func(ctx context.Context, set exporter.Settings, cfg component.Config) (exporter.Logs, error) {
set.ID = adjustID(set.ID)
return originalFactory.CreateLogs(ctx, set, cfg)
}, metadata.LogsStability),
xexporter.WithProfiles(func(ctx context.Context, set exporter.Settings, cfg component.Config) (xexporter.Profiles, error) {
set.ID = adjustID(set.ID)
return originalFactory.CreateProfiles(ctx, set, cfg)
}, metadata.ProfilesStability),
)
}

func createDefaultConfig() component.Config {
clientCfg := configgrpc.NewDefaultClientConfig()
// Default to gzip compression
Expand Down
105 changes: 105 additions & 0 deletions exporter/otlpexporter/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configcompression"
"go.opentelemetry.io/collector/config/configgrpc"
Expand Down Expand Up @@ -339,3 +340,107 @@ func TestCreateProfiles(t *testing.T) {
})
}
}

func TestNewFactoryWithAlias(t *testing.T) {
factory := NewFactoryWithAlias()
assert.NotNil(t, factory)

// Verify the factory type is otlp_grpc
assert.Equal(t, component.MustNewType("otlp_grpc"), factory.Type())

// Verify it can create default config
cfg := factory.CreateDefaultConfig()
assert.NotNil(t, cfg, "failed to create default config")
require.NoError(t, componenttest.CheckConfigStruct(cfg))

// Verify stability levels match the original factory
originalFactory := NewFactory()
assert.Equal(t, originalFactory.TracesStability(), factory.TracesStability())
assert.Equal(t, originalFactory.MetricsStability(), factory.MetricsStability())
assert.Equal(t, originalFactory.LogsStability(), factory.LogsStability())
}

func TestAliasFactoryCreateMetrics(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Use the alias type for settings
set := exportertest.NewNopSettings(factory.Type())
oexp, err := factory.CreateMetrics(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

func TestAliasFactoryCreateTraces(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Use the alias type for settings
set := exportertest.NewNopSettings(factory.Type())
oexp, err := factory.CreateTraces(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

func TestAliasFactoryCreateLogs(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Use the alias type for settings
set := exportertest.NewNopSettings(factory.Type())
oexp, err := factory.CreateLogs(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

func TestAliasFactoryCreateProfiles(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Use the alias type for settings
set := exportertest.NewNopSettings(factory.Type())
xFactory, ok := factory.(xexporter.Factory)
require.True(t, ok)
oexp, err := xFactory.CreateProfiles(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

func TestAliasFactoryWithNamedComponent(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Test with a named component (e.g., otlp_grpc/myname)
aliasType := component.MustNewType("otlp_grpc")
componentID := component.NewIDWithName(aliasType, "myname")
set := exportertest.NewNopSettings(componentID.Type())
set.ID = componentID

oexp, err := factory.CreateMetrics(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}

// TestAliasFactoryUnnamedID covers the branch: return component.NewID(metadata.Type)
// when id.Name() == ""
func TestAliasFactoryUnnamedID(t *testing.T) {
factory := NewFactoryWithAlias()
cfg := factory.CreateDefaultConfig().(*Config)
cfg.ClientConfig.Endpoint = testutil.GetAvailableLocalAddress(t)

// Create an unnamed component ID (no name) to trigger: return component.NewID(metadata.Type)
aliasType := component.MustNewType("otlp_grpc")
unnamedID := component.NewID(aliasType) // ID without a name
set := exportertest.NewNopSettings(aliasType)
set.ID = unnamedID // Override to use unnamed ID

// Test with traces to cover the adjustID branch
oexp, err := factory.CreateTraces(context.Background(), set, cfg)
require.NoError(t, err)
require.NotNil(t, oexp)
}