Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pyroscope client extension #94

Merged
merged 2 commits into from
Aug 23, 2024
Merged
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
2 changes: 2 additions & 0 deletions cmd/otel-collector/components.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"github.com/metrico/otel-collector/extension/pyroscope"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/countconnector"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector"
Expand Down Expand Up @@ -204,6 +205,7 @@ func components() (otelcol.Factories, error) {
jsonlogencodingextension.NewFactory(),
textencodingextension.NewFactory(),
zipkinencodingextension.NewFactory(),
pyroscope.NewFactory(),
}
for _, ext := range factories.Extensions {
extensions = append(extensions, ext)
Expand Down
42 changes: 42 additions & 0 deletions extension/pyroscope/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Pyroscope client

| Status | |
|---------------------------|--------|
| Stability | [beta] |


The Extension provides the functionality to export the opentelementry collector profiles into a pyroscope compatible
server.


The following settings can be configured:

- application_name (default = "opentelemetry-collector"): The name of the application as it will appear in Pyroscope.
- tags (default = empty map): A map of key-value pairs for additional tags to be associated with the profiles.
- server_address (default = "http://localhost:8062"): The URL of the Pyroscope server to which the profiles will be sent.
- basic_auth (default = empty): Basic authentication configuration for connecting to the Pyroscope server.
- username: The username for basic authentication.
- password: The password for basic authentication.
- profile_types (default = ["cpu", "alloc_objects", "alloc_space", "inuse_objects", "inuse_space"]):
An array of profile types to collect and send to Pyroscope.
- tenant_id (default = ""): The tenant ID to use when sending profiles to Pyroscope, for multi-tenancy support.

Example:
```yaml
extensions:
pyroscope:
application_name: "my-collector"
tags:
environment: "production"
region: "us-west-2"
server_address: "http://localhost:8062"
basic_auth:
username: "user"
password: "secret"
profile_types:
- "cpu"
- "alloc_objects"
- "inuse_space"
service:
extensions: [pyroscope]
```
27 changes: 27 additions & 0 deletions extension/pyroscope/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pyroscope

import "go.opentelemetry.io/collector/component"

type Config struct {
ApplicationName string `json:"application_name"`
Tags map[string]string `json:"tags"`
ServerAddress string `json:"server_address"`
BasicAuth BasicAuth `json:"basic_auth"`
ProfileTypes []string `json:"profile_types"`
TenantID string `json:"tenant_id"`
}

type BasicAuth struct {
Username string `json:"username"`
Password string `json:"password"`
}

func defaultConfig() component.Config {
return &Config{
ApplicationName: "opentelemetry-collector",
ServerAddress: "http://localhost:8062",
Tags: map[string]string{},
BasicAuth: BasicAuth{},
ProfileTypes: []string{"cpu", "alloc_objects", "alloc_space", "inuse_objects", "inuse_space"},
}
}
74 changes: 74 additions & 0 deletions extension/pyroscope/extension.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package pyroscope

import (
"context"

"github.com/google/uuid"
"github.com/grafana/pyroscope-go"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/extension"
)

var pyroscopeType = component.MustNewType("pyroscope")

// NewNopCreateSettings returns a new nop settings for extension.Factory Create* functions.
func NewPyroscopeCreateSettings() extension.CreateSettings {
return extension.CreateSettings{
ID: component.NewIDWithName(pyroscopeType, uuid.NewString()),
TelemetrySettings: componenttest.NewNopTelemetrySettings(),
BuildInfo: component.NewDefaultBuildInfo(),
}
}

// NewNopFactory returns an extension.Factory that constructs nop extensions.
func NewFactory() extension.Factory {
return extension.NewFactory(
pyroscopeType,
defaultConfig,
func(ctx context.Context, settings extension.CreateSettings, config component.Config) (extension.Extension, error) {
return &PyroscopeExtension{
config: config.(*Config),
}, nil
},
component.StabilityLevelStable)
}

type PyroscopeExtension struct {
config *Config
settings extension.CreateSettings
ctx context.Context
profiler *pyroscope.Profiler
}

func (p PyroscopeExtension) Start(ctx context.Context, host component.Host) error {
cfg := pyroscope.Config{
ApplicationName: p.config.ApplicationName,

// replace this with the address of pyroscope server
ServerAddress: p.config.ServerAddress,

// you can disable logging by setting this to nil
Logger: pyroscope.StandardLogger,

// Optional HTTP Basic authentication (Grafana Cloud)
BasicAuthUser: p.config.BasicAuth.Username,
BasicAuthPassword: p.config.BasicAuth.Password,
Tags: p.config.Tags,
TenantID: p.config.TenantID,
ProfileTypes: nil,
}
for _, profileType := range p.config.ProfileTypes {
cfg.ProfileTypes = append(cfg.ProfileTypes, pyroscope.ProfileType(profileType))
}
var err error
p.profiler, err = pyroscope.Start(cfg)
return err
}

func (p PyroscopeExtension) Shutdown(ctx context.Context) error {
return p.profiler.Stop()
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ require (
github.com/go-faster/city v1.0.1
github.com/go-logfmt/logfmt v0.6.0
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/grafana/jfr-parser v0.8.0
github.com/grafana/pyroscope-go v1.1.2
github.com/grafana/pyroscope/api v0.4.0
github.com/open-telemetry/opentelemetry-collector-contrib/connector/countconnector v0.98.0
github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector v0.98.0
Expand Down Expand Up @@ -369,13 +371,13 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/gophercloud/gophercloud v1.8.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/gosnmp/gosnmp v1.37.0 // indirect
github.com/grafana/loki/pkg/push v0.0.0-20231127162423-bd505f8e2d37 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
github.com/grobie/gomemcache v0.0.0-20230213081705-239240bbc445 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
Expand Down
5 changes: 4 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,10 @@ github.com/grafana/jfr-parser v0.8.0 h1:/uo2wZNXrxw7tKLFwP2omJ3EQGMkD9wzhPsRogVo
github.com/grafana/jfr-parser v0.8.0/go.mod h1:M5u1ux34Qo47ZBWksbMYVk40s7dvU3WMVYpxweEu4R0=
github.com/grafana/loki/pkg/push v0.0.0-20231127162423-bd505f8e2d37 h1:w59bmBeLOk4enGtyX4kTBNY3FCw/nwDTYUqcjC4vKhg=
github.com/grafana/loki/pkg/push v0.0.0-20231127162423-bd505f8e2d37/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0=
github.com/grafana/pyroscope v1.5.0/go.mod h1:rg53VGcqOf3FawAcAUpkcNNF7+gV1VZFbZY9Gfxry+c=
github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8=
github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
github.com/grafana/pyroscope/api v0.4.0 h1:J86DxoNeLOvtJhB1Cn65JMZkXe682D+RqeoIUiYc/eo=
github.com/grafana/pyroscope/api v0.4.0/go.mod h1:MFnZNeUM4RDsDOnbgKW3GWoLSBpLzMMT9nkvhHHo81o=
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww=
Expand Down
Loading