/// <summary>
        /// A factory method attempting to create an instance of entry out of array of fields as extracted from
        /// a single line in Storage Analytics Log file.
        /// </summary>
        /// <param name="fields">
        /// Array of string values of fields as extracted from a single line in a log file.
        /// It must not be null and should contain exactly 30 items.
        /// </param>
        /// <returns>A valid instance of <see cref="StorageAnalyticsLogEntry"/> if given fields match expected format,
        /// or null otherwise.</returns>
        public static StorageAnalyticsLogEntry TryParse(string[] fields)
        {
            Debug.Assert(fields != null);
            Debug.Assert(fields.Length == (int)StorageAnalyticsLogColumnId.LastColumn + 1);

            var entry = new StorageAnalyticsLogEntry();

            DateTime requestStartTime;

            if (!DateTime.TryParseExact(fields[(int)StorageAnalyticsLogColumnId.RequestStartTime], "o",
                                        CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out requestStartTime))
            {
                return(null);
            }
            entry.RequestStartTime = requestStartTime;

            StorageServiceType serviceType;

            if (Enum.TryParse <StorageServiceType>(fields[(int)StorageAnalyticsLogColumnId.ServiceType], true,
                                                   out serviceType))
            {
                entry.ServiceType = serviceType;

                StorageServiceOperationType operationType;
                if (Enum.TryParse <StorageServiceOperationType>(fields[(int)StorageAnalyticsLogColumnId.OperationType],
                                                                out operationType))
                {
                    entry.OperationType = operationType;
                }

                entry.RequestedObjectKey = fields[(int)StorageAnalyticsLogColumnId.RequestedObjectKey];
            }

            return(entry);
        }
        public void TryParseLogEntry_IfMalformedInput_ReturnsNull(string line)
        {
            StorageAnalyticsLogParser parser = new StorageAnalyticsLogParser(NullLogger <BlobListener> .Instance);

            StorageAnalyticsLogEntry entry = parser.TryParseLogEntry(line);

            Assert.Null(entry);
        }
示例#3
0
        public void ToBlobPath_IfMalformedObjectKey_ReturnsNull(string requestedObjectKey)
        {
            StorageAnalyticsLogEntry entry = CreateEntry("2014-09-08T18:44:18.9681025Z", StorageServiceOperationType.PutBlob, StorageServiceType.Blob, requestedObjectKey);

            BlobPath blobPath = entry.ToBlobPath();

            Assert.Null(blobPath);
        }
示例#4
0
        public void TryParse_IfMalformedStartTime_ReturnsNull()
        {
            string[] fields = CreateArray("<INVALID>", "PutBlob", "blob", @"/storagesample/sample-container/""0x8D199A96CB71468""/sample-blob.txt");

            StorageAnalyticsLogEntry entry = StorageAnalyticsLogEntry.TryParse(fields);

            Assert.Null(entry);
        }
        public void TryParseLogEntry_IfValidLogEnry_ReturnsEntryInstance(string line, string blobPath)
        {
            StorageAnalyticsLogParser parser = new StorageAnalyticsLogParser(NullLogger <BlobListener> .Instance);

            StorageAnalyticsLogEntry entry = parser.TryParseLogEntry(line);

            Assert.NotNull(entry);
            Assert.AreEqual(blobPath, entry.RequestedObjectKey);
        }
示例#6
0
        public void TryParse_IfUnrecognizedOperation_IgnoresIt()
        {
            string[] fields = CreateArray("2014-09-08T18:44:18.9681025Z", "INVALID", "blob", @"/storagesample/sample-container/""0x8D199A96CB71468""/sample-blob.txt");

            StorageAnalyticsLogEntry entry = StorageAnalyticsLogEntry.TryParse(fields);

            Assert.NotNull(entry);
            Assert.False(entry.OperationType.HasValue);
        }
示例#7
0
        private static StorageAnalyticsLogEntry CreateEntry(string requestStartTime, StorageServiceOperationType operationType, StorageServiceType serviceType, string requestedObjectKey)
        {
            StorageAnalyticsLogEntry entry = new StorageAnalyticsLogEntry();

            entry.RequestStartTime   = DateTime.Parse(requestStartTime, CultureInfo.InvariantCulture);
            entry.OperationType      = operationType;
            entry.ServiceType        = serviceType;
            entry.RequestedObjectKey = requestedObjectKey;

            return(entry);
        }
