/// <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); }
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); }
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); }
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); }
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); }
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)); }
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); }
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()); }