/// <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); }
/// <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)); }
/// <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(ICloudBlob blob, CancellationToken cancellationToken) { List <StorageAnalyticsLogEntry> entries = new List <StorageAnalyticsLogEntry>(); using (TextReader tr = new StreamReader(await blob.OpenReadAsync(cancellationToken))) { for (int lineNumber = 1; ; lineNumber++) { cancellationToken.ThrowIfCancellationRequested(); string line = await tr.ReadLineAsync(); 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); throw new FormatException(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); throw new FormatException(message); } entries.Add(entry); } } } return(entries); }
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; }
/// <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; }