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);
        }
Пример #4
0
        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");
        }
Пример #5
0
        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");
        }
Пример #6
0
        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");
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }