public async Task ReadNoTable() { ILogReader reader = LogFactory.NewReader(this); Assert.Empty(_tables); // no tables yet. var segmentDef = await reader.GetFunctionDefinitionsAsync(null, null); Assert.Empty(segmentDef.Results); var segmentTimeline = await reader.GetActiveContainerTimelineAsync(DateTime.MinValue, DateTime.MaxValue, null); Assert.Empty(segmentTimeline.Results); var segmentRecent = await reader.GetRecentFunctionInstancesAsync(new RecentFunctionQuery { FunctionId = FunctionId.Parse("abc"), Start = DateTime.MinValue, End = DateTime.MaxValue, MaximumResults = 1000 }, null); Assert.Empty(segmentRecent.Results); var item = await reader.LookupFunctionInstanceAsync(Guid.NewGuid()); Assert.Null(item); }
public async Task ReadNoTable() { var table = GetNewLoggingTable(); ILogReader reader = LogFactory.NewReader(table); Assert.False(table.Exists()); var segmentDef = await reader.GetFunctionDefinitionsAsync(null); Assert.Equal(0, segmentDef.Results.Length); var segmentTimeline = await reader.GetActiveContainerTimelineAsync(DateTime.MinValue, DateTime.MaxValue, null); Assert.Equal(0, segmentTimeline.Results.Length); var segmentRecent = await reader.GetRecentFunctionInstancesAsync(new RecentFunctionQuery { FunctionName = "abc", Start = DateTime.MinValue, End = DateTime.MaxValue, MaximumResults = 1000 }, null); Assert.Equal(0, segmentRecent.Results.Length); var item = await reader.LookupFunctionInstanceAsync(Guid.NewGuid()); Assert.Null(item); }
private async Task <FunctionInstanceSnapshot> LookupAsync(Guid id) { var t = await _reader.LookupFunctionInstanceAsync(id); if (t == null) { return(null); } return(t.ConvertToSnapshot()); }
public async Task LargeWritesWithParametersAreTruncated() { ILogWriter writer = LogFactory.NewWriter(defaultHost, "c1", this); ILogReader reader = LogFactory.NewReader(this); // Max table request size is 4mb. That gives roughly 40kb per row. string largeValue = new string('x', 100 * 1000); string truncatedPrefix = largeValue.Substring(0, 100); List <Guid> functionIds = new List <Guid>(); for (int i = 0; i < 90; i++) { var functionId = Guid.NewGuid(); functionIds.Add(functionId); var now = DateTime.UtcNow; var item = new FunctionInstanceLogItem { FunctionInstanceId = functionId, Arguments = new Dictionary <string, string>(), StartTime = now, EndTime = now.AddSeconds(3), FunctionName = "tst2", LogOutput = largeValue, ErrorDetails = largeValue, TriggerReason = largeValue }; for (int j = 0; j < 1000; j++) { string paramName = "p" + j.ToString(); item.Arguments[paramName] = largeValue; } await writer.AddAsync(item); } // If we didn't truncate, then this would throw with a 413 "too large" exception. await writer.FlushAsync(); // If we got here without an exception, then we successfully truncated the rows. // Lookup and verify var instance = await reader.LookupFunctionInstanceAsync(functionIds[0]); Assert.True(instance.LogOutput.StartsWith(truncatedPrefix)); Assert.True(instance.ErrorDetails.StartsWith(truncatedPrefix)); Assert.True(instance.TriggerReason.StartsWith(truncatedPrefix)); Assert.Equal(0, instance.Arguments.Count); // totally truncated. }
public async Task DifferentHosts() { // 1a & 1b are 2 instances (different machines) of the same host. They share. // 2 is a separate host. string host1 = "h1-1"; // includes an tricky character that requires escaping. string host2 = "h22"; ILogWriter writer1a = LogFactory.NewWriter(host1, "c1", this); ILogWriter writer1b = LogFactory.NewWriter(host1, "c2", this); ILogWriter writer2 = LogFactory.NewWriter(host2, "c3", this); ILogReader reader1 = LogFactory.NewReader(this); ILogReader reader2 = LogFactory.NewReader(this); string Func1 = "alpha"; var f1a = await QuickWriteAsync(writer1a, Func1); // first var f1b = await QuickWriteAsync(writer1b, Func1); var f1aa = await QuickWriteAsync(writer1a, Func1); // second write var f2 = await QuickWriteAsync(writer2, Func1); // Verify readers // Function definitions. Search all hosts if no host specified { var segment = await reader1.GetFunctionDefinitionsAsync(null, null); Assert.Equal(2, segment.Results.Length); var allDefinitions = segment.Results; segment = await reader1.GetFunctionDefinitionsAsync(host1, null); Assert.Single(segment.Results); var host1Defs = segment.Results[0]; Assert.Equal(Func1, host1Defs.Name); Assert.Equal(FunctionId.Build(host1, Func1), host1Defs.FunctionId); segment = await reader1.GetFunctionDefinitionsAsync(host2, null); Assert.Single(segment.Results); var host2Defs = segment.Results[0]; Assert.Equal(Func1, host2Defs.Name); Assert.Equal(FunctionId.Build(host2, Func1), host2Defs.FunctionId); Assert.Equal(Func1, allDefinitions[0].Name); Assert.Equal(Func1, allDefinitions[1].Name); Assert.Equal(host1Defs.FunctionId, allDefinitions[0].FunctionId); Assert.Equal(host2Defs.FunctionId, allDefinitions[1].FunctionId); } // Recent list { var segment = await reader1.GetRecentFunctionInstancesAsync(new RecentFunctionQuery { FunctionId = FunctionId.Build(host1, Func1), End = DateTime.MaxValue, }, null); Guid[] guids = Array.ConvertAll(segment.Results, x => x.FunctionInstanceId); Assert.Equal(3, guids.Length); // Only include host 1 Assert.Equal(f1a, guids[2]); // reverse chronological Assert.Equal(f1b, guids[1]); Assert.Equal(f1aa, guids[0]); } // cross polination. Lookup across hosts. { var entry = await reader2.LookupFunctionInstanceAsync(f1a); Assert.NotNull(entry); Assert.Equal(entry.FunctionName, Func1); } }
public async Task TimeRangeAcrossEpochs() { // Make some very precise writes and verify we read exactly what we'd expect. ILogWriter writer = LogFactory.NewWriter(defaultHost, "c1", this); ILogReader reader = LogFactory.NewReader(this); // Time that functios are called. DateTime[] times = new DateTime[] { // Epoch 37 new DateTime(2012, 3, 6, 10, 11, 20, DateTimeKind.Utc), new DateTime(2012, 3, 7, 10, 11, 20, DateTimeKind.Utc), // consecutive Epoch 38 new DateTime(2012, 4, 8, 10, 11, 20, DateTimeKind.Utc), // Skip to Epoch 41 new DateTime(2012, 7, 9, 10, 11, 20, DateTimeKind.Utc) }; var logs = Array.ConvertAll(times, time => new FunctionInstanceLogItem { FunctionInstanceId = Guid.NewGuid(), FunctionName = commonFuncName1, StartTime = time, }); var tasks = Array.ConvertAll(logs, log => WriteAsync(writer, log)); await Task.WhenAll(tasks); await writer.FlushAsync(); // Test point lookups for individual function instances. foreach (var log in logs) { var entry = await reader.LookupFunctionInstanceAsync(log.FunctionInstanceId); Assert.NotNull(entry); Assert.Equal(log.FunctionInstanceId, entry.FunctionInstanceId); Assert.Equal(log.FunctionName, entry.FunctionName); Assert.Equal(log.StartTime, entry.StartTime); Assert.Equal(log.EndTime, entry.EndTime); } // Try various combinations. await Verify(reader, DateTime.MinValue, DateTime.MaxValue, logs[3], logs[2], logs[1], logs[0]); // Infinite range, includes all. // Various combinations of straddling an epoch boundary await Verify(reader, Before(times[1]), After(times[2]), logs[2], logs[1]); await Verify(reader, Before(times[1]), Before(times[2]), logs[1]); await Verify(reader, After(times[1]), Before(times[2])); // Skipping over an empty epoch await Verify(reader, Before(times[1]), Before(times[3]), logs[2], logs[1]); // Now... delete the middle table; and verify the other data is still there. ILogTableProvider provider = this; var table = provider.GetTable("201204"); Assert.True(await table.ExistsAsync()); await table.DeleteAsync(); await Verify(reader, DateTime.MinValue, DateTime.MaxValue, logs[3], logs[1], logs[0]); // Infinite range, includes all. // function instance entry from the table we deleted is now missing. var entry2 = await reader.LookupFunctionInstanceAsync(logs[2].FunctionInstanceId); Assert.Null(entry2); }