func dumpFaultyPlugin(typeName string, pluginType reflect.Type) { Log.Error.Print("Failed to load plugin ", typeName, ": Does not qualify for consumer, producer or stream interface") consumerMatch, consumerMissing := shared.GetMissingMethods(pluginType, consumerInterface) producerMatch, producerMissing := shared.GetMissingMethods(pluginType, producerInterface) streamMatch, streamMissing := shared.GetMissingMethods(pluginType, streamInterface) if consumerMatch > producerMatch { if consumerMatch > streamMatch { Log.Error.Print("Plugin looks like a consumer:") for _, message := range consumerMissing { Log.Error.Print(message) } } else { Log.Error.Print("Plugin looks like a stream:") for _, message := range streamMissing { Log.Error.Print(message) } } } else if producerMatch > streamMatch { Log.Error.Print("Plugin looks like a producer:") for _, message := range producerMissing { Log.Error.Print(message) } } else { Log.Error.Print("Plugin looks like a stream:") for _, message := range streamMissing { Log.Error.Print(message) } } }
// Create a new multiplexer based on a given config file. func newMultiplexer(conf *core.Config, profile bool) multiplexer { // Configure the multiplexer, create a byte pool and assign it to the log shared.Metric.New(metricMsgSec) shared.Metric.New(metricMsgSecAvg) shared.Metric.New(metricCons) shared.Metric.New(metricProds) shared.Metric.New(metricMessages) plex := multiplexer{ consumers: []core.Consumer{new(core.LogConsumer)}, consumerWorker: new(sync.WaitGroup), producerWorker: new(sync.WaitGroup), profile: profile, state: multiplexerStateConfigure, } // Sort the plugins by interface type. var consumerConfig, producerConfig, streamConfig []core.PluginConfig consumerInterface := reflect.TypeOf((*core.Consumer)(nil)).Elem() producerInterface := reflect.TypeOf((*core.Producer)(nil)).Elem() streamInterface := reflect.TypeOf((*core.Stream)(nil)).Elem() for _, config := range conf.Plugins { if !config.Enable { continue // ### continue, disabled ### } pluginType := shared.RuntimeType.GetTypeOf(config.Typename) if pluginType == nil { Log.Error.Print("Failed to load plugin ", config.Typename, ": Type not found") continue // ### continue ### } validPlugin := false if pluginType.Implements(consumerInterface) { consumerConfig = append(consumerConfig, config) validPlugin = true } if pluginType.Implements(producerInterface) { producerConfig = append(producerConfig, config) validPlugin = true } if pluginType.Implements(streamInterface) { streamConfig = append(streamConfig, config) validPlugin = true } if !validPlugin { Log.Error.Print("Failed to load plugin ", config.Typename, ": Does not qualify for consumer, producer or stream interface") consumerMatch, consumerMissing := shared.GetMissingMethods(pluginType, consumerInterface) producerMatch, producerMissing := shared.GetMissingMethods(pluginType, producerInterface) streamMatch, streamMissing := shared.GetMissingMethods(pluginType, streamInterface) if consumerMatch > producerMatch { if consumerMatch > streamMatch { Log.Error.Print("Plugin looks like a consumer:") for _, message := range consumerMissing { Log.Error.Print(message) } } else { Log.Error.Print("Plugin looks like a stream:") for _, message := range streamMissing { Log.Error.Print(message) } } } else if producerMatch > streamMatch { Log.Error.Print("Plugin looks like a producer:") for _, message := range producerMissing { Log.Error.Print(message) } } else { Log.Error.Print("Plugin looks like a stream:") for _, message := range streamMissing { Log.Error.Print(message) } } } } // Initialize the plugins in the order of stream, producer, consumer to // match the order of reference between the different types. for _, config := range streamConfig { for _, streamName := range config.Stream { plugin, err := core.NewPlugin(config) if err != nil { Log.Error.Print("Failed to configure stream plugin ", config.Typename, ": ", err) continue // ### continue ### } core.StreamTypes.Register(plugin.(core.Stream), core.GetStreamID(streamName)) } } // All producers are added to the wildcard stream so that consumers can send // to all producers if required. The wildcard producer list is required // to add producers listening to all streams to all streams that are used. wildcardStream := core.StreamTypes.GetStreamOrFallback(core.WildcardStreamID) for _, config := range producerConfig { for i := 0; i < config.Instances; i++ { plugin, err := core.NewPlugin(config) if err != nil { Log.Error.Print("Failed to configure producer plugin ", config.Typename, ": ", err) continue // ### continue ### } producer, _ := plugin.(core.Producer) streams := producer.Streams() if len(streams) == 0 { Log.Error.Print("Producer plugin ", config.Typename, " has no streams set") continue // ### continue ### } for _, streamID := range streams { if streamID == core.WildcardStreamID { core.StreamTypes.RegisterWildcardProducer(producer) } else { stream := core.StreamTypes.GetStreamOrFallback(streamID) stream.AddProducer(producer) } } // Do not add internal streams to wildcard stream for _, streamID := range streams { if streamID != core.LogInternalStreamID && streamID != core.DroppedStreamID { wildcardStream.AddProducer(producer) break } } plex.producers = append(plex.producers, producer) shared.Metric.Inc(metricProds) } } // Consumers are registered last so that the stream reference list can be // built. This eliminates lookups when sending to specific streams. logConsumer, _ := plex.consumers[0].(*core.LogConsumer) logConsumer.Configure(core.NewPluginConfig("core.LogConsumer")) for _, config := range consumerConfig { for i := 0; i < config.Instances; i++ { plugin, err := core.NewPlugin(config) if err != nil { Log.Error.Print("Failed to configure consumer plugin ", config.Typename, ": ", err) continue // ### continue ### } consumer, _ := plugin.(core.Consumer) plex.consumers = append(plex.consumers, consumer) shared.Metric.Inc(metricCons) } } // As consumers might create new fallback streams this is the first position // where we can add the wildcard producers to all streams. No new streams // created beyond this point must use StreamRegistry.AddWildcardProducersToStream. core.StreamTypes.ForEachStream( func(streamID core.MessageStreamID, stream core.Stream) { switch streamID { case core.LogInternalStreamID, core.WildcardStreamID, core.DroppedStreamID: // Internal streams are excluded for wildcard listeners default: core.StreamTypes.AddWildcardProducersToStream(stream) } }) return plex }