Example #1
0
        /// <summary>
        /// Convert a Serilog <see cref="LogEventPropertyValue"/> for JavaScript interop.
        /// </summary>
        public static object ToInteropValue(LogEventPropertyValue value, string format = null)
        {
            if (value is ScalarValue sv)
            {
                if (format == null)
                {
                    return(sv.Value);
                }
                var sw = new StringWriter();
                sv.Render(sw, format);
                return(sw.ToString());
            }

            if (value is SequenceValue sqv)
            {
                return(sqv.Elements
                       .Select(e => ToInteropValue(e))
                       .ToArray());
            }

            if (value is StructureValue st)
            {
                return(st.Properties
                       .ToDictionary(kv => kv.Name, kv => ToInteropValue(kv.Value)));
            }

            var dv = (DictionaryValue)value;

            return(dv.Elements
                   .ToDictionary(kv => ToInteropValue(kv.Key), kv => ToInteropValue(kv.Value)));
        }
        /// <summary>
        /// Visit the root node type. This method delegates to
        /// a concrete Visit*Value() method appropriate for the value.
        /// </summary>
        /// <param name="state">Operation state.</param>
        /// <param name="value">The value to visit.</param>
        /// <returns>The result of visiting <paramref name="value"/>.</returns>
        protected virtual TResult Visit(TState state, LogEventPropertyValue value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (value is ScalarValue sv)
            {
                return(VisitScalarValue(state, sv));
            }

            if (value is SequenceValue seqv)
            {
                return(VisitSequenceValue(state, seqv));
            }

            if (value is StructureValue strv)
            {
                return(VisitStructureValue(state, strv));
            }

            if (value is DictionaryValue dictv)
            {
                return(VisitDictionaryValue(state, dictv));
            }

            return(VisitUnsupportedValue(state, value));
        }
        /// <summary>
        /// Simplify the object so as to make handling the serialized
        /// representation easier.
        /// </summary>
        /// <param name="value">The value to simplify (possibly null).</param>
        /// <param name="format">A format string applied to the value, or null.</param>
        /// <param name="formatProvider">A format provider to apply to the value, or null to use the default.</param>
        /// <returns>An Azure Storage entity EntityProperty</returns>
        public static EntityProperty ToEntityProperty(LogEventPropertyValue value, string format = null, IFormatProvider formatProvider = null)
        {
            var scalar = value as ScalarValue;

            if (scalar != null)
            {
                return(SimplifyScalar(scalar.Value));
            }

            var dict = value as DictionaryValue;

            if (dict != null)
            {
                return(new EntityProperty(dict.ToString(format, formatProvider)));
            }

            var seq = value as SequenceValue;

            if (seq != null)
            {
                return(new EntityProperty(seq.ToString(format, formatProvider)));
            }
            var str = value as StructureValue;

            if (str != null)
            {
                return(new EntityProperty(str.ToString(format, formatProvider)));
            }

            return(null);
        }
Example #4
0
        public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory,
                                   out LogEventPropertyValue result)
        {
            if (value is TodoItemQuery todoItemQuery)
            {
                result = new StructureValue(new List <LogEventProperty>
                {
                    new LogEventProperty(nameof(todoItemQuery.Id), new ScalarValue(todoItemQuery.Id)),
                    new LogEventProperty(nameof(todoItemQuery.NamePattern), new ScalarValue(todoItemQuery.NamePattern)),
                    new LogEventProperty(nameof(todoItemQuery.IsComplete), new ScalarValue(todoItemQuery.IsComplete)),
                    new LogEventProperty(nameof(todoItemQuery.Owner),
                                         new ScalarValue(todoItemQuery.Owner.GetNameOrDefault())),
                    new LogEventProperty(nameof(todoItemQuery.PageIndex), new ScalarValue(todoItemQuery.PageIndex)),
                    new LogEventProperty(nameof(todoItemQuery.PageSize), new ScalarValue(todoItemQuery.PageSize)),
                    new LogEventProperty(nameof(todoItemQuery.SortBy), new ScalarValue(todoItemQuery.SortBy)),
                    new LogEventProperty(nameof(todoItemQuery.IsSortAscending),
                                         new ScalarValue(todoItemQuery.IsSortAscending))
                });

                return(true);
            }

            result = null;
            return(false);
        }
        private static LogEventPropertyValue Stringify(LogEventPropertyValue value)
        {
            switch (value)
            {
            case ScalarValue scalar:
                var element = scalar.Value.ToString();
                return(new ScalarValue(element));

            case SequenceValue sequence:
                var elements = sequence.Elements.Select(Stringify);
                return(new SequenceValue(elements));

            case DictionaryValue dictionary:
                var entries = dictionary.Elements.Select(entry =>
                                                         new KeyValuePair <ScalarValue, LogEventPropertyValue>(
                                                             (ScalarValue)Stringify(entry.Key), Stringify(entry.Value)));
                return(new DictionaryValue(entries));

            case StructureValue structure:
                var properties = structure.Properties.Select(property =>
                                                             new LogEventProperty(property.Name, Stringify(property.Value)));
                return(new StructureValue(properties));

            default:
                throw new ArgumentException("Invalid property type");
            }
        }
