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);
        }
Exemplo n.º 2
0
        /// <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;
        }