From 7ae01f0938dad5a754d570576d86078120bf05e7 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai Date: Fri, 7 Oct 2022 12:36:06 -0700 Subject: [PATCH 1/3] Add redaction project --- OpenTelemetry.sln | 7 +++ .../MyClassWithRedactionEnumerator.cs | 53 ---------------- docs/logs/extending-the-sdk/Program.cs | 3 +- .../MyClassWithRedactionEnumerator.cs | 61 +++++++++++++++++++ .../MyRedactionProcessor.cs | 10 ++- docs/logs/redaction/Program.cs | 38 ++++++++++++ docs/logs/redaction/README.md | 6 ++ docs/logs/redaction/redaction.csproj | 6 ++ .../ConsoleLogRecordExporter.cs | 23 ++++++- 9 files changed, 150 insertions(+), 57 deletions(-) delete mode 100644 docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs create mode 100644 docs/logs/redaction/MyClassWithRedactionEnumerator.cs rename docs/logs/{extending-the-sdk => redaction}/MyRedactionProcessor.cs (72%) create mode 100644 docs/logs/redaction/Program.cs create mode 100644 docs/logs/redaction/README.md create mode 100644 docs/logs/redaction/redaction.csproj diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index ec895d0d87a..25b30662416 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -234,6 +234,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.AspNetCore", "test\TestApp.AspNetCore\TestApp.AspNetCore.csproj", "{5FDAF679-DE5A-4C73-A49B-8ABCF2399229}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "redaction", "docs\logs\redaction\redaction.csproj", "{A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -476,6 +478,10 @@ Global {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Debug|Any CPU.Build.0 = Debug|Any CPU {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Release|Any CPU.ActiveCfg = Release|Any CPU {5FDAF679-DE5A-4C73-A49B-8ABCF2399229}.Release|Any CPU.Build.0 = Release|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -512,6 +518,7 @@ Global {6C7A1595-36D6-4229-BBB5-5A6B5791791D} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {5FDAF679-DE5A-4C73-A49B-8ABCF2399229} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F} + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs b/docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs deleted file mode 100644 index 4e5f3107460..00000000000 --- a/docs/logs/extending-the-sdk/MyClassWithRedactionEnumerator.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System.Collections; -using System.Collections.Generic; - -internal class MyClassWithRedactionEnumerator : IReadOnlyList> -{ - private readonly IReadOnlyList> state; - - public MyClassWithRedactionEnumerator(IReadOnlyList> state) - { - this.state = state; - } - - public int Count => this.state.Count; - - public KeyValuePair this[int index] => this.state[index]; - - public IEnumerator> GetEnumerator() - { - foreach (var entry in this.state) - { - var entryVal = entry.Value; - if (entryVal != null && entryVal.ToString() != null && entryVal.ToString().Contains("")) - { - yield return new KeyValuePair(entry.Key, "newRedactedValueHere"); - } - else - { - yield return entry; - } - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this.GetEnumerator(); - } -} diff --git a/docs/logs/extending-the-sdk/Program.cs b/docs/logs/extending-the-sdk/Program.cs index 2ea9dad4953..2a2703f6efe 100644 --- a/docs/logs/extending-the-sdk/Program.cs +++ b/docs/logs/extending-the-sdk/Program.cs @@ -28,8 +28,7 @@ public static void Main() builder.AddOpenTelemetry(options => { options.IncludeScopes = true; - options.AddProcessor(new MyRedactionProcessor()) - .AddProcessor(new MyProcessor("ProcessorA")) + options.AddProcessor(new MyProcessor("ProcessorA")) .AddProcessor(new MyProcessor("ProcessorB")) .AddProcessor(new SimpleLogRecordExportProcessor(new MyExporter("ExporterX"))) .AddMyExporter(); diff --git a/docs/logs/redaction/MyClassWithRedactionEnumerator.cs b/docs/logs/redaction/MyClassWithRedactionEnumerator.cs new file mode 100644 index 00000000000..7cac155957b --- /dev/null +++ b/docs/logs/redaction/MyClassWithRedactionEnumerator.cs @@ -0,0 +1,61 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System.Collections; +using System.Collections.Generic; + +namespace Redaction +{ + internal class MyClassWithRedactionEnumerator : IReadOnlyList> + { + private readonly IReadOnlyList> state; + + public MyClassWithRedactionEnumerator(IReadOnlyList> state) + { + this.state = state; + } + + public int Count => this.state.Count; + + public KeyValuePair this[int index] + { + get + { + var item = this.state[index]; + var entryVal = item.Value; + if (entryVal != null && entryVal.ToString() != null && entryVal.ToString().Contains("")) + { + return new KeyValuePair(item.Key, "newRedactedValueHere"); + } + + return item; + } + } + + public IEnumerator> GetEnumerator() + { + for (var i = 0; i < this.Count; i++) + { + yield return this[i]; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } +} diff --git a/docs/logs/extending-the-sdk/MyRedactionProcessor.cs b/docs/logs/redaction/MyRedactionProcessor.cs similarity index 72% rename from docs/logs/extending-the-sdk/MyRedactionProcessor.cs rename to docs/logs/redaction/MyRedactionProcessor.cs index 2ad8371ae69..70c704dbad0 100644 --- a/docs/logs/extending-the-sdk/MyRedactionProcessor.cs +++ b/docs/logs/redaction/MyRedactionProcessor.cs @@ -18,11 +18,19 @@ using OpenTelemetry; using OpenTelemetry.Logs; +namespace Redaction; + internal class MyRedactionProcessor : BaseProcessor { public override void OnEnd(LogRecord logRecord) { - if (logRecord.State is IReadOnlyList> listOfKvp) + if (logRecord.State == null) + { + // When State is null, OTel SDK guarantees StateValues is populated + // TODO: Debug.Assert? + logRecord.StateValues = new MyClassWithRedactionEnumerator(logRecord.StateValues); + } + else if (logRecord.State is IReadOnlyList> listOfKvp) { logRecord.State = new MyClassWithRedactionEnumerator(listOfKvp); } diff --git a/docs/logs/redaction/Program.cs b/docs/logs/redaction/Program.cs new file mode 100644 index 00000000000..f381856234e --- /dev/null +++ b/docs/logs/redaction/Program.cs @@ -0,0 +1,38 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using Microsoft.Extensions.Logging; +using OpenTelemetry.Logs; + +namespace Redaction; + +public class Program +{ + public static void Main() + { + using var loggerFactory = LoggerFactory.Create(builder => + builder.AddOpenTelemetry(options => + { + options.AddProcessor(new MyRedactionProcessor()); + options.AddConsoleExporter(); + })); + + var logger = loggerFactory.CreateLogger(); + + // message will be redacted by MyRedactionProcessor + logger.LogInformation("OpenTelemetry {sensitiveString}.", ""); + } +} diff --git a/docs/logs/redaction/README.md b/docs/logs/redaction/README.md new file mode 100644 index 00000000000..0475da6e939 --- /dev/null +++ b/docs/logs/redaction/README.md @@ -0,0 +1,6 @@ +# Redaction + +This program shows an example of how to redact sensitive information from Logs. +In this example, we attach a custom `Processor` called `MyRedactionProcessor` +which is responsible for replacing any instance of the word "<secret>" with the +value "newRedactedValueHere". diff --git a/docs/logs/redaction/redaction.csproj b/docs/logs/redaction/redaction.csproj new file mode 100644 index 00000000000..a0d4b1e148b --- /dev/null +++ b/docs/logs/redaction/redaction.csproj @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs index f089b0e95a2..811838e20c0 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs @@ -84,7 +84,28 @@ public override ExportResult Export(in Batch batch) if (logRecord.State != null) { - this.WriteLine($"{"LogRecord.State:",-RightPaddingLength}{logRecord.State}"); + if (logRecord.State is IReadOnlyList> listKvp) + { + this.WriteLine("LogRecord.State (Key:Value):"); + for (int i = 0; i < listKvp.Count; i++) + { + // Special casing {OriginalFormat} + // See https://github.com/open-telemetry/opentelemetry-dotnet/pull/3182 + // for explanation. + var valueToTransform = listKvp[i].Key.Equals("{OriginalFormat}") + ? new KeyValuePair("OriginalFormat (a.k.a Body)", listKvp[i].Value) + : listKvp[i]; + + if (ConsoleTagTransformer.Instance.TryTransformTag(listKvp[i], out var result)) + { + this.WriteLine($"{string.Empty,-4}{result}"); + } + } + } + else + { + this.WriteLine($"{"LogRecord.State:",-RightPaddingLength}{logRecord.State}"); + } } else if (logRecord.StateValues != null) { From 08069ae5e8bdebd010a95cf36b139bd1c6e5d57c Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai Date: Fri, 7 Oct 2022 12:43:10 -0700 Subject: [PATCH 2/3] Fix markdown --- docs/logs/redaction/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/logs/redaction/README.md b/docs/logs/redaction/README.md index 0475da6e939..1c6d65020a0 100644 --- a/docs/logs/redaction/README.md +++ b/docs/logs/redaction/README.md @@ -2,5 +2,5 @@ This program shows an example of how to redact sensitive information from Logs. In this example, we attach a custom `Processor` called `MyRedactionProcessor` -which is responsible for replacing any instance of the word "<secret>" with the -value "newRedactedValueHere". +which is responsible for replacing any instance of the word "<secret>" +with the value "newRedactedValueHere". From 97d01aa5d5264cf235de059c1ebefa277736147d Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai Date: Mon, 10 Oct 2022 11:45:47 -0700 Subject: [PATCH 3/3] Update docs/logs/redaction/README.md Co-authored-by: Reiley Yang --- docs/logs/redaction/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/logs/redaction/README.md b/docs/logs/redaction/README.md index 1c6d65020a0..07fe87b94bc 100644 --- a/docs/logs/redaction/README.md +++ b/docs/logs/redaction/README.md @@ -1,6 +1,6 @@ # Redaction -This program shows an example of how to redact sensitive information from Logs. +This example shows how to redact sensitive information from Logs. In this example, we attach a custom `Processor` called `MyRedactionProcessor` which is responsible for replacing any instance of the word "<secret>" with the value "newRedactedValueHere".