示例#8
0
        public void ToBlobPath_IfValidBlobOperationEntry_ReturnsBlobPath(object operationType, object serviceType, string requestedObjectKey, string expectedContainerName, string expectedBlobName)
        {
            StorageAnalyticsLogEntry entry = CreateEntry(
                "2014-09-08T18:44:18.9681025Z",
                (StorageServiceOperationType)operationType,
                (StorageServiceType)serviceType, requestedObjectKey);

            BlobPath blobPath = entry.ToBlobPath();

            Assert.NotNull(blobPath);
            Assert.AreEqual(expectedContainerName, blobPath.ContainerName);
            Assert.AreEqual(expectedBlobName, blobPath.BlobName);
        }
        /// <summary>
        /// Given a log file (as a blob), parses it and return a collection of log entries matching version 1.0
        /// of the Storage Analytics Log Format.
        /// </summary>
        /// <param name="blob">Object representing a cloud blob with Storage Analytics log content.</param>
        /// <param name="cancellationToken">A token to monitor for cancellation request.</param>
        /// <returns>Collection of successfully parsed log entries.</returns>
        /// <exception cref="FormatException">If unable to parse a line in given log.</exception>
        /// <seealso cref="StorageAnalyticsLogEntry"/>
        /// <remarks>
        /// The method scans log file lines one at a time.
        /// First it attempts to detect a line format version and throws an exception if failed to do so.
        /// It skips all lines with version different than supported one, i.e. 1.0.
        /// Then it calls TryParseLogEntry to create a log entry out of every line of supported version and throws
        /// an exception if the parse method returns null.
        /// </remarks>
        public async Task <IEnumerable <StorageAnalyticsLogEntry> > ParseLogAsync(BlobBaseClient blob,
                                                                                  CancellationToken cancellationToken)
        {
            List <StorageAnalyticsLogEntry> entries = new List <StorageAnalyticsLogEntry>();

            using (Stream content = (await blob.DownloadAsync(cancellationToken).ConfigureAwait(false)).Value.Content)
            {
                using (TextReader tr = new StreamReader(content))
                {
                    for (int lineNumber = 1; ; lineNumber++)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        string line = await tr.ReadLineAsync().ConfigureAwait(false);

                        if (line == null)
                        {
                            break;
                        }

                        Version version = TryParseVersion(line);
                        if (version == null)
                        {
                            string message = String.Format(CultureInfo.CurrentCulture,
                                                           "Unable to detect a version of log entry on line {1} of Storage Analytics log file '{0}'.",
                                                           blob.Name, lineNumber);

                            _logger.LogWarning(message);
                        }

                        if (version == supportedVersion)
                        {
                            StorageAnalyticsLogEntry entry = TryParseLogEntry(line);
                            if (entry == null)
                            {
                                string message = String.Format(CultureInfo.CurrentCulture,
                                                               "Unable to parse the log entry on line {1} of Storage Analytics log file '{0}'.",
                                                               blob.Name, lineNumber);

                                _logger.LogWarning(message);
                            }

                            entries.Add(entry);
                        }
                    }
                }
            }

            return(entries);
        }
        /// <summary>
        /// Attempts to parse a single line of Storage Analytics Log file using Regex matches.
        /// </summary>
        /// <param name="line">A line as extracted from a Storage Analytics Log file. Must not be null or empty.</param>
        /// <returns>Parsed instance of <see cref="StorageAnalyticsLogEntry"/> if the given line matches expected format
        /// of the Storage Analytics Log v1.0, or null otherwise.</returns>
        public StorageAnalyticsLogEntry TryParseLogEntry(string line)
        {
            Debug.Assert(line != null);

            var capturedFields =
                from Match m in _compiledRegex.Matches(line)
                select WebUtility.HtmlDecode(m.Groups[1].Value);

            string[] fieldsArray = capturedFields.ToArray();

            if (fieldsArray.Length != ColumnCount)
            {
                return(null);
            }

            return(StorageAnalyticsLogEntry.TryParse(fieldsArray));
        }
示例#11
0
        public void TryParse_IfValidFieldValues_ReturnsLogEntryInstance()
        {
            string requestStartTime   = "2014-09-08T18:44:18.9681025Z";
            string operationType      = "PutBlob";
            string serviceType        = "blob";
            string requestedObjectKey = @"/storagesample/sample-container/""0x8D199A96CB71468""/sample-blob.txt";

            string[] fields = CreateArray(requestStartTime, operationType, serviceType, requestedObjectKey);

            StorageAnalyticsLogEntry entry = StorageAnalyticsLogEntry.TryParse(fields);

            Assert.NotNull(entry);
            DateTime expectedRequestStartTime = new DateTime(635457986589681025L, DateTimeKind.Utc);

            Assert.AreEqual(expectedRequestStartTime, entry.RequestStartTime);
            Assert.AreEqual(DateTimeKind.Utc, entry.RequestStartTime.Kind);
            Assert.AreEqual(StorageServiceOperationType.PutBlob, entry.OperationType);
            Assert.AreEqual(StorageServiceType.Blob, entry.ServiceType);
            Assert.AreEqual(requestedObjectKey, entry.RequestedObjectKey);
        }
示例#12
0
        public void ToBlobPath_IfMalformedUri_PropogatesUriFormatException(string requestedObjectKey)
        {
            StorageAnalyticsLogEntry entry = CreateEntry("2014-09-08T18:44:18.9681025Z", StorageServiceOperationType.PutBlob, StorageServiceType.Blob, requestedObjectKey);

            Assert.Throws <UriFormatException>(() => entry.ToBlobPath());
        }