How can I see what my reactive extensions query is doing?

前端 未结 2 1619
旧时难觅i
旧时难觅i 2020-11-27 14:09

I\'m writing a complex Reactive Extensions query with lots of operators. How can I see what\'s going on?

I\'m asking and answering this as it comes up a fair bit and

2条回答
  •  谎友^
    谎友^ (楼主)
    2020-11-27 14:44

    Another three years have passed, and I'm still using your idea. My version has now evolved as follows:

    • Overload for choice of logging destination
    • Log number of subscriptions
    • Log 'downstream' exceptions from bad subscribers.

    The code:

    public static IObservable Spy(this IObservable source, string opName = null)
    {
        return Spy(source, opName, Console.WriteLine);
    }
    
    public static IObservable Spy(this IObservable source, string opName, 
                                                                  Action logger)
    {
        opName = opName ?? "IObservable";
        logger($"{opName}: Observable obtained on Thread: {Thread.CurrentThread.ManagedThreadId}");
    
        var count = 0;
        return Observable.Create(obs =>
        {
            logger($"{opName}: Subscribed to on Thread: {Thread.CurrentThread.ManagedThreadId}");
            try
            {
                var subscription = source
                    .Do(x => logger($"{opName}: OnNext({x}) on Thread: {Thread.CurrentThread.ManagedThreadId}"),
                        ex => logger($"{opName}: OnError({ex}) on Thread: {Thread.CurrentThread.ManagedThreadId}"),
                        () => logger($"{opName}: OnCompleted() on Thread: {Thread.CurrentThread.ManagedThreadId}")
                    )
                    .Subscribe(t =>
                    {
                        try
                        {
                            obs.OnNext(t);
                        }
                        catch(Exception ex)
                        {
                            logger($"{opName}: Downstream exception ({ex}) on Thread: {Thread.CurrentThread.ManagedThreadId}");
                            throw;
                        }
                    }, obs.OnError, obs.OnCompleted);
    
                return new CompositeDisposable(
                        Disposable.Create(() => logger($"{opName}: Dispose (Unsubscribe or Observable finished) on Thread: {Thread.CurrentThread.ManagedThreadId}")),
                        subscription,
                        Disposable.Create(() => Interlocked.Decrement(ref count)),
                        Disposable.Create(() => logger($"{opName}: Dispose (Unsubscribe or Observable finished) completed, {count} subscriptions"))
                    );
            }
            finally
            {
                Interlocked.Increment(ref count);
                logger($"{opName}: Subscription completed, {count} subscriptions.");
            }
        });
    }
    

提交回复
热议问题