Skip to content

Conversation

nblumhardt
Copy link
Member

This PR for #965 converts tuples like (1, 2, 3) into arrays like [1, 2, 3] for consumption by sinks.

I don't think tuples are important enough, currently, to justify the effort of including another LogEventPropertyValue type to represent them. Arrays are a bit easier on the eyes than structures, and we don't lose any information since tuple member names aren't available dynamically.

The @ operator is not required to capture a tuple. E.g.:

Log.Information("{T}", (1, 2));

is fine. Specifying @ will trigger deep serialization in the case of tuple members that are complex types.

The PR is a little ham-fisted (the change doesn't fit in as an IScalarConversionPolicy, unfortunately, so special treatment is needed). Only tuples up to length 7 are supported.

Since tuples are here to stay, and supported everywhere Serilog runs, I've introduced the System.ValueTuple dependency for the current targets. A .NET 4.7-specific target would avoid it, as will .NET Core 2.0. We can add this fresh round of targets once core 2.0 ships, I think (4.7 is a pain right now as it requires a targeting pack).

<PackageReference Include="System.Runtime.Extensions" Version="4.1.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.1.0" />
<PackageReference Include="System.Threading" Version="4.0.11" />
<PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These dependencies are updated; System.ValueTuple depends on s.Collections under .NET Standard, and requires at least 4.3.0, so we might as well be consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The netstandard1.x targets should probably be updated to just depend on NETStandard.Library anyway, TBH.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @khellang - you're probably right here. I guess the dust has settled enough for us to embrace the new order of things :-). Perhaps we make the change when .NET Core 2.0 comes along? I am tempted to leave it alone in this PR, just to avoid any more chasing of corner cases....

@@ -190,6 +190,33 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
enumerable.Cast<object>().Take(_maximumCollectionCount).Select(o => limiter.CreatePropertyValue(o, destructuring)));
}

if (value is IStructuralEquatable)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempting to keep the cost of the test down.

definition == typeof(ValueTuple<,,,,,,>)) // Ignore the 8+ value case for now.
{
var elements = new List<LogEventPropertyValue>();
foreach (var field in type.GetTypeInfo().DeclaredFields)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assumes fields are ordered (I think this is safe).

@nblumhardt nblumhardt changed the title ValueTuple to sequence value conversion [WIP] ValueTuple to sequence value conversion May 31, 2017
@nblumhardt
Copy link
Member Author

Ready to go, if CI likes me :-)

@nblumhardt nblumhardt requested a review from adamchester May 31, 2017 02:14
Copy link
Contributor

@skomis-mm skomis-mm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a question :)

@@ -23,25 +23,44 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
Copy link
Contributor

@skomis-mm skomis-mm May 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a pity. Why you didn't considered the fourth option (along with the first)?

4.Support it everywhere, using reflection only (no direct dependency on ValueTuple itself)

Is that because of some performance concerns? I believe you could check type.Name to constants (ValueTuple'1, ValueTuple'2 etc) like you did with definition == comparisons

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I initially discounted this because it seemed a bit awkward, given tuples are a feature of C# that's here to stay. On second thought, it's not much worse to do the type name check than to do what we have here, so I'll switch it back over and #if VALUETUPLE conditionally-include the Type-based version 👍

@nblumhardt
Copy link
Member Author

Alrighty! Avoided the package dependency and thus any dependency changes. Ready to go 🚀

}

[Fact]
public void EightPlusValueTupleElementsAreIgnored()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit EightPlusValueTupleElementsAreIgnored -> EightPlusValueTupleElementsAreIgnoredWhenDestructuring

Why the arbitrary 8?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 probably should be WhenCapturing, but good point.

The limitation is in how ValueTuple works, up to seven elements can be represented directly in one tuple, but to go 8+ they need to be nested. No major issue with implementing it down the road.

[Fact]
public void AllTupleLengthsUpToSevenAreSupported()
{
var tuples = new object[]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is an empty array test worthwhile?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we migrate to InlineData for use cases?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried, but ValueTuple isn't regarded by csc as a compile-time constant, so no joy :-(

Copy link
Contributor

@merbla merbla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nits but nothing to stop this moving.

@nblumhardt nblumhardt merged commit 8b68856 into serilog:dev Jun 3, 2017
@nblumhardt nblumhardt mentioned this pull request Jun 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants