/// <summary>
        /// Sends the events.
        /// </summary>
        /// <param name="events">The events that need to be send.</param>
        /// <remarks>
        /// <para>
        /// The subclass must override this method to process the buffered events.
        /// </para>
        /// </remarks>
        protected override void SendBuffer(LoggingEvent[] events)
        {
            AppendBlobClient appendBlob = _cloudBlobContainer.GetAppendBlobClient(Filename(_directoryName));

            if (!appendBlob.Exists())
            {
                appendBlob.Create();
            }
            else
            {
                _lineFeed = Environment.NewLine;
            }

            Parallel.ForEach(events, ProcessEvent);
        }
Пример #2
0
        public AzureBlobsLogWriter(BlobContainerClient blobsContainerClient,
                                   string fileName,
                                   bool appendOpen = false)
        {
            fileName = AzureBlobsLogsInterface.PathFixer(fileName);
            _blobsContainerClient = blobsContainerClient;
            _logClient            = _blobsContainerClient.GetAppendBlobClient(fileName);
            ETag currentETag;

            if (_previousOpenAttempts.ContainsKey(fileName) && appendOpen)
            {
                // We've opened this blob before and want to be non-destructive. We don't need to CreateIfNotExists, which could be VERY slow.
                currentETag = _logClient.GetProperties().Value.ETag;
            }
            else
            {
                try
                {
                    // Create the file non-destructively if needed, guaranteeing write continuity on creation by grabbing the etag of the create, if needed
                    if (appendOpen)
                    {
                        var response = _logClient.CreateIfNotExists();
                        if (response != null)
                        {
                            currentETag = response.Value.ETag;
                        }
                        else
                        {
                            currentETag = _logClient.GetProperties().Value.ETag;
                        }
                    }
                    else
                    {
                        currentETag = _logClient.Create().Value.ETag;
                    }
                }
                catch { currentETag = _logClient.GetProperties().Value.ETag; }
            }
            // Try to grab the blob lease
            _leaseClient = _logClient.GetBlobLeaseClient();
            // The blob hasn't be touched since the last time. This is a candidate for breaking the lease.
            if (_previousOpenAttempts.ContainsKey(fileName) && (_previousOpenAttempts[fileName].ToString().Equals(currentETag.ToString())))
            {
                _previousOpenAttempts[fileName] = currentETag;
                // The blob hasn't been updated. Try to break the lease and reacquire
                var requestConditions = new BlobRequestConditions();
                requestConditions         = new BlobRequestConditions();
                requestConditions.IfMatch = currentETag;
                // If the condition fails in the break, it's because someone else managed to touch the file, so give up
                ETag newETag;
                try
                {
                    newETag = _leaseClient.Break(null, requestConditions).Value.ETag;
                }
                catch (Exception e) { newETag = currentETag; }
                var etagCondition = new RequestConditions();
                etagCondition.IfMatch = newETag;
                // If the condition fails, someone snuck in and grabbed the lock before we could. Give up.
                _curLease = _leaseClient.Acquire(TimeSpan.FromSeconds(-1), etagCondition).Value;
            }
            else
            {
                // Not a candidate for breaking the lease. Just try to acquire.
                _previousOpenAttempts[fileName] = currentETag;
                _curLease = _leaseClient.Acquire(TimeSpan.FromSeconds(-1)).Value;
            }

            _leaseCondition         = new AppendBlobRequestConditions();
            _leaseCondition.LeaseId = _curLease.LeaseId;
            // We got the lease! Set up thread to periodically touch the blob to prevent others from breaking the lease.
            _blobMetadata        = _logClient.GetProperties().Value.Metadata;
            _stopRelockThread    = false;
            _relockThreadStopped = false;
            _leaseRenewThread    = new Thread(() =>
            {
                while (!_stopRelockThread)
                {
                    Thread.Sleep(100);
                    var response = _logClient.SetMetadata(_blobMetadata, _leaseCondition);
                }
                _relockThreadStopped = true;
            })
            {
                IsBackground = true
            };
            _leaseRenewThread.Start();
            _bytesToSend = new MemoryStream();
            Debug.Assert(_logClient.Exists());
        }