Skip to content

Commit

Permalink
Add json format support for log export via faro receiver
Browse files Browse the repository at this point in the history
Update docs
  • Loading branch information
ravishankar15 committed Dec 12, 2024
1 parent 566527d commit 23c07db
Show file tree
Hide file tree
Showing 10 changed files with 501 additions and 120 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Main (unreleased)
- Change processlist query to support ONLY_FULL_GROUP_BY sql_mode
- Add perf_schema quantile columns to collector

- Add json format support for log export via faro receiver (@ravishankar15)
- Add three new stdlib functions to_base64, from_URLbase64 and to_URLbase64 (@ravishankar15)

- Use a forked `github.com/goccy/go-json` module which reduces the memory consumption of an Alloy instance by 20MB.
Expand Down Expand Up @@ -101,7 +102,7 @@ v1.5.1

- Fixed a crash when updating the configuration of `remote.http`. (@kinolaev)

- Fixed an issue in the `otelcol.processor.attribute` component where the actions `delete` and `hash` could not be used with the `pattern` argument. (@wildum)
- Fixed an issue in the `otelcol.processor.attribute` component where the actions `delete` and `hash` could not be used with the `pattern` argument. (@wildum)

- Fixed an issue in the `prometheus.exporter.postgres` component that would leak goroutines when the target was not reachable (@dehaansa)

Expand Down Expand Up @@ -301,7 +302,7 @@ v1.4.0

- Add the label `alloy_cluster` in the metric `alloy_config_hash` when the flag `cluster.name` is set to help differentiate between
configs from the same alloy cluster or different alloy clusters. (@wildum)

- Add support for discovering the cgroup path(s) of a process in `process.discovery`. (@mahendrapaipuri)

### Bugfixes
Expand Down
8 changes: 8 additions & 0 deletions docs/sources/reference/components/faro/faro.receiver.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ The following arguments are supported:
Name | Type | Description | Default | Required
-------------------|---------------|----------------------------------------------|---------|---------
`extra_log_labels` | `map(string)` | Extra labels to attach to emitted log lines. | `{}` | no
`log_format` | `string` | Export format for the logs | `logfmt`| no

### Log format

The following strings are recognized as valid log line formats:

* `"logfmt"`: Export logs as [logfmt][] lines.
* `"json"`: Export logs as JSON objects.

## Blocks

Expand Down
34 changes: 34 additions & 0 deletions internal/component/faro/receiver/arguments.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package receiver

import (
"encoding"
"fmt"
"time"

"github.com/alecthomas/units"
Expand All @@ -13,6 +15,7 @@ import (
// Arguments configures the app_agent_receiver component.
type Arguments struct {
LogLabels map[string]string `alloy:"extra_log_labels,attr,optional"`
LogFormat LogFormat `alloy:"log_format,attr,optional"`

Server ServerArguments `alloy:"server,block,optional"`
SourceMaps SourceMapsArguments `alloy:"sourcemaps,block,optional"`
Expand All @@ -23,6 +26,7 @@ var _ syntax.Defaulter = (*Arguments)(nil)

// SetToDefault applies default settings.
func (args *Arguments) SetToDefault() {
args.LogFormat = FormatDefault
args.Server.SetToDefault()
args.SourceMaps.SetToDefault()
}
Expand Down Expand Up @@ -93,3 +97,33 @@ type OutputArguments struct {
Logs []loki.LogsReceiver `alloy:"logs,attr,optional"`
Traces []otelcol.Consumer `alloy:"traces,attr,optional"`
}

type LogFormat string

const (
FormatLogfmt LogFormat = "logfmt"
FormatJSON LogFormat = "json"

FormatDefault = FormatLogfmt
)

var (
_ encoding.TextMarshaler = FormatDefault
_ encoding.TextUnmarshaler = (*LogFormat)(nil)
)

func (ll LogFormat) MarshalText() (text []byte, err error) {
return []byte(ll), nil
}

func (ll *LogFormat) UnmarshalText(text []byte) error {
switch LogFormat(text) {
case "":
*ll = FormatDefault
case FormatLogfmt, FormatJSON:
*ll = LogFormat(text)
default:
return fmt.Errorf("unrecognized log format %q", string(text))
}
return nil
}
19 changes: 17 additions & 2 deletions internal/component/faro/receiver/exporters.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package receiver

import (
"context"
"encoding/json"
"errors"
"fmt"
"sync"
Expand Down Expand Up @@ -79,6 +80,7 @@ func (exp *metricsExporter) Export(ctx context.Context, p payload.Payload) error
type logsExporter struct {
log log.Logger
sourceMaps sourceMapsStore
format LogFormat

receiversMut sync.RWMutex
receivers []loki.LogsReceiver
Expand All @@ -89,10 +91,11 @@ type logsExporter struct {

var _ exporter = (*logsExporter)(nil)

func newLogsExporter(log log.Logger, sourceMaps sourceMapsStore) *logsExporter {
func newLogsExporter(log log.Logger, sourceMaps sourceMapsStore, format LogFormat) *logsExporter {
return &logsExporter{
log: log,
sourceMaps: sourceMaps,
format: format,
}
}

Expand Down Expand Up @@ -153,7 +156,19 @@ func (exp *logsExporter) sendKeyValsToLogsPipeline(ctx context.Context, kv *payl
)
exp.receiversMut.RUnlock()

line, err := logfmt.MarshalKeyvals(payload.KeyValToInterfaceSlice(kv)...)
var (
line []byte
err error
)
switch exp.format {
case FormatLogfmt:
line, err = logfmt.MarshalKeyvals(payload.KeyValToInterfaceSlice(kv)...)
case FormatJSON:
line, err = json.Marshal(payload.KeyValToInterfaceMap(kv))
default:
line, err = logfmt.MarshalKeyvals(payload.KeyValToInterfaceSlice(kv)...)
}

if err != nil {
level.Error(exp.log).Log("msg", "failed to logfmt a frontend log event", "err", err)
return err
Expand Down
Loading

0 comments on commit 23c07db

Please sign in to comment.