diff --git a/src/TraceClient/TraceClient.cs b/src/TraceClient/TraceClient.cs
index 06241b6..4b48f7a 100644
--- a/src/TraceClient/TraceClient.cs
+++ b/src/TraceClient/TraceClient.cs
@@ -76,7 +76,8 @@ public sealed class TraceClient : IDisposable
/// The most tags the server accepts on one report.
public const int MaxTags = 32;
- /// The longest application, name, tag key or tag value the server accepts, in UTF-16 chars.
+ /// The longest application, name, tag key or tag value the server accepts, in UTF-16 chars.
+ /// The program's version and installation ID are tag values too, so the constructor rejects either past it.
public const int MaxLength = 255;
/// Environment variable that turns reporting off: off, false, 0, no.
@@ -122,9 +123,10 @@ public sealed class TraceClient : IDisposable
/// , reporting to the trace server at
/// . Throws only for a
/// missing or malformed , a missing
- /// , or a missing or
- /// one longer than characters -- programming errors,
- /// not runtime ones.
+ /// , a missing or
+ /// one longer than characters, or an
+ /// longer than characters --
+ /// programming errors, not runtime ones.
///
/// The trace server, e.g. https://trace.danielstephenson.dev.
/// The program's name, exactly as its key was issued for.
diff --git a/tests/TraceClient.Tests/TraceClientTest.cs b/tests/TraceClient.Tests/TraceClientTest.cs
index 6dbd83f..92b6300 100644
--- a/tests/TraceClient.Tests/TraceClientTest.cs
+++ b/tests/TraceClient.Tests/TraceClientTest.cs
@@ -453,6 +453,38 @@ public void Json_RejectsATagKeyLongerThanTheLimitAndNamesOnlyItsStart()
Assert.Null(body);
}
+ [Fact]
+ public void Json_RejectsANameLongerThanTheLimitButNotOneAtIt()
+ {
+ string longest = new string('n', TraceClient.MaxLength);
+ string tooLong = new string('n', TraceClient.MaxLength + 1);
+
+ string problem = TraceClient.Json("App", tooLong, null, null, out string rejected);
+
+ Assert.Equal("name longer than " + TraceClient.MaxLength + " characters", problem);
+ Assert.Null(rejected);
+ Assert.Null(TraceClient.Json("App", longest, null, null, out string accepted));
+ Assert.Contains(longest, accepted);
+ }
+
+ [Fact]
+ public void Json_RejectsATagValueLongerThanTheLimitAndNamesItsKey()
+ {
+ // The reason names the key, not the value: the value is what ran
+ // away, and the key is what the program can find in its source.
+ string tooLongValue = new string('v', TraceClient.MaxLength + 1);
+ string longestValue = new string('v', TraceClient.MaxLength);
+
+ string problem = TraceClient.Json("App", "n", null,
+ new Dictionary { { "level", tooLongValue } }, out string body);
+
+ Assert.Equal("tag level longer than " + TraceClient.MaxLength + " characters", problem);
+ Assert.Null(body);
+ Assert.Null(TraceClient.Json("App", "n", null,
+ new Dictionary { { "level", longestValue } }, out string accepted));
+ Assert.Contains("\"level\":\"" + longestValue + "\"", accepted);
+ }
+
[Fact]
public void Quote_EscapesCarriageReturnAndEveryOtherControlCharacter()
{