Skip to content

Commit a499e49

Browse files
author
goodsign
committed
Added config-scope custom dispatcher mappings. cihub#39.
1 parent fd6c865 commit a499e49

File tree

5 files changed

+239
-99
lines changed

5 files changed

+239
-99
lines changed

cfg_config.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,40 @@ func LoggerFromConfigAsString(data string) (LoggerInterface, error) {
6161
return LoggerFromConfigAsBytes([]byte(data))
6262
}
6363

64+
// LoggerFromParamConfigAsFile does the same as LoggerFromConfigAsFile, but includes special parser options.
65+
// See 'CfgParseParams' comments.
66+
func LoggerFromParamConfigAsFile(fileName string, parserParams *CfgParseParams) (LoggerInterface, error) {
67+
file, err := os.Open(fileName)
68+
if err != nil {
69+
return nil, err
70+
}
71+
defer file.Close()
72+
73+
conf, err := configFromReaderWithConfig(file, parserParams)
74+
if err != nil {
75+
return nil, err
76+
}
77+
78+
return createLoggerFromConfig(conf)
79+
}
80+
81+
// LoggerFromParamConfigAsBytes does the same as LoggerFromConfigAsBytes, but includes special parser options.
82+
// See 'CfgParseParams' comments.
83+
func LoggerFromParamConfigAsBytes(data []byte, parserParams *CfgParseParams) (LoggerInterface, error) {
84+
conf, err := configFromReaderWithConfig(bytes.NewBuffer(data), parserParams)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
return createLoggerFromConfig(conf)
90+
}
91+
92+
// LoggerFromParamConfigAsString does the same as LoggerFromConfigAsString, but includes special parser options.
93+
// See 'CfgParseParams' comments.
94+
func LoggerFromParamConfigAsString(data string, parserParams *CfgParseParams) (LoggerInterface, error) {
95+
return LoggerFromParamConfigAsBytes([]byte(data), parserParams)
96+
}
97+
6498
// LoggerFromWriterWithMinLevel creates a proxy logger that uses io.Writer as the
6599
// receiver with minimal level = minLevel.
66100
//
@@ -79,7 +113,7 @@ func LoggerFromWriterWithMinLevel(output io.Writer, minLevel LogLevel) (LoggerIn
79113
return nil, err
80114
}
81115

82-
conf, err := newConfig(constraints, make([]*logLevelException, 0), dispatcher, syncloggerTypeFromString, nil)
116+
conf, err := newConfig(constraints, make([]*logLevelException, 0), dispatcher, syncloggerTypeFromString, nil, nil)
83117
if err != nil {
84118
return nil, err
85119
}
@@ -116,7 +150,7 @@ func LoggerFromCustomReceiver(receiver CustomReceiver) (LoggerInterface, error)
116150
return nil, err
117151
}
118152

119-
output, err := newCustomReceiverDispatcherByValue(msgonlyformatter, receiver)
153+
output, err := newCustomReceiverDispatcherByValue(msgonlyformatter, receiver, "user-proxy", CustomReceiverInitArgs{})
120154
if err != nil {
121155
return nil, err
122156
}
@@ -125,7 +159,7 @@ func LoggerFromCustomReceiver(receiver CustomReceiver) (LoggerInterface, error)
125159
return nil, err
126160
}
127161

128-
conf, err := newConfig(constraints, make([]*logLevelException, 0), dispatcher, syncloggerTypeFromString, nil)
162+
conf, err := newConfig(constraints, make([]*logLevelException, 0), dispatcher, syncloggerTypeFromString, nil, nil)
129163
if err != nil {
130164
return nil, err
131165
}

cfg_logconfig.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,16 @@ type logConfig struct {
8383
RootDispatcher dispatcherInterface // Root of output tree
8484
LogType loggerTypeFromString
8585
LoggerData interface{}
86+
Params *CfgParseParams // Check cfg_parser: CfgParseParams
8687
}
8788

8889
func newConfig(
8990
constraints logLevelConstraints,
9091
exceptions []*logLevelException,
9192
rootDispatcher dispatcherInterface,
9293
logType loggerTypeFromString,
93-
logData interface{}) (*logConfig, error) {
94+
logData interface{},
95+
cfgParams *CfgParseParams) (*logConfig, error) {
9496
if constraints == nil {
9597
return nil, errors.New("Constraints can not be nil")
9698
}
@@ -104,6 +106,7 @@ func newConfig(
104106
config.RootDispatcher = rootDispatcher
105107
config.LogType = logType
106108
config.LoggerData = logData
109+
config.Params = cfgParams
107110

108111
return config, nil
109112
}

cfg_parser.go

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,38 @@ const (
9191
connWriterReconnectOnMsgAttr = "reconnectonmsg"
9292
)
9393

94+
// CfgParseParams represent specific parse options or flags used by parser. It is used if seelog parser needs
95+
// some special directives or additional info to correctly parse a config.
96+
type CfgParseParams struct {
97+
// CustomReceiverProducers expose the same functionality as RegisterReceiver func
98+
// but only in the scope (context) of the config parse func instead of a global package scope.
99+
//
100+
// It means that if you use custom receivers in your code, you may either register them globally once with
101+
// RegisterReceiver or you may call funcs like LoggerFromParamConfigAsFile (with 'ParamConfig')
102+
// and use CustomReceiverProducers to provide custom producer funcs.
103+
//
104+
// A producer func is called when config parser processes a '<custom>' element. It takes the 'name' attribute
105+
// of the element and tries to find a match in two places:
106+
// 1) CfgParseParams.CustomReceiverProducers map
107+
// 2) Global type map, filled by RegisterReceiver
108+
//
109+
// If a match is found in the CustomReceiverProducers map, parser calls the corresponding producer func
110+
// passing the init args to it. The func takes exactly the same args as CustomReceiver.AfterParse.
111+
// The producer func must return a correct receiver or an error. If case of error, seelog will behave
112+
// in the same way as with any other config error.
113+
//
114+
// You may use this param to set custom producers in case you need to pass some context when instantiating
115+
// a custom receiver or if you frequently change custom receivers with different parameters or in any other
116+
// situation where package-level registering (RegisterReceiver) is not an option for you.
117+
CustomReceiverProducers map[string]func(initArgs CustomReceiverInitArgs) (CustomReceiver, error)
118+
}
119+
120+
func (cfg *CfgParseParams) String() string {
121+
return fmt.Sprintf("CfgParams: {custom_recs=%d}", len(cfg.CustomReceiverProducers))
122+
}
123+
94124
type elementMapEntry struct {
95-
constructor func(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error)
125+
constructor func(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error)
96126
}
97127

98128
var elementMap map[string]elementMapEntry
@@ -152,6 +182,13 @@ func fillPredefinedFormats() error {
152182
// Returns parsed config which can be used to create logger in case no errors occured.
153183
// Returns error if format is incorrect or anything happened.
154184
func configFromReader(reader io.Reader) (*logConfig, error) {
185+
return configFromReaderWithConfig(reader, nil)
186+
}
187+
188+
// configFromReader parses data from a given reader.
189+
// Returns parsed config which can be used to create logger in case no errors occured.
190+
// Returns error if format is incorrect or anything happened.
191+
func configFromReaderWithConfig(reader io.Reader, cfg *CfgParseParams) (*logConfig, error) {
155192
config, err := unmarshalConfig(reader)
156193
if err != nil {
157194
return nil, err
@@ -200,7 +237,7 @@ func configFromReader(reader io.Reader) (*logConfig, error) {
200237
return nil, err
201238
}
202239

203-
dispatcher, err := getOutputsTree(config, formats)
240+
dispatcher, err := getOutputsTree(config, formats, cfg)
204241
if err != nil {
205242
// If we open several files, but then fail to parse the config, we should close
206243
// those files before reporting that config is invalid.
@@ -216,7 +253,7 @@ func configFromReader(reader io.Reader) (*logConfig, error) {
216253
return nil, err
217254
}
218255

219-
return newConfig(constraints, exceptions, dispatcher, loggerType, logData)
256+
return newConfig(constraints, exceptions, dispatcher, loggerType, logData, cfg)
220257
}
221258

222259
func getConstraints(node *xmlNode) (logLevelConstraints, error) {
@@ -478,7 +515,7 @@ func getloggerTypeFromStringData(config *xmlNode) (logType loggerTypeFromString,
478515
return logType, logData, nil
479516
}
480517

481-
func getOutputsTree(config *xmlNode, formats map[string]*formatter) (dispatcherInterface, error) {
518+
func getOutputsTree(config *xmlNode, formats map[string]*formatter, cfg *CfgParseParams) (dispatcherInterface, error) {
482519
var outputsNode *xmlNode
483520
for _, child := range config.children {
484521
if child.name == outputsId {
@@ -498,7 +535,7 @@ func getOutputsTree(config *xmlNode, formats map[string]*formatter) (dispatcherI
498535
return nil, err
499536
}
500537

501-
output, err := createSplitter(outputsNode, formatter, formats)
538+
output, err := createSplitter(outputsNode, formatter, formats, cfg)
502539
if err != nil {
503540
return nil, err
504541
}
@@ -537,15 +574,15 @@ func getCurrentFormat(node *xmlNode, formatFromParent *formatter, formats map[st
537574
return pdFormat, nil
538575
}
539576

540-
func createInnerReceivers(node *xmlNode, format *formatter, formats map[string]*formatter) ([]interface{}, error) {
577+
func createInnerReceivers(node *xmlNode, format *formatter, formats map[string]*formatter, cfg *CfgParseParams) ([]interface{}, error) {
541578
outputs := make([]interface{}, 0)
542579
for _, childNode := range node.children {
543580
entry, ok := elementMap[childNode.name]
544581
if !ok {
545582
return nil, errors.New("Unnknown tag '" + childNode.name + "' in outputs section")
546583
}
547584

548-
output, err := entry.constructor(childNode, format, formats)
585+
output, err := entry.constructor(childNode, format, formats, cfg)
549586
if err != nil {
550587
return nil, err
551588
}
@@ -556,7 +593,7 @@ func createInnerReceivers(node *xmlNode, format *formatter, formats map[string]*
556593
return outputs, nil
557594
}
558595

559-
func createSplitter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
596+
func createSplitter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
560597
err := checkUnexpectedAttribute(node, outputFormatId)
561598
if err != nil {
562599
return nil, err
@@ -571,15 +608,15 @@ func createSplitter(node *xmlNode, formatFromParent *formatter, formats map[stri
571608
return nil, err
572609
}
573610

574-
receivers, err := createInnerReceivers(node, currentFormat, formats)
611+
receivers, err := createInnerReceivers(node, currentFormat, formats, cfg)
575612
if err != nil {
576613
return nil, err
577614
}
578615

579616
return newSplitDispatcher(currentFormat, receivers)
580617
}
581618

582-
func createCustomReceiver(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
619+
func createCustomReceiver(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
583620
dataCustomPrefixes := make(map[string]string)
584621
// Expecting only 'formatid', 'name' and 'data-' attrs
585622
for attr, attrval := range node.attributes {
@@ -611,10 +648,29 @@ func createCustomReceiver(node *xmlNode, formatFromParent *formatter, formats ma
611648
args := CustomReceiverInitArgs{
612649
XmlCustomAttrs: dataCustomPrefixes,
613650
}
651+
652+
if cfg != nil && cfg.CustomReceiverProducers != nil {
653+
if prod, ok := cfg.CustomReceiverProducers[customName]; ok {
654+
rec, err := prod(args)
655+
if err != nil {
656+
return nil, err
657+
}
658+
creceiver, err := newCustomReceiverDispatcherByValue(currentFormat, rec, customName, args)
659+
if err != nil {
660+
return nil, err
661+
}
662+
err = rec.AfterParse(args)
663+
if err != nil {
664+
return nil, err
665+
}
666+
return creceiver, nil
667+
}
668+
}
669+
614670
return newCustomReceiverDispatcher(currentFormat, customName, args)
615671
}
616672

617-
func createFilter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
673+
func createFilter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
618674
err := checkUnexpectedAttribute(node, outputFormatId, filterLevelsAttrId)
619675
if err != nil {
620676
return nil, err
@@ -639,15 +695,15 @@ func createFilter(node *xmlNode, formatFromParent *formatter, formats map[string
639695
return nil, err
640696
}
641697

642-
receivers, err := createInnerReceivers(node, currentFormat, formats)
698+
receivers, err := createInnerReceivers(node, currentFormat, formats, cfg)
643699
if err != nil {
644700
return nil, err
645701
}
646702

647703
return newFilterDispatcher(currentFormat, receivers, levels...)
648704
}
649705

650-
func createfileWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
706+
func createfileWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
651707
err := checkUnexpectedAttribute(node, outputFormatId, pathId)
652708
if err != nil {
653709
return nil, err
@@ -676,7 +732,7 @@ func createfileWriter(node *xmlNode, formatFromParent *formatter, formats map[st
676732
}
677733

678734
// Creates new SMTP writer if encountered in the config file.
679-
func createSmtpWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
735+
func createSmtpWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
680736
err := checkUnexpectedAttribute(node, outputFormatId, senderaddressId, senderNameId, hostNameId, hostPortId, userNameId, userPassId)
681737
if err != nil {
682738
return nil, err
@@ -759,7 +815,7 @@ func createSmtpWriter(node *xmlNode, formatFromParent *formatter, formats map[st
759815
return newFormattedWriter(smtpWriter, currentFormat)
760816
}
761817

762-
func createConsoleWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
818+
func createConsoleWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
763819
err := checkUnexpectedAttribute(node, outputFormatId)
764820
if err != nil {
765821
return nil, err
@@ -782,7 +838,7 @@ func createConsoleWriter(node *xmlNode, formatFromParent *formatter, formats map
782838
return newFormattedWriter(consoleWriter, currentFormat)
783839
}
784840

785-
func createconnWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
841+
func createconnWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
786842
if node.hasChildren() {
787843
return nil, nodeCannotHaveChildrenError
788844
}
@@ -824,7 +880,7 @@ func createconnWriter(node *xmlNode, formatFromParent *formatter, formats map[st
824880
return newFormattedWriter(connWriter, currentFormat)
825881
}
826882

827-
func createRollingFileWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
883+
func createRollingFileWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
828884
if node.hasChildren() {
829885
return nil, nodeCannotHaveChildrenError
830886
}
@@ -943,7 +999,7 @@ func createRollingFileWriter(node *xmlNode, formatFromParent *formatter, formats
943999
return nil, errors.New("Incorrect rolling writer type " + rollingTypeStr)
9441000
}
9451001

946-
func createbufferedWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter) (interface{}, error) {
1002+
func createbufferedWriter(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error) {
9471003
err := checkUnexpectedAttribute(node, outputFormatId, bufferedSizeAttr, bufferedFlushPeriodAttr)
9481004
if err != nil {
9491005
return nil, err
@@ -978,7 +1034,7 @@ func createbufferedWriter(node *xmlNode, formatFromParent *formatter, formats ma
9781034
}
9791035

9801036
// Inner writer couldn't have its own format, so we pass 'currentFormat' as its parent format
981-
receivers, err := createInnerReceivers(node, currentFormat, formats)
1037+
receivers, err := createInnerReceivers(node, currentFormat, formats, cfg)
9821038
if err != nil {
9831039
return nil, err
9841040
}

0 commit comments

Comments
 (0)