Example #6
0
        // Convert scalars into a small set of primitive types; leave everything else unchanged. This
        // makes it easier to flow values through operations.
        public static object Represent(LogEventPropertyValue value)
        {
            var sv = value as ScalarValue;

            if (sv != null)
            {
                if (sv.Value == null)
                {
                    return(null);
                }

                if (Array.IndexOf(AllowedTypes, sv.Value.GetType()) != -1)
                {
                    return(sv.Value);
                }

                if (Array.IndexOf(NumericTypes, sv.Value.GetType()) != -1)
                {
                    return(Convert.ChangeType(sv.Value, typeof(decimal)));
                }

                return(sv.Value.ToString());
            }

            return(value);
        }
Example #7
0
        /// <summary>
        /// Writes event properties as labels for a GCP log entry.
        /// GCP log labels are a flat key/value namespace so all child event properties will be prefixed with parent property names "parentkey.childkey" similar to json path.
        /// </summary>
        private void WritePropertyAsLabel(LogEntry log, string propertyKey, LogEventPropertyValue propertyValue)
        {
            switch (propertyValue)
            {
            case ScalarValue scalarValue when scalarValue.Value is null:
                log.Labels.Add(propertyKey, String.Empty);
                break;

            case ScalarValue scalarValue:
                var stringValue = scalarValue.Value.ToString();
                log.Labels.Add(propertyKey, stringValue);
                CheckIfSourceContext(log, propertyKey, stringValue);
                break;

            case SequenceValue sequenceValue:
                log.Labels.Add(propertyKey, String.Join(",", sequenceValue.Elements));
                break;

            case StructureValue structureValue when structureValue.Properties.Count > 0:
                foreach (var childProperty in structureValue.Properties)
                {
                    WritePropertyAsLabel(log, propertyKey + "." + childProperty.Name, childProperty.Value);
                }

                break;

            case DictionaryValue dictionaryValue when dictionaryValue.Elements.Count > 0:
                foreach (var childProperty in dictionaryValue.Elements)
                {
                    WritePropertyAsLabel(log, propertyKey + "." + childProperty.Key.ToString().Replace("\"", ""), childProperty.Value);
                }

                break;
            }
        }
        /// <summary>
        /// Removes the structure of <see cref="LogEventPropertyValue"/> implementations introduced
        /// by Serilog and brings properties closer to the structure of the original object.
        /// This enables Exceptionless to display the properties in a nicer way.
        /// </summary>
        private static object FlattenProperties(LogEventPropertyValue value)
        {
            var scalar = value as ScalarValue;

            if (scalar != null)
            {
                return(scalar.Value);
            }

            var sequence = value as SequenceValue;

            if (sequence != null)
            {
                return(sequence.Elements.Select(FlattenProperties));
            }

            var structure = value as StructureValue;

            if (structure != null)
            {
                return(structure.Properties.ToDictionary(p => p.Name, p => FlattenProperties(p.Value)));
            }

            var dictionary = value as DictionaryValue;

            if (dictionary != null)
            {
                return(dictionary.Elements.ToDictionary(p => p.Key.Value, p => FlattenProperties(p.Value)));
            }

            return(value);
        }
