Exemplo n.º 1
0
 protected PersistenceSpec(string config)
     : base(config)
 {
     _name = NamePrefix + "-" + _counter.GetAndIncrement();
     Clean = new Cleanup(this);
     Clean.Initialize();
 }
        /// <summary>
        ///     Performs all of the initialization to get the PCF metrics forwarding engine up and running.
        /// </summary>
        /// <param name="settings">The options and settings needed to communicate with PCF.</param>
        /// <param name="system">Optional. An <see cref="ActorSystem" /> used to spawn the underlying actors needed to do the job.</param>
        /// <returns>A new <see cref="PcfMetricRecorder" /> instance.</returns>
        public static PcfMetricRecorder Create(PcfMetricForwarderSettings settings, ActorSystem system = null)
        {
            var weOwnActorSystem = false;

            if (system == null) // create our own ActorSystem if it doesn't already exist.
            {
                weOwnActorSystem = true;
                system           = ActorSystem.Create("pbpcfmetrics",
                                                      settings.DebugLogging ? DebugHocon : NormalHocon);
            }

            // spawn as a System actor, so in the event of being in a non-owned system our traces get shut down
            // only after all of the user-defined actors have terminated.
            var reporterActor = system.AsInstanceOf <ExtendedActorSystem>().SystemActorOf(
                Props.Create(() => new MetricsReporterActor(settings)),
                $"pcf-reporter-{NameCounter.GetAndIncrement()}");


            var counterActor = system.AsInstanceOf <ExtendedActorSystem>().SystemActorOf(
                Props.Create(() =>
                             new CounterAggregator(reporterActor, settings.TimeProvider ?? new DateTimeOffsetTimeProvider())),
                $"pcf-reporter-{NameCounter.GetAndIncrement()}");

            return(new PcfMetricRecorder(reporterActor, counterActor, weOwnActorSystem ? system : null));
        }
Exemplo n.º 3
0
        public void SharedFiber_shutdown_should_not_disrupt_original_Fiber()
        {
            var atomicCounter = new AtomicCounter(0);
            var originalFiber = FiberFactory.CreateFiber(2); //going to use a dedicated thread Fiber
            var sharedFiber1  = new SharedFiber(originalFiber);
            var sharedFiber2  = sharedFiber1.Clone();

            for (var i = 0; i < 1000; i++)
            {
                originalFiber.Add(() => atomicCounter.GetAndIncrement());
                sharedFiber1.Add(() => atomicCounter.GetAndIncrement());
            }
            sharedFiber1.GracefulShutdown(TimeSpan.FromSeconds(1)).Wait(); //wait for the fiber to finish

            Assert.AreEqual(2000, atomicCounter.Current);                  //should have a total count of 2000

            for (var i = 0; i < 1000; i++)
            {
                originalFiber.Add(() => atomicCounter.GetAndIncrement());
                sharedFiber1.Add(() => atomicCounter.GetAndIncrement());
            }
            Thread.Sleep(TimeSpan.FromSeconds(1));
            Assert.AreEqual(3000, atomicCounter.Current); //should have a total count of 3000
            Assert.IsTrue(sharedFiber2.Running);
            Assert.IsTrue(originalFiber.Running);
            Assert.IsFalse(sharedFiber1.Running);
        }
Exemplo n.º 4
0
 protected PersistenceSpec(string config, ITestOutputHelper output = null)
     : base(config, output)
 {
     _name = NamePrefix + "-" + _counter.GetAndIncrement();
     Clean = new Cleanup(this);
     Clean.Initialize();
 }
Exemplo n.º 5
0
        private void Main_Load(object sender, EventArgs e)
        {
            _chartActor = Program.ChartActors.ActorOf(Props.Create(() => new ChartingActor(sysChart)), "charting");
            var series = ChartDataHelper.RandomSeries("FakeSeries" + _seriesCounter.GetAndIncrement());

            _chartActor.Tell(new ChartingActor.InitializeChart(new Dictionary <string, Series>()
            {
                { series.Name, series }
            }));
        }
Exemplo n.º 6
0
 public FailAfterSuccess(TestLatch latch, AtomicCounter counter)
 {
     StartWith(
         AllSucceed(
             AnySucceed(
                 After(
                     Execute(_ => counter.GetAndIncrement()),
                     Fail()),
                 Execute(_ => counter.GetAndIncrement())),
             Execute(_ => latch.CountDown())), null);
 }
