public void StreamsAppSensorTest() { var builder = new StreamBuilder(); builder.Stream <string, string>("topic").To("topic2"); var sensor = GeneralClientMetrics.StreamsAppSensor( "my-application", builder.Build().Describe().ToString(), () => 0, () => 1, streamMetricsRegistry); Assert.AreEqual(5, sensor.Metrics.Keys.Count()); Assert.AreEqual(Assembly.GetExecutingAssembly().GetName().Version.ToString(), sensor.Metrics[MetricName.NameAndGroup( GeneralClientMetrics.VERSION, StreamMetricsRegistry.CLIENT_LEVEL_GROUP)].Value); Assert.AreEqual(0, sensor.Metrics[MetricName.NameAndGroup( GeneralClientMetrics.STATE, StreamMetricsRegistry.CLIENT_LEVEL_GROUP)].Value); Assert.AreEqual(builder.Build().Describe().ToString(), sensor.Metrics[MetricName.NameAndGroup( GeneralClientMetrics.TOPOLOGY_DESCRIPTION, StreamMetricsRegistry.CLIENT_LEVEL_GROUP)].Value); Assert.AreEqual(1, sensor.Metrics[MetricName.NameAndGroup( GeneralClientMetrics.STREAM_THREADS, StreamMetricsRegistry.CLIENT_LEVEL_GROUP)].Value); Assert.AreEqual("my-application", sensor.Metrics[MetricName.NameAndGroup( GeneralClientMetrics.APPLICATION_ID, StreamMetricsRegistry.CLIENT_LEVEL_GROUP)].Value); }
/// <summary> /// Create a <see cref="KafkaStream"/> instance with your own <see cref="IKafkaSupplier" /> /// Please DO NOT FORGET to call Close to avoid resources leak ! /// </summary> /// <param name="topology">the topology specifying the computational logic</param> /// <param name="configuration">configuration about this stream</param> /// <param name="kafkaSupplier">the Kafka clients supplier which provides underlying producer and consumer clients for the new <see cref="KafkaStream"/> instance</param> public KafkaStream(Topology topology, IStreamConfig configuration, IKafkaSupplier kafkaSupplier) { this.topology = topology; this.kafkaSupplier = kafkaSupplier; this.configuration = configuration; Logger.LoggerFactory = configuration.Logger; logger = Logger.GetLogger(typeof(KafkaStream)); // check if ApplicationId & BootstrapServers has been set if (string.IsNullOrEmpty(configuration.ApplicationId) || string.IsNullOrEmpty(configuration.BootstrapServers)) { throw new StreamConfigException($"Stream configuration is not correct. Please set ApplicationId and BootstrapServers as minimal."); } var processID = Guid.NewGuid(); clientId = string.IsNullOrEmpty(configuration.ClientId) ? $"{configuration.ApplicationId.ToLower()}-{processID}" : configuration.ClientId; logPrefix = $"stream-application[{configuration.ApplicationId}] "; metricsRegistry = new StreamMetricsRegistry(clientId, configuration.MetricsRecording); this.kafkaSupplier.MetricsRegistry = metricsRegistry; logger.LogInformation($"{logPrefix} Start creation of the stream application with this configuration: {configuration}"); // re-write the physical topology according to the config topology.Builder.RewriteTopology(configuration); // sanity check var processorTopology = topology.Builder.BuildTopology(); int numStreamThreads = topology.Builder.HasNoNonGlobalTopology ? 0 : configuration.NumStreamThreads; GeneralClientMetrics.StreamsAppSensor( configuration.ApplicationId, topology.Describe().ToString(), () => StreamState != null && StreamState.IsRunning() ? 1 : 0, () => threads.Count(t => t.State != ThreadState.DEAD && t.State != ThreadState.PENDING_SHUTDOWN), metricsRegistry); threads = new IThread[numStreamThreads]; var threadState = new Dictionary <long, Processors.ThreadState>(); ProcessorTopology globalTaskTopology = topology.Builder.BuildGlobalStateTopology(); bool hasGlobalTopology = globalTaskTopology != null; if (numStreamThreads == 0 && !hasGlobalTopology) { throw new TopologyException("Topology has no stream threads and no global threads, " + "must subscribe to at least one source topic or global table."); } GlobalThreadState globalThreadState = null; if (hasGlobalTopology) { string globalThreadId = $"{clientId}-GlobalStreamThread"; GlobalStreamThreadFactory globalStreamThreadFactory = new GlobalStreamThreadFactory( globalTaskTopology, globalThreadId, kafkaSupplier.GetGlobalConsumer(configuration.ToGlobalConsumerConfig(globalThreadId)), configuration, kafkaSupplier.GetAdmin(configuration.ToAdminConfig(clientId)), metricsRegistry); globalStreamThread = globalStreamThreadFactory.GetGlobalStreamThread(); globalThreadState = globalStreamThread.State; } List <StreamThreadStateStoreProvider> stateStoreProviders = new List <StreamThreadStateStoreProvider>(); for (int i = 0; i < numStreamThreads; ++i) { var threadId = $"{clientId}-stream-thread-{i}"; var adminClient = this.kafkaSupplier.GetAdmin(configuration.ToAdminConfig(StreamThread.GetSharedAdminClientId(clientId))); threads[i] = StreamThread.Create( threadId, clientId, this.topology.Builder, metricsRegistry, configuration, this.kafkaSupplier, adminClient, i); threadState.Add(threads[i].Id, threads[i].State); stateStoreProviders.Add(new StreamThreadStateStoreProvider(threads[i], this.topology.Builder)); } manager = new StreamStateManager(this, threadState, globalThreadState); if (hasGlobalTopology) { globalStreamThread.StateChanged += manager.OnGlobalThreadStateChange; } foreach (var t in threads) { t.StateChanged += manager.OnChange; } var globalStateStoreProvider = new GlobalStateStoreProvider(topology.Builder.GlobalStateStores); queryableStoreProvider = new QueryableStoreProvider(stateStoreProviders, globalStateStoreProvider); StreamState = State.CREATED; }