Example #9
0
        static JToken ConvertPropertyValue(LogEventPropertyValue value)
        {
            var scalar = value as ScalarValue;

            if (scalar != null)
            {
                return(ConvertScalarValue(scalar));
            }

            var seq = value as SequenceValue;

            if (seq != null)
            {
                return(ConvertSequenceValue(seq));
            }

            var strct = value as StructureValue;

            if (strct != null)
            {
                return(ConvertStructureValue(strct));
            }

            var dict = value as DictionaryValue;

            if (dict != null)
            {
                return(ConvertDictionaryValue(dict));
            }

            // TODO: Log or something.
            return(JValue.CreateUndefined());
        }
Example #10
0
        private static object PropertyValueToObject(LogEventPropertyValue propertyValue)
        {
            if (propertyValue is SequenceValue values)
            {
                return(values.Elements.Select(e => PropertyValueToObject(e)).ToArray());
            }

            if (propertyValue is ScalarValue sv)
            {
                return(sv.Value);
            }
            else if (propertyValue is DictionaryValue dv)
            {
                return(dv.Elements.ToDictionary(keySelector: (kvp) => ToSnakeCase(kvp.Key.Value.ToString()), elementSelector: (kvp) => PropertyValueToObject(kvp.Value)));
            }
            else if (propertyValue is StructureValue ov)
            {
                var dict = ov.Properties.ToDictionary(p => p.Name, p => PropertyValueToObject(p.Value));
                if (ov.TypeTag != null)
                {
                    dict.Add("$type", ov.TypeTag);
                }
                return(dict);
            }
            else
            {
                return(propertyValue);
            }
        }
Example #11
0
        async Task SendEvent(LogEvent logEvent)
        {
            LogEventPropertyValue datasetProperty = null;

            logEvent.Properties.TryGetValue(DatasetPropertyKey, out datasetProperty);
            string dataset = ((datasetProperty as ScalarValue)?.Value as string) ?? this.defaultDataset;

            var request = new HttpRequestMessage(HttpMethod.Post, "events/" + dataset)
            {
                Content = new StringContent(
                    content: JsonConvert.SerializeObject(EventToJObject(logEvent)),
                    encoding: Encoding.UTF8,
                    mediaType: "application/json"
                    ),
                Headers =
                {
                    { "X-Honeycomb-Event-Time", logEvent.Timestamp.ToString("o") },
                }
            };

            using (HttpResponseMessage message = await client.SendAsync(request))
            {
                // TODO: Log if unsuccessful. This requires... hum.
                if (!message.IsSuccessStatusCode)
                {
                    string msg = await message.Content.ReadAsStringAsync();

                    Console.WriteLine($"Warning: Failed to send event: {message.StatusCode}: {msg}");
                }
            }
        }
Example #12
0
        static object ToData(LogEventPropertyValue value)
        {
            switch (value)
            {
            case ScalarValue sv:
                return(sv.Value);

            case StructureValue str:
                var props = str.Properties.ToDictionary(kv => kv.Name, kv => ToData(kv.Value));
                if (str.TypeTag != null)
                {
                    props["$type"] = str.TypeTag;
                }
                return(props);

            case SequenceValue seq:
                return(seq.Elements.Select(ToData).ToArray());

            case DictionaryValue dv:
                var dict = new Dictionary <object, object>();
                foreach (var kvp in dv.Elements)
                {
                    dict[ToData(kvp.Key)] = ToData(kvp.Value);
                }
                return(dict);

            default:
                throw new NotSupportedException($"Value type {value} is not supported.");
            }
        }
