public void TestExceptionRender() { try { // Throw the exception to give it a target site. throw new InvalidOperationException("Test Exception"); } catch (InvalidOperationException e) { var logEvent = new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Error, e, new MessageTemplate(new MessageTemplateToken[0]), new LogEventProperty[0]); var result = LogglySink.EventToJson(logEvent); var json = JsonConvert.DeserializeObject <dynamic>(result); (json["Exception"]["TargetSite"] as object).Should().BeNull(); #if NET46 (json["Exception"]["ClassName"].Value as string).Should().Be("System.InvalidOperationException"); #else (json["Exception"]["Type"].Value as string).Should().Be("System.InvalidOperationException"); #endif } }
/// <summary> /// Adds a sink that writes log events to the Loggly.com webservice. Properties are being send as data and the level is used as category. /// </summary> /// <param name="loggerConfiguration">The logger configuration.</param> /// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param> /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param> /// <param name="batchPostingLimit">The maximum number of events to post in a single batch.</param> /// <param name="period">The time to wait between checking for event batches.</param> /// <param name="bufferBaseFilename">Path for a set of files that will be used to buffer events until they /// can be successfully transmitted across the network. Individual files will be created using the /// pattern <paramref name="bufferBaseFilename"/>-{Date}.json.</param> /// <param name="bufferFileSizeLimitBytes">The maximum size, in bytes, to which the buffer /// log file for a specific date will be allowed to grow. By default no limit will be applied.</param> /// <param name="eventBodyLimitBytes">The maximum size, in bytes, that the JSON representation of /// an event may take before it is dropped rather than being sent to the Loggly server. Specify null for no limit. /// The default is 1 MB.</param> /// <param name="controlLevelSwitch">If provided, the switch will be updated based on the Seq server's level setting /// for the corresponding API key. Passing the same key to MinimumLevel.ControlledBy() will make the whole pipeline /// dynamically controlled. Do not specify <paramref name="restrictedToMinimumLevel"/> with this setting.</param> /// <param name="retainedInvalidPayloadsLimitBytes">A soft limit for the number of bytes to use for storing failed requests. /// The limit is soft in that it can be exceeded by any single error payload, but in that case only that single error /// payload will be retained.</param> /// <param name="retainedFileCountLimit">number of files to retain for the buffer. If defined, this also controls which records /// <param name="logglyConfig">Used to configure underlying LogglyClient programmaticaly. Otherwise use app.Config.</param> /// <param name="includes">Decides if the sink should include specific properties in the log message</param> /// in the buffer get sent to the remote Loggly instance</param> /// <returns>Logger configuration, allowing configuration to continue.</returns> /// <exception cref="ArgumentNullException">A required parameter is null.</exception> public static LoggerConfiguration Loggly( this LoggerSinkConfiguration loggerConfiguration, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = LogglySink.DefaultBatchPostingLimit, TimeSpan?period = null, IFormatProvider formatProvider = null, string bufferBaseFilename = null, long?bufferFileSizeLimitBytes = null, long?eventBodyLimitBytes = 1024 * 1024, LoggingLevelSwitch controlLevelSwitch = null, long?retainedInvalidPayloadsLimitBytes = null, int?retainedFileCountLimit = null, LogglyConfiguration logglyConfig = null, LogIncludes includes = null) { if (loggerConfiguration == null) { throw new ArgumentNullException(nameof(loggerConfiguration)); } if (bufferFileSizeLimitBytes.HasValue && bufferFileSizeLimitBytes < 0) { throw new ArgumentOutOfRangeException(nameof(bufferFileSizeLimitBytes), "Negative value provided; file size limit must be non-negative."); } var defaultedPeriod = period ?? LogglySink.DefaultPeriod; ILogEventSink sink; if (bufferBaseFilename == null) { sink = new LogglySink(formatProvider, batchPostingLimit, defaultedPeriod, logglyConfig, includes); } else { sink = new DurableLogglySink( bufferBaseFilename, batchPostingLimit, defaultedPeriod, bufferFileSizeLimitBytes, eventBodyLimitBytes, controlLevelSwitch, retainedInvalidPayloadsLimitBytes, retainedFileCountLimit, formatProvider, logglyConfig, includes); } return(loggerConfiguration.Sink(sink, restrictedToMinimumLevel)); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="LogglySink" />. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="instanceName">The name of the instance originating the entries.</param> /// <param name="connectionString">The endpoint address for the Loggly Service.</param> /// <param name="customerToken">The loggly customerToken that must be part of the Url.</param> /// <param name="tag">The tag used in loggly updates. Default is to use the instanceName.</param> /// <param name="flattenPayload">Flatten the payload if you want the parameters serialized.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval" />.</param> /// <param name="onCompletedTimeout">Defines a timeout interval for when flushing the entries after an <see cref="LogglySink.OnCompleted" /> call is received and before disposing the sink.</param> /// <param name="bufferingCount">Buffering count to send entries sot Loggly. Default value is <see cref="Buffering.DefaultBufferingCount" /></param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered while it's sending to Loggly before the sink starts dropping entries. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose" /> on /// the <see cref="System.Diagnostics.Tracing.EventListener" /> will block until all the entries are flushed or the interval elapses. /// If <see langword="null" /> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <returns> /// A subscription to the sink that can be disposed to unsubscribe the sink and dispose it, or to get access to the sink instance. /// </returns> public static SinkSubscription<LogglySink> LogToLoggly(this IObservable<EventEntry> eventStream, string instanceName, string connectionString, string customerToken, string tag, bool flattenPayload = true, TimeSpan? bufferingInterval = null, TimeSpan? onCompletedTimeout = null, int bufferingCount = Buffering.DefaultBufferingCount, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new LogglySink(instanceName, connectionString, customerToken, tag, flattenPayload, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan); var subscription = eventStream.Subscribe(sink); return new SinkSubscription<LogglySink>(subscription, sink); }
public void TestAddIfContains() { var dictionary = new Dictionary <string, string>() { { "hello", "world" } }; LogglySink.AddIfNotContains(dictionary, "hello", "another world"); dictionary.ContainsKey("hello").Should().BeTrue(); dictionary["hello"].Should().Be("world"); LogglySink.AddIfNotContains(dictionary, "newkey", "orange"); dictionary.ContainsKey("newkey").Should().BeTrue(); dictionary["newkey"].Should().Be("orange"); }
public void TestAddIfContains() { var dictionary = new Dictionary <string, string>() { { "hello", "world" } }; LogglySink.AddIfNotContains(dictionary, "hello", "another world"); Assert.IsTrue(dictionary.ContainsKey("hello")); Assert.AreEqual(dictionary["hello"], "world"); LogglySink.AddIfNotContains(dictionary, "newkey", "orange"); Assert.IsTrue(dictionary.ContainsKey("newkey")); Assert.AreEqual(dictionary["newkey"], "orange"); }
public void TestRender() { var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Debug, null, new MessageTemplate(Enumerable.Empty <MessageTemplateToken>()), new [] { new LogEventProperty("test1", new ScalarValue("answer1")), new LogEventProperty("0", new ScalarValue("this should be missing")), new LogEventProperty("key", new ScalarValue("value")) }); var result = LogglySink.EventToJson(logEvent); var json = JsonConvert.DeserializeObject <dynamic>(result); (json["test1"].Value as string).Should().Be("answer1"); bool hasZero = (json["0"] == null); hasZero.Should().Be(true); (json["key"].Value as string).Should().Be("value"); }
public void PackageContentsTest() { var jsons = new[] { "{'fruit': 'orange'}", "{'fruit': 'apple'}", "{'fruit': 'banana'}", }.ToList(); var noDiagContent = LogglySink.PackageContent(jsons, Encoding.UTF8.GetByteCount(string.Join("\n", jsons)), 0, false); var stringContent = LogglySink.PackageContent(jsons, Encoding.UTF8.GetByteCount(string.Join("\n", jsons)), 0, true); stringContent.Should().NotBeNull(); noDiagContent.Should().NotBeNull(); var result = stringContent.ReadAsStringAsync().GetAwaiter().GetResult(); var resultNoDiag = noDiagContent.ReadAsStringAsync().GetAwaiter().GetResult(); result.Split('\n').Count().Should().Be(4); resultNoDiag.Split('\n').Count().Should().Be(3); }
public void IncludeDiagnostics_WhenDisbled_DoesNotIncludeDiagnosticsEvent() { var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Debug, null, new MessageTemplate(Enumerable.Empty <MessageTemplateToken>()), new[] { new LogEventProperty("Field1", new ScalarValue("Value1")), }); var result = new List <string> { LogglySink.EventToJson(logEvent) }; var package = LogglySink.PackageContent(result, 1024, 5); var packageStringTask = package.ReadAsStringAsync(); packageStringTask.Wait(); var packageString = packageStringTask.Result; (result.Count == 1).Should().BeTrue(); packageString.Contains("LogglyDiagnostics").Should().BeFalse(); }
public void PackageContentsTest() { var jsons = new[] { "{'fruit': 'orange'}", "{'fruit': 'apple'}", "{'fruit': 'banana'}", }.ToList(); //changing to remove diagnostics parameter to show that the default version is false, and that this test ensures backwards API compatibility. Don't add it back w/o cutting major version! var noDiagContent = LogglySink.PackageContent(jsons, Encoding.UTF8.GetByteCount(string.Join("\n", jsons)), 0); var stringContent = LogglySink.PackageContent(jsons, Encoding.UTF8.GetByteCount(string.Join("\n", jsons)), 0, true); stringContent.Should().NotBeNull(); noDiagContent.Should().NotBeNull(); var result = stringContent.ReadAsStringAsync().GetAwaiter().GetResult(); var resultNoDiag = noDiagContent.ReadAsStringAsync().GetAwaiter().GetResult(); result.Split('\n').Length.Should().Be(4); resultNoDiag.Split('\n').Length.Should().Be(3); }