public QueryStringMaskingRule(string field, params TextMaskingRule[] rules)
        {
            Field = field;
            FieldMaskingRules.AddRange(rules);
            Mask = new FuncMask(new Func <string, string>(target =>
            {
                var keyMap     = new Dictionary <string, string>();
                var copy       = new Dictionary <string, string>();
                var startIndex = target.IndexOf("?") + 1;
                var payload    = startIndex >= 1 ? target.Substring(startIndex) : target;

                foreach (var param in payload?.Split('&')?.Select(x => x.Split('=')))
                {
                    keyMap[param[0]] = param[1];
                }
                ;

                foreach (KeyValuePair <string, string> kvp in keyMap)
                {
                    var rule = FindMaskingRule(kvp.Key);
                    if (rule != null)
                    {
                        var value     = keyMap[kvp.Key].Trim();
                        copy[kvp.Key] = rule != null && rule.Mask != null ? rule.Mask.Mask(value) : Masks.DefaultMask.Mask(value);
                    }
                    else
                    {
                        copy[kvp.Key] = keyMap[kvp.Key];
                    }
                }

                return((startIndex >= 1 ? target.Substring(0, startIndex) : string.Empty) + String.Join("&", copy.Select(x => string.Format("{0}={1}", x.Key, x.Value)).ToArray()));
            }));
        }
        public void Should_Mask_Json_Payload()
        {
            var id     = Convert.ToString(Guid.NewGuid());
            var apiLog = Utility.GetApiLog();

            apiLog.Id = id;

            List <PayloadFieldMaskingRule> rules = new List <PayloadFieldMaskingRule>();
            IMask CreditCardMask = new FuncMask(CreditcardMask.Mask);

            rules.Add(new PayloadFieldMaskingRule()
            {
                Path = "paymentMethod.cards[0].num", Mask = CreditCardMask
            });
            var jsonPayloadMaskingRule = new JsonPayloadMaskingRule("request", rules.ToArray());
            var filter = new StreamLogMaskingFilter(new PayloadMaskingRule[] { jsonPayloadMaskingRule });

            Assert.IsNotNull(filter.Rules);
            var maskedLog = filter.Apply(apiLog);

            var formatter     = JsonLogFormatter.Instance;
            var firehoseSink  = Utility.GetFirehoseSink();
            var redisSink     = Utility.GetRedisSink();
            var compositeSink = Utility.GetCompositeSink(formatter, redisSink, firehoseSink);

            var logWriter = new LogWriter(formatter, compositeSink);

            logWriter.WriteAsync(maskedLog).GetAwaiter().GetResult();
            //Thread.Sleep(40000);

            var logData = Utility.GetEsLogDataById(id);
            var esLogId = string.Empty;

            var    expectedSubstring = "444455******5555";
            string actualUrl;

            logData.TryGetValue("request", out actualUrl);
            var actual = Utility.GetOutputFromUrl(actualUrl);

            var isMasked = actual.Contains(expectedSubstring);

            Assert.IsTrue(isMasked);
        }