Exemplo n.º 7
0
 public SuccessAfterFailure(TestLatch latch, AtomicCounter counter)
 {
     StartWith(
         AllSucceed(
             AllComplete(
                 After(
                     AllSucceed(
                         Execute(_ => counter.GetAndIncrement()),
                         Fail()),
                     Not(Fail())),
                 Execute(_ => counter.GetAndIncrement())),
             Execute(_ => latch.CountDown())), null);
 }
Exemplo n.º 8
0
        public void Should_be_able_to_change_NetworkEventLoop_error_handler_at_runtime()
        {
            var eventLoop          = EventLoopFactory.CreateNetworkEventLoop();
            var count              = new AtomicCounter(0);
            var trappedException   = false;
            var backgroundProducer = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    eventLoop.Execute(() => count.GetAndIncrement());
                    Thread.Sleep(10);
                }
            });

            eventLoop.SetExceptionHandler((connection, exception) => trappedException = true, null);
            eventLoop.Execute(() =>
            {
                throw new Exception("I'm an exception!");
            });

            backgroundProducer.Wait();

            Assert.AreEqual(10, count.Current);
            Assert.IsTrue(trappedException);
        }
Exemplo n.º 9
0
        public override Routee NewRoutee(Props routeeProps, IActorContext context)
        {
            var name     = "c" + _childNameCounter.GetAndIncrement();
            var actorRef = context.ActorOf(EnrichWithPoolDispatcher(routeeProps, context), name);

            return(new ActorRefRoutee(actorRef));
        }
