public void MessageOverTheLimitIsCut()
        {
            var config = new Config
            {
                // there is over 150 bytes of fixed JSON unrelated to "message" value (hostname, timestamp, logger name, ...)
                // so this value should leave part of the message and cut the rest.
                MaxEventSizeBytes = 200
            };
            var formatter = new LogdnaFormatter(config);
            var evt       = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                "logger",
                Level.Info,
                null,
                null);

            var originalMessage =
                "This is very long test log message that will be cut down. This message will be shorter in result " +
                "event because it will be cut to fit into max event limit. Actual result size can vary based on values " +
                "such as hostname, thread name, process name. It's therefore not possible to check against fixed value, " +
                "the test just needs to check that result message is shorter than this one and that the whole event size " +
                "fits into max allowed size";

            var result = formatter.ToJson(evt, originalMessage);

            result.Length.Should().Be(config.MaxEventSizeBytes, "result event size should be within the limit");

            dynamic json = JObject.Parse(result);

            var message = (string)json.message;

            message.Length.Should().BeLessThan(originalMessage.Length, "result message should be shorter than original message");
            originalMessage.Should().StartWith(message, "result message should be beginning of the original message");
        }
        public void ShouldSerializeThreadContextProperties()
        {
            var evt = _fixture.Create <LoggingEvent>();

            ThreadContext.Properties["Key1"] = _fixture.Create("value1");
            ThreadContext.Properties["Key2"] = _fixture.Create <int>();
            ThreadContext.Properties["Key3"] = _fixture.Create <ComplexType>();
            ThreadContext.Properties["Key4"] = _fixture.Create <FixedComplexType>();
            ThreadContext.Properties["Key5"] = null;

            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var key1 = json.Key1;
            var key2 = json.Key2;
            var key3 = json.Key3;
            var key4 = json.Key4;
            var key5 = json.Key5;

            ((string)key1).Should().StartWith("value1", "because that's the value of the event property with this key");
            ((int)key2).Should().BeGreaterThan(0, "because the key is set to a positive value in the event properties");
            ((object)key3).Should().NotBeNull("because the key is set in the event properties");
            ((string)key3.PropertyOne).Should().StartWith("PropertyOne", "because the value of the complex type should be serialized");
            ((int)key3.PropertyTwo).Should().BeGreaterThan(0, "because the value of the complex type should be serialized");
            ((object)key4).Should().NotBeNull("because the key is set in the event properties");
            ((string)key4).Should().Be("I'm a fixed type!", "because the type of this property requires fixing");
            ((object)key5).Should().BeNull("because the key is set but the value is null");
        }
        public void ShouldReturnValidJson()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var    result = instance.ToJson(evt, evt.RenderedMessage);
            Action act    = () => JObject.Parse(result);

            act.Should().NotThrow <JsonException>("because the result should be a valid json document");
        }
        public void ShouldAddALevelProperty()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var level = (string)json.level;

            level.Should().StartWith("levelName", "because the level name property on the event is used");
        }
        public void ShouldAddALoggerNameProperty()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var loggerName = (string)json.loggerName;

            loggerName.Should().StartWith("LoggerName", "because this is the value of the LoggerName property on the event");
        }
        public void ShouldAddAHostNameProperty()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var hostName = (string)json.hostName;

            hostName.Should().NotBeNullOrEmpty("because the machine name is used to set the hostname");
        }
        public void ShouldAddAProcessProperty()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var process = (string)json.process;

            process.Should().NotBeNullOrEmpty("because the value is taken from the current process which should always be set");
        }
        public void ShouldAddAValidTimestampProperty()
        {
            var evt      = _fixture.Create <LoggingEvent>();
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var timestamp = (string)json.timestamp;

            timestamp.Should().NotBeNullOrEmpty("because the timestamp property should always be set");
            DateTime.TryParse(timestamp, out _).Should().BeTrue("because the timestamp should always be a valid date");
        }
        public void ShouldAddAMessagePropertyForEventsWithoutMessages()
        {
            var evt = new LoggingEvent(new LoggingEventData {
                Level = Level.Info
            });
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var message = (string)json.message;

            message.Should()
            .Be("null", "because the MessageObject property is null but we want to log \"null\" to show this explicitly");
        }
        public void ShouldSerializeCustomObjectToOutput()
        {
            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                new { property1 = "value1" },
                null);
            var instance = new LogdnaFormatter(new Config());

            var result = instance.ToJson(evt, evt.RenderedMessage);
            var json   = JObject.Parse(result);

            json.Should().HaveElement("property1").Which.Should().HaveValue("value1");
        }
        public void ShouldSerializeGlobalContextEnvProperties()
        {
            var evt = _fixture.Create <LoggingEvent>();

            PopulateSixContextProperties(GlobalContext.Properties);

            var instance = new LogdnaFormatter(new Config
            {
                Env = "prod"
            });

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            VerifyContextPropertiesInJson(json);
        }
        public void ShouldSerializeRenderedMessageIfNoMessageObjectIsSet()
        {
            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                new LoggingEventData
            {
                Message = "test message"
            });
            var instance = new LogdnaFormatter(new Config());

            var result = instance.ToJson(evt, evt.RenderedMessage);
            var json   = JObject.Parse(result);

            json.Should().HaveElement("message").Which.Should().HaveValue("test message");
        }
        public void ShouldSerializeFormattedString()
        {
            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                new SystemStringFormat(CultureInfo.InvariantCulture, "test: {0}{1}{2}", 1, 2, 3),
                null);
            var instance = new LogdnaFormatter(new Config());

            var result = instance.ToJson(evt, evt.RenderedMessage);
            var json   = JObject.Parse(result);

            json.Should().HaveElement("message").Which.Should().HaveValue("test: 123");
        }
        public void ShouldSetMessagePropertyWhenMessageObjectIsString()
        {
            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                _fixture.Create("message"),
                null);
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var message = (string)json.message;

            message.Should().StartWith("message", "because the MessageObject property value is used");
        }
        public void ShouldAddExtraPropertiesWhenMessageObjectIsAComplexType()
        {
            var evt = new LoggingEvent(
                GetType(),
                null,
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                _fixture.Create <ComplexType>(),
                null);
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var propertyOne = (string)json.PropertyOne;
            var propertyTwo = (int)json.PropertyTwo;

            propertyOne.Should().StartWith("PropertyOne", "because the value from the PropertyOne property on the complex type is used");
            propertyTwo.Should().BeGreaterThan(0, "because the value of the PropertyTwo property on the complex type is used");
        }
        public void EventWithoutMessageExceedingMaxSizeIsDropped()
        {
            var config = new Config
            {
                // there is 155 bytes of fixed JSON (for "evt" values below) unrelated to "message" value
                // so this value should cut message to first 20 characters
                MaxEventSizeBytes = 175
            };
            var formatter = new LogdnaFormatter(config);
            var evt       = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                "logger",
                Level.Info,
                new { Property1 = "value1", Property2 = "value2", Property3 = "value3" },
                null);

            var result = formatter.ToJson(evt, "<anonymous_type>");

            result.Should().BeNull();
        }
        public void ShouldSerializeInnerExceptions(int configurationNumberOfInnerExceptions, int expectedNumberOfInnerExceptions, int innerExceptionsToCreate)
        {
            Exception ex = GetArgumentException(innerExceptionsToCreate + 1);

            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                _fixture.Create("message"),
                ex);
            var instance = new LogdnaFormatter(new Config
            {
                NumberOfInnerExceptions = configurationNumberOfInnerExceptions
            });

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var exception = json.exception;

            ((object)exception).Should().NotBeNull("because an exception was specified in the event");

            var count = 0;

            while (exception != null)
            {
                var message    = (string)exception.exceptionMessage;
                var type       = (string)exception.exceptionType;
                var stacktrace = (string)exception.stacktrace;
                AssertException(message, type, stacktrace, count);
                exception = exception.innerException;
                if (exception != null)
                {
                    count++;
                }
            }

            count.Should().Be(expectedNumberOfInnerExceptions, "Expects all stacktraces");
        }
        public void ShouldSerializeTheException()
        {
            // In order to populate the stacktrace.
            Exception ex;

            try
            {
                throw new ArgumentException();
            }
            catch (Exception e)
            {
                ex = e;
            }

            var evt = new LoggingEvent(
                GetType(),
                CreateMockRepository(),
                _fixture.Create("loggerName"),
                _fixture.Create <Level>(),
                _fixture.Create("message"),
                ex);
            var instance = new LogdnaFormatter(new Config());

            var     result = instance.ToJson(evt, evt.RenderedMessage);
            dynamic json   = JObject.Parse(result);

            var exception = json.exception;

            ((object)exception).Should().NotBeNull("because an exception was specified in the event");

            var message    = (string)exception.exceptionMessage;
            var type       = (string)exception.exceptionType;
            var stacktrace = (string)exception.stacktrace;

            message.Should().NotBeNullOrEmpty("because an argument exception has a default message");
            type.Should().Be(typeof(ArgumentException).FullName, "because we logged an argument exception");
            stacktrace.Should().NotBeNull("because the exception has a stacktrace");
        }