@@ -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+
94124type 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
98128var 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.
154184func 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
222259func 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