-
Notifications
You must be signed in to change notification settings - Fork 0
/
fromlogfmt.go
84 lines (78 loc) · 2.23 KB
/
fromlogfmt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package main
import (
"context"
"fmt"
"io"
"github.com/ainvaltin/nu-plugin"
"github.com/oderwat/nu_plugin_logfmt/logfmt"
)
func fromLogFmt() *nu.Command {
return &nu.Command{
Signature: nu.PluginSignature{
Name: "from logfmt",
Category: "Formats",
SearchTerms: []string{"logfmt", "slog", "logging"},
InputOutputTypes: [][]string{{"String", "Any"}},
Usage: `Convert from 'logfmt' format to Nushell Value.`,
AllowMissingExamples: true,
Named: []nu.Flag{
{Long: "typed", Short: "t", Desc: "Try to detect simple types in the input"},
},
},
Examples: nu.Examples{
{
Description: `Convert a logfmt string to a Nu record`,
Example: `'msg="Test message" level=info esc="» Say \"Hello\"' | from logfmt`,
Result: &nu.Value{Value: nu.Record{
"level": nu.Value{Value: "info"},
"msg": nu.Value{Value: "Test message"},
"esc": nu.Value{Value: "» Say \"Hello\""},
}},
},
},
OnRun: fromLogFmtHandler,
}
}
func parseTypes(flags nu.NamedParams) bool {
_, ok := flags["typed"]
return ok
}
func fromLogFmtHandler(ctx context.Context, call *nu.ExecCommand) error {
typed := parseTypes(call.Named)
switch in := call.Input.(type) {
case nil:
return nil
case nu.Value:
var buf []byte
switch data := in.Value.(type) {
case []byte:
buf = data
case string:
buf = []byte(data)
default:
return fmt.Errorf("unsupported input value type %T", data)
}
fields := logfmt.Decode(string(buf), logfmt.DecodeOptions{ParseTypes: typed})
rv, err := asValue(fields)
if err != nil {
return fmt.Errorf("converting to Value: %w", err)
}
return call.ReturnValue(ctx, rv)
case io.Reader:
// decoder wants io.ReadSeeker so we need to read to buf.
// could read just enough that the decoder can detect the
// format and stream the rest?
buf, err := io.ReadAll(in)
if err != nil {
return fmt.Errorf("reding input: %w", err)
}
fields := logfmt.Decode(string(buf), logfmt.DecodeOptions{ParseTypes: typed})
rv, err := asValue(fields)
if err != nil {
return fmt.Errorf("converting to Value: %w", err)
}
return call.ReturnValue(ctx, rv)
default:
return fmt.Errorf("unsupported input type %T", call.Input)
}
}