Exemplo n.º 10
0
        private void btnAddSeries_Click(object sender, EventArgs e)
        {
            var series  = ChartDataHelper.RandomSeries($"Fake Series {_seriesCounter.GetAndIncrement()}");
            var message = new AddSeriesMessage(series);

            _chartActor.Tell(message);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Sends a message to the tail chopping router's collection of routees.
        /// </summary>
        /// <param name="message">The message to send.</param>
        /// <param name="sender">The sender of the message.</param>
        public override void Send(object message, IActorRef sender)
        {
            _routees.Shuffle();
            var routeeIndex = new AtomicCounter(0);

            var completion = new TaskCompletionSource <object>();
            var cancelable = new Cancelable(_scheduler);

            _scheduler.Advanced.ScheduleRepeatedly(TimeSpan.Zero, _interval, async() =>
            {
                var currentIndex = routeeIndex.GetAndIncrement();
                if (currentIndex < _routees.Length)
                {
                    completion.TrySetResult(await((Task <object>)_routees[currentIndex].Ask(message, null)));
                }
            }, cancelable);

            _scheduler.Advanced.ScheduleOnce(_within, () =>
            {
                completion.TrySetException(new TimeoutException(String.Format("Ask timed out on {0} after {1}", sender, _within)));
            }, cancelable);

            var request = completion.Task;

            completion.Task.ContinueWith(task =>
            {
                cancelable.Cancel(false);
            });

            request.PipeTo(sender);
        }
Exemplo n.º 12
0
        private void Main_Load(object sender, EventArgs e)
        {
            _chartActor = Program.ChartActors.ActorOf(Props.Create(() => new ChartingActor(sysChart, btnPauseResume)), "charting");
            var series = ChartDataHelper.RandomSeries("FakeSeries" + _seriesCounter.GetAndIncrement());

            _chartActor.Tell(new ChartingActor.InitializeChart(null));

            _coordinatorActor = Program.ChartActors.ActorOf(Props.Create(() =>
                                                                         new PerformanceCounterCoordinatorActor(_chartActor)), "counters");

            // CPU button toggle actor
            _toggleActors[CounterType.Cpu] = Program.ChartActors.ActorOf(
                Props.Create(() => new ButtonToggleActor(_coordinatorActor, btnCpu,
                                                         CounterType.Cpu, false))
                .WithDispatcher("akka.actor.synchronized-dispatcher"));

            // MEMORY button toggle actor
            _toggleActors[CounterType.Memory] = Program.ChartActors.ActorOf(
                Props.Create(() => new ButtonToggleActor(_coordinatorActor, btnMemory,
                                                         CounterType.Memory, false))
                .WithDispatcher("akka.actor.synchronized-dispatcher"));

            // DISK button toggle actor
            _toggleActors[CounterType.Disk] = Program.ChartActors.ActorOf(
                Props.Create(() => new ButtonToggleActor(_coordinatorActor, btnDisk,
                                                         CounterType.Disk, false))
                .WithDispatcher("akka.actor.synchronized-dispatcher"));

            // Set the CPU toggle to ON so we start getting some data
            _toggleActors[CounterType.Cpu].Tell(new ButtonToggleActor.Toggle());
        }
Exemplo n.º 13
0
        /// <summary>
        /// Sends a message to the tail chopping router's collection of routees.
        /// </summary>
        /// <param name="message">The message to send.</param>
        /// <param name="sender">The sender of the message.</param>
        public override void Send(object message, ActorRef sender)
        {
            routees.Shuffle();
            var routeeIndex = new AtomicCounter(0);

            var completion  = new TaskCompletionSource <object>();
            var tokenSource = new CancellationTokenSource();
            var token       = tokenSource.Token;

            var scheduledSends = scheduler.Schedule(TimeSpan.Zero, interval, async() =>
            {
                var currentIndex = routeeIndex.GetAndIncrement();
                if (currentIndex < routees.Length)
                {
                    completion.TrySetResult(await((Task <object>)routees[currentIndex].Ask(message, null)));
                }
            }, token);

            var withinTimeout = scheduler.ScheduleOnce(within, () =>
            {
                completion.TrySetException(new TimeoutException(String.Format("Ask timed out on {0} after {1}", sender, within)));
            }, token);

            var request = completion.Task;

            completion.Task.ContinueWith((task) =>
            {
                tokenSource.Cancel(false);
            });

            request.PipeTo(sender);
        }
Exemplo n.º 14
0
 public void Setup(BenchmarkContext context)
 {
     _system                = ActorSystem.Create($"GetMailboxTypeSpec{Counter.GetAndIncrement()}");
     _messageDispatcher     = _system.Dispatchers.Lookup(EchoActor.Props.Dispatcher);
     _mailboxes             = new Mailboxes(_system);
     _createActorThroughput = context.GetCounter(CreateThroughputCounter);
 }
Exemplo n.º 15
0
        static ActorSystem LaunchFrontend(string port)
        {
            Console.WriteLine("Start - actorsystem for frontend node - port: {0}", port);

            var config =
                    ConfigurationFactory.ParseString("akka.remote.helios.tcp.port=" + port)
                    .WithFallback(ConfigurationFactory.ParseString("akka.cluster.roles = [frontend]"))
                        .WithFallback(_clusterConfig);

            var system = ActorSystem.Create("ClusterSystem", config);

            var frontend = system.ActorOf(Props.Create<FrontendActor>(port), "frontend");
            var interval = TimeSpan.FromSeconds(2);
            var timeout = TimeSpan.FromSeconds(5);
            var counter = new AtomicCounter();
            system.Scheduler.Advanced.ScheduleRepeatedly(interval, interval,
                () => frontend.Ask(new Messages.Request("request-" + counter.GetAndIncrement() + " from frontend node port " + port), timeout)
                    .ContinueWith( r =>
                    {
                        if (!r.IsCanceled)
                        {
                            Console.WriteLine(r.Result);
                            // Debug.WriteLine(r.Result);
                        }
                    }));

            Console.WriteLine("End - actorsystem for frontend node - port: {0}", port);

            return system;
        }
 public MongoDbCurrentEventsByPersistenceIdsSpec(ITestOutputHelper output, DatabaseFixture databaseFixture)
     : base(CreateSpecConfig(databaseFixture, Counter.GetAndIncrement()), "MongoDbCurrentEventsByPersistenceIdsSpec", output)
 {
     _output = output;
     output.WriteLine(databaseFixture.ConnectionString + Counter.Current);
     ReadJournal = Sys.ReadJournalFor <MongoDbReadJournal>(MongoDbReadJournal.Identifier);
 }
Exemplo n.º 17
0
        public void Required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue_forSynchronousPublisher()
        {
            var sent = new AtomicCounter(0);

            var publisher = new LamdaPublisher <int>(onSubscribe: subscriber =>
            {
                var started   = false;
                var cancelled = false;

                subscriber.OnSubscribe(new LamdaSubscription(onRequest: n =>
                {
                    if (!started)
                    {
                        started = true;
                        while (!cancelled)
                        {
                            subscriber.OnNext(sent.GetAndIncrement());
                        }
                    }
                }, onCancel: () => cancelled = true));
            });
            var verification = CustomPublisherVerification(publisher);

            verification.Required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue();

            // 11 due to the implementation of this particular TCK test (see impl)
            Assert.AreEqual(11, sent.Current);
        }
Exemplo n.º 18
0
        public void Setup(BenchmarkContext context)
        {
            _mailboxThroughput = context.GetCounter(MailboxCounterName);
            System             = ActorSystem.Create($"{GetType().Name}{Counter.GetAndIncrement()}");

            _targetActor = new CounterRef(_mailboxThroughput);
            System.EventStream.Subscribe(_targetActor, typeof(string));
        }
Exemplo n.º 19
0
 public void Setup(BenchmarkContext context)
 {
     _selectionOpCounter = context.GetCounter(ActorSelectionCounterName);
     System = ActorSystem.Create("MailboxThroughputSpecBase" + Counter.GetAndIncrement());
     _receiver = System.ActorOf(Props.Create(() => new BenchmarkActor(_selectionOpCounter, NumberOfMessages, _resetEvent)));
     _receiverActorPath = _receiver.Path;
     _oneMessageBenchmarkProps = Props.Create(() => new BenchmarkActor(_selectionOpCounter, 1, _resetEvent));
 }
 public void Setup(BenchmarkContext context)
 {
     _actorSystem   = ActorSystem.Create("MessageDispatcher" + Counter.GetAndIncrement(), RemoteHocon);
     _systemAddress = RARP.For(_actorSystem).Provider.DefaultAddress;
     _inboundMessageDispatcherCounter = context.GetCounter(MessageDispatcherThroughputCounterName);
     _message        = SerializedMessage.CreateBuilder().SetSerializerId(0).SetMessage(ByteString.CopyFromUtf8("foo")).Build();
     _dispatcher     = new DefaultMessageDispatcher(_actorSystem, RARP.For(_actorSystem).Provider, _actorSystem.Log);
     _targetActorRef = new BenchmarkActorRef(_inboundMessageDispatcherCounter, RARP.For(_actorSystem).Provider);
 }
Exemplo n.º 21
0
        public void Setup(BenchmarkContext context)
        {
            _mailboxThroughput = context.GetCounter(MailboxCounterName);
            System             = ActorSystem.Create($"{GetType().Name}{Counter.GetAndIncrement()}");

            _actorBasePatternMatchActorRef = System.ActorOf(BenchmarkActorBasePatternMatchActor.Props(_mailboxThroughput, MailboxMessageCount * 3, _resetEvent));
            _untypedActorRef = System.ActorOf(BenchmarkUntypedActor.Props(_mailboxThroughput, MailboxMessageCount * 3, _resetEvent));
            _receiveActorRef = System.ActorOf(BenchmarkReceiveActor.Props(_mailboxThroughput, MailboxMessageCount * 3, _resetEvent));
            _minimalActorRef = new BenchmarkMinimalActorRef(_mailboxThroughput, MailboxMessageCount, _resetEvent);
        }
Exemplo n.º 22
0
        protected Eventsourced()
        {
            LastSequenceNr = 0L;

            Extension            = Persistence.Instance.Apply(Context.System);
            _instanceId          = InstanceCounter.GetAndIncrement();
            _maxMessageBatchSize = Extension.Settings.Journal.MaxMessageBatchSize;
            _currentState        = RecoveryPending();
            _internalStash       = CreateStash();
        }
Exemplo n.º 23
0
        public void Should_not_be_able_to_add_jobs_after_shutdown()
        {
            var atomicCounter = new AtomicCounter(0);
            var fiber         = FiberFactory.CreateFiber(2);

            for (var i = 0; i < 1000; i++)
            {
                fiber.Add(() => atomicCounter.GetAndIncrement());
            }
            fiber.GracefulShutdown(TimeSpan.FromSeconds(1)).Wait(); //wait for the fiber to finish

            //try to increment the counter a bunch more times
            for (var i = 0; i < 1000; i++)
            {
                fiber.Add(() => atomicCounter.GetAndIncrement());
            }

            //value should be equal to its pre-shutdown value
            Assert.AreEqual(1000, atomicCounter.Current);
        }
Exemplo n.º 24
0
 public void Setup(BenchmarkContext context)
 {
     _actorSystem   = ActorSystem.Create("MessageDispatcher" + Counter.GetAndIncrement(), RemoteHocon);
     _systemAddress = RARP.For(_actorSystem).Provider.DefaultAddress;
     _inboundMessageDispatcherCounter = context.GetCounter(MessageDispatcherThroughputCounterName);
     _message = new SerializedMessage {
         SerializerId = 0, Message = ByteString.CopyFromUtf8("foo")
     };
     _dispatcher     = new DefaultMessageDispatcher(_actorSystem.AsInstanceOf <ExtendedActorSystem>(), RARP.For(_actorSystem).Provider, _actorSystem.Log);
     _targetActorRef = new BenchmarkActorRef(_inboundMessageDispatcherCounter, RARP.For(_actorSystem).Provider);
 }
Exemplo n.º 25
0
        public void Should_use_multiple_threads_to_process_queue()
        {
            var atomicCounter = new AtomicCounter(0);
            var fiber         = FiberFactory.CreateFiber(2);

            for (var i = 0; i < 1000; i++)
            {
                fiber.Add(() => atomicCounter.GetAndIncrement());
            }
            fiber.GracefulShutdown(TimeSpan.FromSeconds(1)).Wait(); //wait for the fiber to finish
            Assert.AreEqual(1000, atomicCounter.Current);
        }
Exemplo n.º 26
0
        public override Routee NewRoutee(Props routeeProps, IActorContext context)
        {
            _nodeAddrEnumerator.MoveNext();
            var name   = "c" + _childNameCounter.GetAndIncrement();
            var deploy = new Deploy(routeeProps.RouterConfig, new RemoteScope(_nodeAddrEnumerator.Current));


            var actorRef = context.AsInstanceOf <ActorCell>()
                           .AttachChild(Local.EnrichWithPoolDispatcher(routeeProps, context).WithDeploy(deploy), false, name);

            return(new ActorRefRoutee(actorRef));
        }
Exemplo n.º 27
0
 public ShortTimeoutLongTask(TestLatch latch, AtomicCounter counter)
 {
     StartWith(
         Loop(
             ReceiveAny(s => s.Equals("RUN"),
                 After(
                     Timeout(TimeSpan.FromMilliseconds(100),
                         Delay(5.Seconds(), Execute(_ => counter.GetAndIncrement())),
                         Execute(_ =>
                         {
                             counter.GetAndDecrement();
                             Sender.Tell("TIMEOUT");
                         })),
                     Execute(_ => latch.CountDown())))), null);
 }
Exemplo n.º 28
0
        /// <summary>
        /// Sends a message to the collection of routees.
        /// </summary>
        /// <param name="message">The message that is being sent.</param>
        /// <param name="sender">The actor sending the message.</param>
        public override void Send(object message, IActorRef sender)
        {
            _routees.Shuffle();
            var routeeIndex = new AtomicCounter(0);

            var completion = new TaskCompletionSource <object>();
            var cancelable = new Cancelable(_scheduler);

            completion.Task
            .ContinueWith(task => cancelable.Cancel(false));

            if (_routees.Length == 0)
            {
                completion.TrySetResult(NoRoutee);
            }
            else
            {
                _scheduler.Advanced.ScheduleRepeatedly(TimeSpan.Zero, _interval, async() =>
                {
                    var currentIndex = routeeIndex.GetAndIncrement();
                    if (currentIndex >= _routees.Length)
                    {
                        return;
                    }

                    try
                    {
                        completion.TrySetResult(
                            await(_routees[currentIndex].Ask(message, _within)).ConfigureAwait(false));
                    }
                    catch (AskTimeoutException)
                    {
                        completion.TrySetResult(
                            new Status.Failure(
                                new AskTimeoutException($"Ask timed out on {sender} after {_within}")));
                    }
                    catch (TaskCanceledException)
                    {
                        completion.TrySetResult(
                            new Status.Failure(
                                new AskTimeoutException($"Ask timed out on {sender} after {_within}")));
                    }
                }, cancelable);
            }

            completion.Task.PipeTo(sender);
        }
Exemplo n.º 29
0
            protected override void OnReceive(object message)
            {
                PatternMatch.Match(message)
                .With <string>(str =>
                {
                    if (str.Equals("bar"))
                    {
                        _barCount.GetAndIncrement();
                        _barLatch.CountDown();
                    }

                    if (str.Equals("foo"))
                    {
                        _fooLatch.CountDown();
                    }
                });
            }
Exemplo n.º 30
0
            public void Subscribe(ISubscriber <int> subscriber)
            => subscriber.OnSubscribe(new LamdaSubscription(onRequest: n =>
            {
                Action signalling = () =>
                {
                    for (var i = 0L; i < n; i++)
                    {
                        try
                        {
                            // shutdown cleanly in when the task is shutting down
                            if (_token.IsCancellationRequested)
                            {
                                return;
                            }

                            subscriber.OnNext((int)i);
                        }
                        catch (Exception ex)
                        {
                            // signal others to shut down
                            _source.Cancel();

                            if (ex is Latch.ExpectedOpenLatchException)
                            {
                                if (!_concurrentAccessCaused.CompareAndSet(false, true))
                                {
                                    throw new Exception("Concurrent access detected", ex);
                                }
                                // error signalled once already, stop more errors from propagating
                                return;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                };

                // must be guarded like this in case a Subscriber triggers request() synchronously from it's onNext()
                while (_startedSignallingThreads.GetAndIncrement() < MaxSignallingThreads && !_token.IsCancellationRequested)
                {
                    new Thread(() => signalling()).Start();
                }
            }));
Exemplo n.º 31
0
        static void LaunchFrontend(string[] args)
        {
            var port = args.Length > 0 ? args[0] : "0";
            var config =
                    ConfigurationFactory.ParseString("akka.remote.helios.tcp.port=" + port)
                    .WithFallback(ConfigurationFactory.ParseString("akka.cluster.roles = [frontend]"))
                        .WithFallback(_clusterConfig);

            var system = ActorSystem.Create("ClusterSystem", config);
            var backendRouter =
                system.ActorOf(
                    Props.Empty.WithRouter(new ClusterRouterGroup(new ConsistentHashingGroup("/user/backend"),
                        new ClusterRouterGroupSettings(10, false, "backend", ImmutableHashSet.Create("/user/backend")))));
            var frontend = system.ActorOf(Props.Create(() => new FrontendActor(backendRouter)), "frontend");
            var interval = TimeSpan.FromSeconds(12);
            var counter = new AtomicCounter();
            system.Scheduler.Advanced.ScheduleRepeatedly(interval, interval,() => frontend.Tell(new StartCommand("hello-" + counter.GetAndIncrement())));
        }
Exemplo n.º 32
0
        static void LaunchFrontend(string[] args)
        {
            var port = args.Length > 0 ? args[0] : "0";
            var config =
                    ConfigurationFactory.ParseString("akka.remote.helios.tcp.port=" + port)
                    .WithFallback(ConfigurationFactory.ParseString("akka.cluster.roles = [frontend]"))
                        .WithFallback(_clusterConfig);

            var system = ActorSystem.Create("ClusterSystem", config);

            var frontend = system.ActorOf(Props.Create<TransformationFrontend>(), "frontend");
            var interval = TimeSpan.FromSeconds(2);
            var timeout = TimeSpan.FromSeconds(5);
            var counter = new AtomicCounter();
            system.Scheduler.Advanced.ScheduleRepeatedly(interval, interval, 
                () => frontend.Ask(new TransformationMessages.TransformationJob("hello-" + counter.GetAndIncrement()), timeout)
                    .ContinueWith(
                        r => Console.WriteLine(r.Result)));
        }
Exemplo n.º 33
0
        /// <summary>
        ///     Performs all of the setup and initialization needed to get the Zipkin Kafka reporting engine up and running.
        /// </summary>
        /// <param name="options">The set of options for configuring timeouts and batch sizes.</param>
        /// <param name="actorSystem">
        ///     Optional. If using Akka.NET, you can hook your own <see cref="ActorSystem" /> into our
        ///     reporting engine.
        /// </param>
        /// <returns></returns>
        public static ZipkinKafkaSpanReporter Create(ZipkinKafkaReportingOptions options,
                                                     ActorSystem actorSystem = null)
        {
            // force this component to explode if the end-user screwed up the URI somehow.
            var weOwnActorSystem = false;

            if (actorSystem == null) // create our own ActorSystem if it doesn't already exist.
            {
                weOwnActorSystem = true;
                actorSystem      = ActorSystem.Create("pbzipkin",
                                                      options.DebugLogging ? DebugHocon : NormalHocon);
            }

            // spawn as a System actor, so in the event of being in a non-owned system our traces get shut down
            // only after all of the user-defined actors have terminated.
            var zipkinActor = actorSystem.AsInstanceOf <ExtendedActorSystem>().SystemActorOf(
                Props.Create(() => new KafkaReportingActor(options)),
                $"zipkin-tracing-kafka-{NameCounter.GetAndIncrement()}");

            return(new ZipkinKafkaSpanReporter(zipkinActor, weOwnActorSystem ? actorSystem : null));
        }