예제 #1
0
        public Logger(params AbstractWriter[] writers)
        {
            Contract.Requires(writers != null);
            Contract.Requires(writers.Length >= 1);

            cts = new CancellationTokenSource();

            bufferBlocks = new List <BufferBlock <LogItem> >();
            writerBlocks = new List <ActionBlock <LogItem[]> >();

            foreach (var writer in writers)
            {
                writer.Setup();

                var bufferBlock = new BufferBlock <LogItem>(
                    new DataflowBlockOptions()
                {
                    CancellationToken = cts.Token
                });

                var batchBlock = new BatchBlock <LogItem>(
                    writer.BatchSize,
                    new GroupingDataflowBlockOptions()
                {
                    Greedy            = true,
                    CancellationToken = cts.Token
                });

                var timer = new Timer(state => batchBlock.TriggerBatch());

                var timeoutBlock = new TransformBlock <LogItem, LogItem>(
                    value =>
                {
                    timer.Change((int)writer.Timeout.TotalMilliseconds,
                                 Timeout.Infinite);

                    return(value);
                },
                    new ExecutionDataflowBlockOptions()
                {
                    CancellationToken         = cts.Token,
                    SingleProducerConstrained = true
                });

                var writerBlock = new ActionBlock <LogItem[]>(
                    async logItems =>
                {
                    await writer.WriteAsync(logItems);
                },
                    new ExecutionDataflowBlockOptions()
                {
                    MaxDegreeOfParallelism    = 1,
                    CancellationToken         = cts.Token,
                    SingleProducerConstrained = true
                });

                writerBlock.Completion.ContinueWith(task => writer.Teardown());

                timeoutBlock.LinkTo(batchBlock);
                bufferBlock.LinkTo(timeoutBlock);
                batchBlock.LinkTo(writerBlock);

                writerBlocks.Add(writerBlock);
                bufferBlocks.Add(bufferBlock);

                timeoutBlock.HandleCompletion(batchBlock);
                bufferBlock.HandleCompletion(timeoutBlock);
                batchBlock.HandleCompletion(writerBlock);
            }
        }