Example #13
0
        public ExpressionFilter(string filterExpression)
        {
            Func <LogEvent, bool> filter;

            // Our custom Serilog Functions to extend Serilog.Expressions
            // In this case we are plugging the gap for the missing Has()
            // function from porting away from Serilog.Filters.Expressions to Serilog.Expressions
            // Along with patching support for the more verbose built in property names
            var customSerilogFunctions = new SerilogLegacyNameResolver(typeof(SerilogExpressionsFunctions));

            if (string.IsNullOrEmpty(filterExpression))
            {
                return;
            }

            // If the expression is one word and doesn't contain a serilog operator then we can perform a like search
            if (!filterExpression.Contains(" ") && !filterExpression.ContainsAny(s_expressionOperators.Select(c => c)))
            {
                filter = PerformMessageLikeFilter(filterExpression);
            }
            else // check if it's a valid expression
            {
                // If the expression evaluates then make it into a filter
                if (SerilogExpression.TryCompile(filterExpression, null, customSerilogFunctions, out CompiledExpression compiled, out var error))
                {
                    filter = evt =>
                    {
                        LogEventPropertyValue result = compiled(evt);
                        return(ExpressionResult.IsTrue(result));
                    };
                }
Example #14
0
        private static object PropertyValueToObject(LogEventPropertyValue propertyValue)
        {
            switch (propertyValue)
            {
            case SequenceValue values:
                return(values.Elements.Select(PropertyValueToObject).ToArray());

            case ScalarValue sv:
                return(sv.Value);

            case DictionaryValue dv:
                return(dv.Elements.ToDictionary(keySelector: kvp => ToSnakeCase(kvp.Key.Value.ToString()), elementSelector: (kvp) => PropertyValueToObject(kvp.Value)));

            case StructureValue ov:
            {
                var dict = ov.Properties.ToDictionary(p => p.Name, p => PropertyValueToObject(p.Value));
                if (ov.TypeTag != null)
                {
                    dict.Add("$type", ov.TypeTag);
                }
                return(dict);
            }

            default:
                return(propertyValue);
            }
        }
Example #15
0
        /// <summary>
        /// Visit a <see cref="SequenceValue"/> value.
        /// </summary>
        /// <param name="state">Operation state.</param>
        /// <param name="sequence">The value to visit.</param>
        /// <returns>The result of visiting <paramref name="sequence"/>.</returns>
        protected override LogEventPropertyValue VisitSequenceValue(TState state, SequenceValue sequence)
        {
            if (sequence == null)
            {
                throw new ArgumentNullException(nameof(sequence));
            }

            for (var i = 0; i < sequence.Elements.Count; ++i)
            {
                var original = sequence.Elements[i];
                if (!ReferenceEquals(original, Visit(state, original)))
                {
                    var contents = new LogEventPropertyValue[sequence.Elements.Count];

                    // There's no need to visit any earlier elements: they all evaluated to
                    // a reference equal with the original so just fill in the array up until `i`.
                    for (var j = 0; j < i; ++j)
                    {
                        contents[j] = sequence.Elements[j];
                    }

                    for (var k = i; k < contents.Length; ++k)
                    {
                        contents[k] = Visit(state, sequence.Elements[k]);
                    }

                    return(new SequenceValue(contents));
                }
            }

            return(sequence);
        }
Example #16
0
 /// <summary>
 /// Format <paramref name="value"/> as JSON to <paramref name="output"/>.
 /// </summary>
 /// <param name="value">The value to format</param>
 /// <param name="output">The output</param>
 public void Format(LogEventPropertyValue value, TextWriter output)
 {
     // Parameter order of ITextFormatter is the reverse of the visitor one.
     // In this class, public methods and methods with Format*() names use the
     // (x, output) parameter naming convention.
     Visit(output, value);
 }
Example #17
0
 public static LogEventPropertyValue AsSensitive(this LogEventPropertyValue eventPropertyValue)
 {
     return(new DictionaryValue(new Dictionary <ScalarValue, LogEventPropertyValue>
     {
         [new ScalarValue(Constants.SensitiveInformation)] = eventPropertyValue,
     }));
 }
        private static object ToRawValue(LogEventPropertyValue logEventValue)
        {
            // Special-case a few types of LogEventPropertyValue that allow us to maintain better type fidelity.
            // For everything else take the default string rendering as the data.
            ScalarValue scalarValue = logEventValue as ScalarValue;

            if (scalarValue != null)
            {
                return(scalarValue.Value);
            }

            SequenceValue sequenceValue = logEventValue as SequenceValue;

            if (sequenceValue != null)
            {
                object[] arrayResult = sequenceValue.Elements.Select(e => ToRawScalar(e)).ToArray();
                if (arrayResult.Length == sequenceValue.Elements.Count)
                {
                    // All values extracted successfully, it is a flat array of scalars
                    return(arrayResult);
                }
            }

            StructureValue structureValue = logEventValue as StructureValue;

            if (structureValue != null)
            {
                IDictionary <string, object> structureResult = new Dictionary <string, object>(structureValue.Properties.Count);
                foreach (var property in structureValue.Properties)
                {
                    structureResult[property.Name] = ToRawScalar(property.Value);
                }

                if (structureResult.Count == structureValue.Properties.Count)
                {
                    if (structureValue.TypeTag != null)
                    {
                        structureResult["$type"] = structureValue.TypeTag;
                    }

                    return(structureResult);
                }
            }

            DictionaryValue dictionaryValue = logEventValue as DictionaryValue;

            if (dictionaryValue != null)
            {
                IDictionary <string, object> dictionaryResult = dictionaryValue.Elements
                                                                .Where(kvPair => kvPair.Key.Value is string)
                                                                .ToDictionary(kvPair => (string)kvPair.Key.Value, kvPair => ToRawScalar(kvPair.Value));
                if (dictionaryResult.Count == dictionaryValue.Elements.Count)
                {
                    return(dictionaryResult);
                }
            }

            // Fall back to string rendering of the value
            return(logEventValue.ToString());
        }
Example #19
0
        /// <summary>
        /// Checks a <see cref="LogEventPropertyValue"/> to have the correct data value type.
        /// </summary>
        /// <param name="receivedPropertyName">The key to use when writing the data value as GELF property.</param>
        /// <param name="property">The <see cref="LogEventPropertyValue"/> containing the data value.</param>
        /// <returns>A <see cref="GraylogPropertyCheckResult"/> with the check result.</returns>
        public GraylogPropertyCheckResult CheckProperty(string receivedPropertyName, LogEventPropertyValue property)
        {
            var res = new GraylogPropertyCheckResult {
                ReceivedPropertyName = receivedPropertyName
            };
            var pos = IndexOfKey(receivedPropertyName);

            if (pos == -1)
            {
                res.CheckResult |= GraylogPropertyCheckResultType.ErrorNameNotRegistered;
                return(res);
            }
            res.ExpectedPropertyName = Keys[pos];
            if (!receivedPropertyName.Equals(res.ExpectedPropertyName))
            {
                res.CheckResult |= GraylogPropertyCheckResultType.ErrorNameSpelling;
            }
            res.PropertyValue = GetValue(property, out var receivedType);
            var expectedType = Values[pos];

            if (expectedType == GraylogPropertyType.Object && receivedType != GraylogPropertyType.String || !expectedType.HasFlag(receivedType))
            {
                res.CheckResult      |= GraylogPropertyCheckResultType.ErrorValueTypeNotMatching;
                res.ExpectedValueType = expectedType;
                res.ReceivedValueType = receivedType;
            }
            return(res);
        }
        /// <inheritdoc/>
        public void Format(LogEvent logEvent, TextWriter output)
        {
            if (logEvent == null)
            {
                throw new ArgumentNullException(nameof(logEvent));
            }
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            output.Write("{\"time\":\"");
            output.Write(logEvent.Timestamp.ToEpoch().ToString(CultureInfo.InvariantCulture));
            output.Write("\",\"event\":{\"Severity\":\"");
            output.Write(logEvent.Level);
            output.Write('"');

            // Configure common event source properties
            LogEventPropertyValue eventName = null;

            foreach (var eventSourcePropertyName in EventSourceProperties)
            {
                if (logEvent.Properties.TryGetValue(eventSourcePropertyName, out eventName))
                {
                    if (eventSourcePropertyName == "SourceContext")
                    {
                        output.Write($",\"LoggerName\":");
                    }
                    else
                    {
                        output.Write($",\"{eventSourcePropertyName}\":");
                    }
                    ValueFormatter.Format(eventName, output);
                }
            }

            if (logEvent.Exception != null)
            {
                output.Write(",\"Exception\":");
                JsonValueFormatter.WriteQuotedJsonString(logEvent.Exception.ToString(), output);
            }

            var propertiesToRender = logEvent.Properties.Where(IsRenderedProperty);

            if (propertiesToRender.Count() != 0)
            {
                WriteProperties(propertiesToRender, output);
            }

            var message = logEvent.RenderMessage(null);

            if (!(string.IsNullOrWhiteSpace(message) || message == EventLogger.EventDataTemplate))
            {
                output.Write(",\"Message\":");
                JsonValueFormatter.WriteQuotedJsonString(message, output);
            }

            output.WriteLine(suffix);
        }
Example #21
0
 private int GetIntValue(LogEventPropertyValue value)
 {
     if (value is ScalarValue scalar)
     {
         return((int)scalar.Value);
     }
     return(0);
 }
Example #22
0
 private string GetTextValue(LogEventPropertyValue value)
 {
     if (value is ScalarValue scalar)
     {
         return(scalar.Value.ToString());
     }
     return("");
 }
Example #23
0
        public static void HasPropertyValue(object propertyValue, string propertyName, LogEvent logEvent)
        {
            HasProperty(propertyName, logEvent);

            LogEventPropertyValue value = logEvent.Properties[propertyName];

            Assert.That(value.LiteralValue(), Is.EqualTo(propertyValue), "The property value was not as expected");
        }
 private static object GetPropertyValue(LogEventPropertyValue propertyValue)
 {
     return(propertyValue switch
     {
         SequenceValue sequenceValue => sequenceValue.Elements.Select(RenderSequenceValue).ToArray(),
         ScalarValue scalarValue => scalarValue.Value,
         _ => propertyValue.ToString()
     });
 /// <summary>
 /// Visit a value of an unsupported type.
 /// </summary>
 /// <param name="state">Operation state.</param>
 /// <param name="value">The value to visit.</param>
 /// <returns>The result of visiting <paramref name="value"/>.</returns>
 // ReSharper disable once UnusedParameter.Global
 // ReSharper disable once VirtualMemberNeverOverriden.Global
 protected virtual TResult VisitUnsupportedValue(TState state, LogEventPropertyValue value)
 {
     if (value == null)
     {
         throw new ArgumentNullException(nameof(value));
     }
     throw new NotSupportedException($"The value {value} is not of a type supported by this visitor.");
 }
Example #26
0
 public static bool CoerceToScalarBoolean(LogEventPropertyValue value)
 {
     if (value is ScalarValue sv && sv.Value is bool b)
     {
         return(b);
     }
     return(false);
 }
        static string Format(LogEventPropertyValue value)
        {
            var formatter = new TestThemedJsonValueFormatter();
            var output    = new StringWriter();

            formatter.Format(value, output, null);
            return(output.ToString());
        }
Example #28
0
        public static bool MatchesStringRepresentationOfLogEventPropertyValue(
            string expectedValue,
            LogEventPropertyValue property)
        {
            var actualValue  = ExtractStringRepresentationOfLogEventPropertyValue(property);
            var valueMatches = actualValue.Equals(expectedValue, StringComparison.InvariantCultureIgnoreCase);

            return(valueMatches);
        }
 public static string AsString(this LogEventPropertyValue propertyValue)
 {
     if (!(propertyValue is ScalarValue scalar))
     {
         return(null);
     }
     // Handle string values differently as the ToString() method will wrap the string in unwanted quotes
     return(scalar.Value is string s ? s : scalar.ToString());
 }
        public static object[] SequenceValues(this LogEventPropertyValue @this)
        {
            if (@this is SequenceValue sequenceValue)
            {
                return(sequenceValue.Elements.Select(x => x.LiteralValue()).ToArray());
            }

            return(null);
        }