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

feat: add ability to filter and export markers #27862

Merged
merged 46 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e7737de
feat: add ability to filter and export markers
fchikwekwe Oct 18, 2023
87ee53c
test: add export tests and export functionality
fchikwekwe Oct 19, 2023
bca314b
test: test log exporter
fchikwekwe Oct 24, 2023
2adc71e
feat: add queue and retry settings
fchikwekwe Oct 26, 2023
3e8ae0e
test: remove log conditions from response testing
fchikwekwe Nov 1, 2023
2d7a06b
test: add bad path log tests
fchikwekwe Nov 2, 2023
78ab791
chore: merge in main'
fchikwekwe Nov 2, 2023
00bcf5d
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 2, 2023
aceca83
Merge remote-tracking branch 'contrib/main' into feat/hny-marker-expo…
fchikwekwe Nov 2, 2023
168be30
Merge branch 'feat/hny-marker-exporter' of https://github.com/fchikwe…
fchikwekwe Nov 2, 2023
905c018
doc: update README with new config
fchikwekwe Nov 2, 2023
aee1f38
chore: restore deps from main
fchikwekwe Nov 2, 2023
b018f82
chore: comply with lint
fchikwekwe Nov 2, 2023
35543ee
chore: manually update out of sync deps
fchikwekwe Nov 2, 2023
07aa44d
chore: regen dependabot files
fchikwekwe Nov 2, 2023
dcac5c5
fix: update log tests to properly access config vals
fchikwekwe Nov 2, 2023
c79ee46
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 2, 2023
c4baad9
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 13, 2023
31e50f3
feat: add honeycombexpoter to otelcontribcol
fchikwekwe Nov 13, 2023
25f6c29
Merge branch 'feat/hny-marker-exporter' of https://github.com/fchikwe…
fchikwekwe Nov 13, 2023
4027d8b
feat: add honeycombexpoter to otelcontribcol
fchikwekwe Nov 13, 2023
92ba5c1
fix: remove test files
fchikwekwe Nov 14, 2023
f8f3d26
fix: run go mod tidy
fchikwekwe Nov 14, 2023
1394bca
fix: update more deps
fchikwekwe Nov 14, 2023
a559255
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 14, 2023
9ca87b9
fix: update deps with required versions
fchikwekwe Nov 14, 2023
f387225
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 14, 2023
c2f5cae
fix: update config internal
fchikwekwe Nov 14, 2023
dccbdea
fix: run make gotidy
fchikwekwe Nov 14, 2023
f7df24d
fix: add api key to header
fchikwekwe Nov 14, 2023
f37b593
test: add headers to log tests
fchikwekwe Nov 14, 2023
02839ca
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 14, 2023
4fdd457
fix: sort imports
fchikwekwe Nov 14, 2023
da47830
Merge branch 'feat/hny-marker-exporter' of https://github.com/fchikwe…
fchikwekwe Nov 14, 2023
3c63558
fix: use comparable strings in lgo test
fchikwekwe Nov 14, 2023
1cdf013
fix: remove whitespace
fchikwekwe Nov 14, 2023
2c336c5
Merge branch 'main' into feat/hny-marker-exporter
fchikwekwe Nov 14, 2023
0d1a09a
doc: added better descriptions to README
fchikwekwe Nov 14, 2023
9072850
Update exporter/honeycombmarkerexporter/README.md
TylerHelmuth Nov 14, 2023
c0f500b
Merge branch 'main' into feat/hny-marker-exporter
TylerHelmuth Nov 15, 2023
d540f49
Apply suggestions from code review
TylerHelmuth Nov 15, 2023
8dabee7
Apply suggestions from code review
TylerHelmuth Nov 15, 2023
1c99e46
Merge branch 'main' into feat/hny-marker-exporter
TylerHelmuth Nov 15, 2023
a8258cc
Update cmd/otelcontribcol/builder-config.yaml
TylerHelmuth Nov 15, 2023
27cc3ad
Merge branch 'main' into feat/hny-marker-exporter
TylerHelmuth Nov 15, 2023
af666ee
Merge branch 'main' into feat/hny-marker-exporter
TylerHelmuth Nov 16, 2023
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
11 changes: 1 addition & 10 deletions exporter/honeycombmarkerexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ The following configuration options are supported:
* `api_key` (Required): This is the API key (also called Write Key) for your Honeycomb account.
* `api_url` (Required): You can set the hostname to send marker data to.
* `markers` (Required): This specifies the exact configuration to create an event marker.
* `type`: Specifies the marker type. Markers with the same type will appear in the same color in Honeycomb. MarkerType or MarkerColor should be set.
* `color`: Specifies the marker color. Will only be used if MarkerType is not set.
* `type`: Specifies the marker type. Markers with the same type will appear in the same color in Honeycomb.
* `messagefield`: This is the attribute that will be used as the message. If necessary the value will be converted to a string.
* `urlfield`: This is the attribute that will be used as the url. If necessary the value will be converted to a string.
* `rules`: This is a list of OTTL rules that determine when to create an event marker.
Expand All @@ -31,12 +30,4 @@ exporters:
- IsMatch(attributes["test"], ".*")
- logconditions:
- body == "test"
- color: "green",
messagefield: "another test message",
urlfield: "https://api.testhost.io",
rules:
- resourceconditions:
- IsMatch(attributes["test"], ".*")
- logconditions:
- body == "test"
```
22 changes: 8 additions & 14 deletions exporter/honeycombmarkerexporter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package honeycombmarkerexporter // import "github.com/open-telemetry/opentelemet

import (
"fmt"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter/expr"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/ottllog"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configopaque"
Expand All @@ -27,12 +29,9 @@ type Config struct {
}

type Marker struct {
// Type defines the type of Marker. Markers with the same type appear in Honeycomb with the same color
// Type defines the type of Marker.
Type string `mapstructure:"type"`

// Color is the color of the Marker. Will only be used if the Type does not already exist.
Color string `mapstructure:"color"`

// MessageField is the attribute that will be used as the message.
// If necessary the value will be converted to a string.
MessageField string `mapstructure:"message_field"`
Expand All @@ -46,11 +45,11 @@ type Marker struct {
}

type Rules struct {
// ResourceConditions is the list of ottlresource conditions that determine a match
ResourceConditions []string `mapstructure:"resource_conditions"`

// LogConditions is the list of ottllog conditions that determine a match
LogConditions []string `mapstructure:"log_conditions"`

//
logBoolExpr expr.BoolExpr[ottllog.TransformContext]
}

var defaultCfg = createDefaultConfig().(*Config)
TylerHelmuth marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -66,16 +65,11 @@ func (cfg *Config) Validate() error {

if len(cfg.Markers) != 0 {
for _, m := range cfg.Markers {
if len(m.Rules.ResourceConditions) == 0 && len(m.Rules.LogConditions) == 0 {
if len(m.Rules.LogConditions) == 0 {
return fmt.Errorf("no rules supplied for Marker %v", m)
}

_, err := filterottl.NewBoolExprForResource(m.Rules.ResourceConditions, filterottl.StandardResourceFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
if err != nil {
return err
}

_, err = filterottl.NewBoolExprForLog(m.Rules.LogConditions, filterottl.StandardLogFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
_, err := filterottl.NewBoolExprForLog(m.Rules.LogConditions, filterottl.StandardLogFuncs(), ottl.PropagateError, component.TelemetrySettings{Logger: zap.NewNop()})
if err != nil {
return err
}
Expand Down
25 changes: 0 additions & 25 deletions exporter/honeycombmarkerexporter/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,6 @@ func TestLoadConfig(t *testing.T) {
MessageField: "test message",
URLField: "https://api.testhost.io",
Rules: Rules{
ResourceConditions: []string{
`IsMatch(attributes["test"], ".*")`,
},
LogConditions: []string{
`body == "test"`,
},
},
},
},
},
},
{
id: component.NewIDWithName("honeycomb", "color_no_type"),
expected: &Config{
APIKey: "test-apikey",
APIURL: "https://api.testhost.io",
Markers: []Marker{
{
Color: "green",
MessageField: "test message",
URLField: "https://api.testhost.io",
Rules: Rules{
ResourceConditions: []string{
`IsMatch(attributes["test"], ".*")`,
},
LogConditions: []string{
`body == "test"`,
},
Expand Down
8 changes: 5 additions & 3 deletions exporter/honeycombmarkerexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package honeycombmarkerexporter // import "github.com/open-telemetry/opentelemet

import (
"context"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/exporter/exporterhelper"
Expand Down Expand Up @@ -36,12 +35,15 @@ func createLogsExporter(
) (exporter.Logs, error) {
cf := cfg.(*Config)

exporter := newLogsExporter(set.Logger, cf)
logsExp, err := newHoneycombLogsExporter(set.TelemetrySettings, cf)
if err != nil {
return nil, err
}

return exporterhelper.NewLogsExporter(
ctx,
set,
cfg,
exporter.exportLogs,
logsExp.exportMarkers,
TylerHelmuth marked this conversation as resolved.
Show resolved Hide resolved
)
}
99 changes: 95 additions & 4 deletions exporter/honeycombmarkerexporter/logs_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,116 @@
package honeycombmarkerexporter // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/honeycombmarkerexporter"

import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter/filterottl"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/ottllog"
"go.opentelemetry.io/collector/component"
"net/http"
"strings"

"go.opentelemetry.io/collector/pdata/plog"

"go.uber.org/zap"
)

type honeycombLogsExporter struct {
logger *zap.Logger
markers []Marker
client *http.Client
fchikwekwe marked this conversation as resolved.
Show resolved Hide resolved
APIURL string
}

func newLogsExporter(logger *zap.Logger, config *Config) *honeycombLogsExporter {
func newHoneycombLogsExporter(set component.TelemetrySettings, config *Config) (*honeycombLogsExporter, error) {
if config == nil {
return nil, fmt.Errorf("unable to create honeycombLogsExporter without config")
}

for _, m := range config.Markers {
matchLogConditions, err := filterottl.NewBoolExprForLog(m.Rules.LogConditions, filterottl.StandardLogFuncs(), ottl.PropagateError, set)
if err != nil {
return nil, fmt.Errorf("failed to parse log conditions: %w", err)
}

m.Rules.logBoolExpr = matchLogConditions
}
logsExp := &honeycombLogsExporter{
logger: logger,
logger: set.Logger,
markers: config.Markers,
APIURL: config.APIURL,
}
return logsExp
return logsExp, nil
}

func (e *honeycombLogsExporter) exportLogs(_ context.Context, _ plog.Logs) error {
func (e *honeycombLogsExporter) exportMarkers(ctx context.Context, ld plog.Logs) error {
for i := 0; i < ld.ResourceLogs().Len(); i++ {
rlogs := ld.ResourceLogs().At(i)
for j := 0; j < rlogs.ScopeLogs().Len(); j++ {
slogs := rlogs.ScopeLogs().At(j)
logs := slogs.LogRecords()
for k := 0; k < logs.Len(); k++ {
logRecord := logs.At(k)
tCtx := ottllog.NewTransformContext(logRecord, slogs.Scope(), rlogs.Resource())
for _, m := range e.markers {
match, err := m.Rules.logBoolExpr.Eval(ctx, tCtx)
if err != nil {
return err
}
if match {
err := e.sendMarker(ctx, m, logRecord)
if err != nil {
return err
}
}
}

}
}
}
return nil
}

func (e *honeycombLogsExporter) sendMarker(ctx context.Context, marker Marker, logRecord plog.LogRecord) error {
requestMap := map[string]string{
"type": marker.Type,
}

messageField, found := logRecord.Attributes().Get(marker.MessageField)
if found {
requestMap["messageField"] = messageField.AsString()
}

URLField, found := logRecord.Attributes().Get(marker.URLField)
if found {
requestMap["URLField"] = URLField.AsString()
}

request, err := json.Marshal(requestMap)

url := strings.TrimSuffix(e.APIURL, "/") + "/bundle"
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(request))
if err != nil {
return err
}

req.Header.Set("Content-Type", "application/json")

resp, err := e.client.Do(req)
if err != nil {
return fmt.Errorf("failed to send a request: %w", err)
}

defer resp.Body.Close()

if err != nil {
return err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("failed with %s and message: %s", resp.Status, resp.Body)
}

return nil
}
45 changes: 45 additions & 0 deletions exporter/honeycombmarkerexporter/logs_exporter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package honeycombmarkerexporter

import (
"context"
"go.opentelemetry.io/collector/pdata/plog"
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/exporter/exportertest"
"net/http"
"net/http/httptest"
)

func TestExportMarkers(t *testing.T) {
markerServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusAccepted)
}))
defer markerServer.Close()

cfg := Config{
APIKey: "test-apikey",
APIURL: "https://api.testhost.io",
Markers: []Marker{
{
Type: "test-type",
MessageField: "test message",
URLField: "https://api.testhost.io",
Rules: Rules{
LogConditions: []string{
`body == "test"`,
},
},
},
},
}
noOpSettings := exportertest.NewNopCreateSettings()
markerExporter, err := newHoneycombLogsExporter(noOpSettings.TelemetrySettings, &cfg)
assert.NoError(t, err)

ctx := context.Background()

logs := plog.NewLogs()
err = markerExporter.exportMarkers(ctx, logs)
assert.NoError(t, err)
}
15 changes: 1 addition & 14 deletions exporter/honeycombmarkerexporter/testdata/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,6 @@ honeycomb:
log_conditions:
- body == "test"

honeycomb/color_no_type:
api_key: "test-apikey"
api_url: "https://api.testhost.io"
markers:
- color: "green"
message_field: "test message"
url_field: "https://api.testhost.io"
rules:
resource_conditions:
- IsMatch(attributes["test"], ".*")
log_conditions:
- body == "test"

honeycomb/bad_syntax_log:
api_key: "test-apikey"
api_url: "https://api.testhost.io"
Expand All @@ -40,7 +27,7 @@ honeycomb/no_conditions:
api_key: "test-apikey"
api_url: "https://api.testhost.io"
markers:
- color: "green"
- type: "test-apikey"
message_field: "test message"
url_field: "https://api.testhost.io"
rules:
Expand Down