Skip to content

Commit 556ff76

Browse files
authored
Add logp package and its minor dependencies (#6)
1 parent d059cc9 commit 556ff76

36 files changed

+4981
-7
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
This repository is the home to the common libraries used by Elastic Agent and Beats.
44

55
Provided packages:
6-
* `github.com/elastic/elastic-agent-libs/config` the previous `config.go` file from `github.com/elastic/beats/v7/libbeat/common`. A minimal wrapper around `github.com/elastic/go-ucfg`. It contains helpers for merging and accessing configuration objects.
6+
* `github.com/elastic/elastic-agent-libs/config` the previous `config.go` file from `github.com/elastic/beats/v7/libbeat/common`. A minimal wrapper around `github.com/elastic/go-ucfg`. It contains helpers for merging and accessing configuration objects and flags.
77
* `github.com/elastic/elastic-agent-libs/str` the previous `stringset.go` file from `github.com/elastic/beats/v7/libbeat/common`. It provides a string set implementation.
8+
* `github.com/elastic/elastic-agent-libs/file` is responsible for rotating and writing input and output files.
9+
* `github.com/elastic/elastic-agent-libs/logp` is the well known logger from libbeat.

config/flags.go

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package config
19+
20+
import (
21+
"flag"
22+
"strings"
23+
24+
ucfg "github.com/elastic/go-ucfg"
25+
cfgflag "github.com/elastic/go-ucfg/flag"
26+
)
27+
28+
// StringsFlag collects multiple usages of the same flag into an array of strings.
29+
// Duplicate values will be ignored.
30+
type StringsFlag struct {
31+
list *[]string
32+
isDefault bool
33+
flag *flag.Flag
34+
}
35+
36+
// SettingsFlag captures key/values pairs into an Config object.
37+
// The flag backed by SettingsFlag can be used multiple times.
38+
// Values are overwritten by the last usage of a key.
39+
type SettingsFlag cfgflag.FlagValue
40+
41+
// flagOverwrite provides a flag value, which always overwrites the same setting
42+
// in an Config object.
43+
type flagOverwrite struct {
44+
config *ucfg.Config
45+
path string
46+
value string
47+
}
48+
49+
// StringArrFlag creates and registers a new StringsFlag with the given FlagSet.
50+
// If no FlagSet is passed, flag.CommandLine will be used as target FlagSet.
51+
func StringArrFlag(fs *flag.FlagSet, name, def, usage string) *StringsFlag {
52+
var arr *[]string
53+
if def != "" {
54+
arr = &[]string{def}
55+
} else {
56+
arr = &[]string{}
57+
}
58+
59+
return StringArrVarFlag(fs, arr, name, usage)
60+
}
61+
62+
// StringArrVarFlag creates and registers a new StringsFlag with the given
63+
// FlagSet. Results of the flag usage will be appended to `arr`. If the slice
64+
// is not initially empty, its first value will be used as default. If the flag
65+
// is used, the slice will be emptied first. If no FlagSet is passed,
66+
// flag.CommandLine will be used as target FlagSet.
67+
func StringArrVarFlag(fs *flag.FlagSet, arr *[]string, name, usage string) *StringsFlag {
68+
if fs == nil {
69+
fs = flag.CommandLine
70+
}
71+
f := NewStringsFlag(arr)
72+
f.Register(fs, name, usage)
73+
return f
74+
}
75+
76+
// NewStringsFlag creates a new, but unregistered StringsFlag instance.
77+
// Results of the flag usage will be appended to `arr`. If the slice is not
78+
// initially empty, its first value will be used as default. If the flag is
79+
// used, the slice will be emptied first.
80+
func NewStringsFlag(arr *[]string) *StringsFlag {
81+
if arr == nil {
82+
panic("No target array")
83+
}
84+
return &StringsFlag{list: arr, isDefault: true}
85+
}
86+
87+
// Register registers the StringsFlag instance with a FlagSet.
88+
// A valid FlagSet must be used.
89+
// Register panics if the flag is already registered.
90+
func (f *StringsFlag) Register(fs *flag.FlagSet, name, usage string) {
91+
if f.flag != nil {
92+
panic("StringsFlag is already registered")
93+
}
94+
95+
fs.Var(f, name, usage)
96+
f.flag = fs.Lookup(name)
97+
if f.flag == nil {
98+
panic("Failed to lookup registered flag")
99+
}
100+
101+
if len(*f.list) > 0 {
102+
f.flag.DefValue = (*f.list)[0]
103+
}
104+
}
105+
106+
// String joins all it's values set into a comma-separated string.
107+
func (f *StringsFlag) String() string {
108+
if f == nil || f.list == nil {
109+
return ""
110+
}
111+
112+
l := *f.list
113+
return strings.Join(l, ", ")
114+
}
115+
116+
// SetDefault sets the flags new default value.
117+
// This overwrites the contents in the backing array.
118+
func (f *StringsFlag) SetDefault(v string) {
119+
if f.flag != nil {
120+
f.flag.DefValue = v
121+
}
122+
123+
*f.list = []string{v}
124+
f.isDefault = true
125+
}
126+
127+
// Set is used to pass usage of the flag to StringsFlag. Set adds the new value
128+
// to the backing array. The array will be emptied on Set, if the backing array
129+
// still contains the default value.
130+
func (f *StringsFlag) Set(v string) error {
131+
// Ignore duplicates, can be caused by multiple flag parses
132+
if f.isDefault {
133+
*f.list = []string{v}
134+
} else {
135+
for _, old := range *f.list {
136+
if old == v {
137+
return nil
138+
}
139+
}
140+
*f.list = append(*f.list, v)
141+
}
142+
f.isDefault = false
143+
return nil
144+
}
145+
146+
// Get returns the backing slice its contents as interface{}. The type used is
147+
// `[]string`.
148+
func (f *StringsFlag) Get() interface{} {
149+
return f.List()
150+
}
151+
152+
// List returns the current set values.
153+
func (f *StringsFlag) List() []string {
154+
return *f.list
155+
}
156+
157+
// Type reports the type of contents (string) expected to be parsed by Set.
158+
// It is used to build the CLI usage string.
159+
func (f *StringsFlag) Type() string {
160+
return "string"
161+
}
162+
163+
// SettingFlag defines a setting flag, name and it's usage. The return value is
164+
// the Config object settings are applied to.
165+
func SettingFlag(fs *flag.FlagSet, name, usage string) *C {
166+
cfg := NewConfig()
167+
SettingVarFlag(fs, cfg, name, usage)
168+
return cfg
169+
}
170+
171+
// SettingVarFlag defines a setting flag, name and it's usage.
172+
// Settings are applied to the Config object passed.
173+
func SettingVarFlag(fs *flag.FlagSet, def *C, name, usage string) {
174+
if fs == nil {
175+
fs = flag.CommandLine
176+
}
177+
178+
f := NewSettingsFlag(def)
179+
fs.Var(f, name, usage)
180+
}
181+
182+
// NewSettingsFlag creates a new SettingsFlag instance, not registered with any
183+
// FlagSet.
184+
func NewSettingsFlag(def *C) *SettingsFlag {
185+
opts := append(
186+
[]ucfg.Option{
187+
ucfg.MetaData(ucfg.Meta{Source: "command line flag"}),
188+
},
189+
configOpts...,
190+
)
191+
192+
tmp := cfgflag.NewFlagKeyValue(def.access(), true, opts...)
193+
return (*SettingsFlag)(tmp)
194+
}
195+
196+
func (f *SettingsFlag) access() *cfgflag.FlagValue {
197+
return (*cfgflag.FlagValue)(f)
198+
}
199+
200+
// Config returns the config object the SettingsFlag stores applied settings to.
201+
func (f *SettingsFlag) Config() *C {
202+
return fromConfig(f.access().Config())
203+
}
204+
205+
// Set sets a settings value in the Config object. The input string must be a
206+
// key-value pair like `key=value`. If the value is missing, the value is set
207+
// to the boolean value `true`.
208+
func (f *SettingsFlag) Set(s string) error {
209+
return f.access().Set(s)
210+
}
211+
212+
// Get returns the Config object used to store values.
213+
func (f *SettingsFlag) Get() interface{} {
214+
return f.Config()
215+
}
216+
217+
// String always returns an empty string. It is required to fulfil
218+
// the flag.Value interface.
219+
func (f *SettingsFlag) String() string {
220+
return ""
221+
}
222+
223+
// Type reports the type of contents (setting=value) expected to be parsed by Set.
224+
// It is used to build the CLI usage string.
225+
func (f *SettingsFlag) Type() string {
226+
return "setting=value"
227+
}
228+
229+
// ConfigOverwriteFlag defines a new flag updating a setting in an Config
230+
// object. The name is used as the flag its name the path parameter is the
231+
// full setting name to be used when the flag is set.
232+
func ConfigOverwriteFlag(
233+
fs *flag.FlagSet,
234+
config *C,
235+
name, path, def, usage string,
236+
) *string {
237+
if config == nil {
238+
panic("Missing configuration")
239+
}
240+
if path == "" {
241+
panic("empty path")
242+
}
243+
244+
if fs == nil {
245+
fs = flag.CommandLine
246+
}
247+
248+
if def != "" {
249+
err := config.SetString(path, -1, def)
250+
if err != nil {
251+
panic(err)
252+
}
253+
}
254+
255+
f := newOverwriteFlag(config, path, def)
256+
fs.Var(f, name, usage)
257+
return &f.value
258+
}
259+
260+
func newOverwriteFlag(c *C, path, def string) *flagOverwrite {
261+
return &flagOverwrite{config: c.access(), path: path, value: def}
262+
}
263+
264+
func (f *flagOverwrite) String() string {
265+
return f.value
266+
}
267+
268+
func (f *flagOverwrite) Set(v string) error {
269+
opts := append(
270+
[]ucfg.Option{
271+
ucfg.MetaData(ucfg.Meta{Source: "command line flag"}),
272+
},
273+
configOpts...,
274+
)
275+
276+
err := f.config.SetString(f.path, -1, v, opts...)
277+
if err != nil {
278+
return err
279+
}
280+
f.value = v
281+
return nil
282+
}
283+
284+
func (f *flagOverwrite) Get() interface{} {
285+
return f.value
286+
}
287+
288+
func (f *flagOverwrite) Type() string {
289+
return "string"
290+
}

0 commit comments

Comments
 (0)