示例#1
0
        // this method implements the H production for the grammar
        // H -> identifier I
        private ParseResult H(Field.Kind fieldKind, TraceAggregationConfig telConfigEntry, ref List <Token> identifierList)
        {
            // check for argument name first
            Token token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected field name", this.lexAnalyzer.Position));
            }

            // checking semantics against manifest file
            ParseResult parseRes = this.semanticsAnalyzer.CheckManifestFieldKindAndDefinition(telConfigEntry.TaskName, telConfigEntry.EventName, token.Text, fieldKind, this.lexAnalyzer.Position);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // consume the argument name token
            this.lexAnalyzer.ConsumeToken();

            identifierList.Add(token);

            // try finding more aggregation kinds
            return(this.I(fieldKind, telConfigEntry, ref identifierList));
        }
示例#2
0
        // this method implements the C production for the grammar
        // C -> metric : D
        private ParseResult C(ref TraceAggregationConfig telConfigEntry)
        {
            // check for "metric" first
            Token token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier || Field.Kind.Metric != Field.CreateFieldKindFromName(token.Text))
            {
                return(new ParseResult(ParseCode.SemanticsInvalidFieldKind, "Invalid field kind specified", this.lexAnalyzer.Position));
            }

            // consume the identifier (metric) token
            this.lexAnalyzer.ConsumeToken();

            // check for :
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Colon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected : ", this.lexAnalyzer.Position));
            }

            // consume the : token
            this.lexAnalyzer.ConsumeToken();

            return(this.D(Field.Kind.Metric, ref telConfigEntry));
        }
示例#3
0
        // this method implements the D production for the grammar
        // D -> E F G
        private ParseResult D(Field.Kind fieldKind, ref TraceAggregationConfig telConfigEntry)
        {
            // try parsing E , i.e get the param names
            List <Token> fieldTokenList = new List <Token>();
            ParseResult  parseRes       = this.E(fieldKind, telConfigEntry, ref fieldTokenList);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // get the field names
            List <Field> fieldParamList;

            parseRes = SemanticsAnalyzer.CreateFieldsFromTokenList(fieldTokenList, fieldKind, out fieldParamList);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // try parsing F , i.e get the aggregation kinds
            List <Token> aggregationParamList = new List <Token>();

            parseRes = this.F(ref aggregationParamList);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // check if the aggregation kinds are valid
            List <Aggregation.Kinds> aggregationKindsList;

            parseRes = SemanticsAnalyzer.CreateAggregationKindsFromTokenList(aggregationParamList, fieldKind, out aggregationKindsList);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // sucessfully parsed the aggregation entry E F
            // setting the current aggregation entry
            telConfigEntry.AddAggregationEntries(fieldParamList, aggregationKindsList);

            // try to find a new aggregation G
            parseRes = this.G(ref telConfigEntry);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            return(new ParseResult(ParseCode.Success));
        }
        public EnvironmentTelemetry(
            string clusterType,
            string serviceFabricVersion,
            string clusterDevType)
        {
            // getting hardware information
            int  processorCount;
            long physicalMemoryInKB;

            EnvironmentTelemetry.GetSystemInfo(out processorCount, out physicalMemoryInKB);

            // getting disk and drive info
            string disks  = "[]";
            string drives = "[]";

            try
            {
#if !DotNetCoreClrLinux && !DotNetCoreClrIOT
                disks  = JsonConvert.SerializeObject(DiskInfoTelemetry.GetAllDisks());
                drives = JsonConvert.SerializeObject(DriveInfoTelemetry.GetAllDrives());
#endif
            }
            catch (Exception e)
            {
                // catching any exception for safety in case it fails for some reason
                // otherwise it will crash DCA everytime and prevent other telemetry to be sent
                EnvironmentTelemetry.traceSource.WriteError(LogSourceId, "Failed trying to get information about disks and drives. {0}", e);
            }

            // getting OS information
            string operatingSystem;
            string operatingSystemVersion;
            EnvironmentTelemetry.GetOperatingSystemInfo(out operatingSystem, out operatingSystemVersion);

            // populating the properties list with arguments
            this.Properties = new Dictionary <string, string>();
            this.Properties.Add(ClusterTypeStr, clusterType);
            this.Properties.Add(ServiceFabricVersionStr, serviceFabricVersion);
            this.Properties.Add(ClusterDevTypeStr, clusterDevType);
            this.Properties.Add(DisksStr, disks);
            this.Properties.Add(DrivesStr, drives);
            this.Properties.Add(OperatingSystemStr, operatingSystem);
            this.Properties.Add(OperatingSystemVersionStr, operatingSystemVersion);

            // populating the metrics list with arguments
            this.Metrics = new Dictionary <string, double>();
            this.Metrics.Add(ProcessorCountStr, (double)processorCount);
            this.Metrics.Add(PhysicalMemoryInKBStr, (double)physicalMemoryInKB);

            this.TraceAggregationCfg = TraceAggregationConfig.CreateSnapshotTraceAggregatorConfig(TaskNameStr, EventNameStr, string.Empty, this.Properties.Keys, this.Metrics.Keys);
        }
示例#5
0
        // this method implements the G production for the grammar
        // G -> , A | \epsilon
        private ParseResult G(ref TraceAggregationConfig telConfigEntry)
        {
            // check for , first
            Token token = this.lexAnalyzer.GetCurrentToken();

            // \epsilon case
            if (token.Id != TokenId.Comma)
            {
                return(new ParseResult(ParseCode.Success));
            }

            // consume the , token
            this.lexAnalyzer.ConsumeToken();

            return(this.A(ref telConfigEntry));
        }
示例#6
0
        // this method implements the I production for the grammar
        // I -> , H | \epsilon
        private ParseResult I(Field.Kind fieldKind, TraceAggregationConfig telConfigEntry, ref List <Token> identifierList)
        {
            // check for , first
            Token token = this.lexAnalyzer.GetCurrentToken();

            // \epsilon case
            if (token.Id != TokenId.Comma)
            {
                return(new ParseResult(ParseCode.Success, string.Empty, this.lexAnalyzer.Position));
            }

            // consume the , token
            this.lexAnalyzer.ConsumeToken();

            return(this.H(fieldKind, telConfigEntry, ref identifierList));
        }
示例#7
0
        // This method starts the parsing of a new line in the input configuration file
        // this method implements the
        // L -> Comment | EOL | T
        private ParseResult L(out TraceAggregationConfig telConfigEntry)
        {
            telConfigEntry = null;

            // getting next Token;
            Token token = this.lexAnalyzer.GetCurrentToken();

            // check for EmptyLine first
            if (token.Id == TokenId.EOL)
            {
                return(new ParseResult(ParseCode.EmptyLine));
            }

            if (token.Id == TokenId.Comment)
            {
                return(new ParseResult(ParseCode.Comment));
            }

            return(this.T(out telConfigEntry));
        }
        private static EventTelemetry ConvertAggregationToTelemetry(TraceAggregationConfig traceAggregationConfig, TraceAggregator traceAggregator, TelemetryIdentifiers telemetryIds, int telBatchesDaily, int telBatchNumber)
        {
            EventTelemetry eventEntity = AppInsightsTelemetryWriter.CreateBaseEventTelemetry(telemetryIds, traceAggregationConfig.TaskName, traceAggregationConfig.EventName, telBatchesDaily, telBatchNumber, traceAggregator.TraceTimestamp);

            Dictionary <string, string> properties;
            Dictionary <string, double> metrics;

            traceAggregator.CurrentFormattedFieldAggregationsValues(out properties, out metrics);

            foreach (var property in properties)
            {
                eventEntity.Properties[property.Key] = property.Value;
            }

            foreach (var metric in metrics)
            {
                eventEntity.Metrics[metric.Key] = metric.Value;
            }

            return(eventEntity);
        }
示例#9
0
        // this method implements the E production for the grammar
        // E -> ( H )
        private ParseResult E(Field.Kind fieldKind, TraceAggregationConfig telConfigEntry, ref List <Token> identifierList)
        {
            // check for ( first
            Token token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.OpenParenthesis)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected (", this.lexAnalyzer.Position));
            }

            // consume the ( token
            this.lexAnalyzer.ConsumeToken();

            // try parsing H , i.e get the param names
            List <string> fieldParamList = new List <string>();
            ParseResult   parseRes       = this.H(fieldKind, telConfigEntry, ref identifierList);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // A semantics check could be done here later against the trace manifest file

            // check for )
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.CloseParenthesis)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected )", this.lexAnalyzer.Position));
            }

            // consume the ) token
            this.lexAnalyzer.ConsumeToken();

            return(new ParseResult(ParseCode.Success));
        }
示例#10
0
        public TelemetryPerformanceInstrumentation()
        {
            string[] metrics    = new string[] { ProcessingEventsMeasuredTimeStr };
            string[] properties = new string[] { };
            List <Aggregation.Kinds> metricAggr = new List <Aggregation.Kinds>()
            {
                Aggregation.Kinds.Snapshot,
                Aggregation.Kinds.Minimum,
                Aggregation.Kinds.Maximum,
                Aggregation.Kinds.Count,
                Aggregation.Kinds.Sum,
                Aggregation.Kinds.Average,
                Aggregation.Kinds.Variance
            };

            this.TraceAggregationCfg = TraceAggregationConfig.CreateTraceAggregatorConfig(
                TaskNameStr,
                EventNameStr,
                string.Empty,
                properties,
                new List <Aggregation.Kinds>(),
                metrics,
                metricAggr);
        }
示例#11
0
        // this method implements the B production for the grammar
        // A -> B | C
        private ParseResult A(ref TraceAggregationConfig telConfigEntry)
        {
            // check for "string" first
            Token token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Identifier expected", this.lexAnalyzer.Position));
            }

            Field.Kind fieldKind = Field.CreateFieldKindFromName(token.Text);

            switch (fieldKind)
            {
            case Field.Kind.Property:
                return(this.B(ref telConfigEntry));

            case Field.Kind.Metric:
                return(this.C(ref telConfigEntry));

            default:
                return(new ParseResult(ParseCode.SemanticsInvalidFieldKind, "Invalid field kind specified - Expecting \"metric\" or \"property\"", this.lexAnalyzer.Position));
            }
        }
示例#12
0
        public void TestMetricsAggregations()
        {
            // initializing the configuration of the aggregation for a single field with all types of aggregation
            string[] properties = { };
            string[] metrics    = { "metric1", "metric2" };

            Aggregation.Kinds[] aggrKindsProperties = { };

            Aggregation.Kinds[] aggrKindsMetrics =
            {
                Aggregation.Kinds.Average,
                Aggregation.Kinds.Count,
                Aggregation.Kinds.Maximum,
                Aggregation.Kinds.Minimum,
                Aggregation.Kinds.Snapshot,
                Aggregation.Kinds.Sum,
                Aggregation.Kinds.Variance
            };

            TraceAggregationConfig traceAggrconfig = TraceAggregationConfig.CreateTraceAggregatorConfig(
                "TestTaskName",
                "TestEventName",
                string.Empty,
                properties,
                aggrKindsProperties,
                metrics,
                aggrKindsMetrics);

            // create the trace aggregator
            TraceAggregator traceAggr = new TraceAggregator(traceAggrconfig);

            // creating some metric values to test the aggregations
            KeyValuePair <string, double>[] metricValues =
            {
                new KeyValuePair <string, double>("metric1", 0.0),
                new KeyValuePair <string, double>("metric2", 1.0)
            };

            // aggregating
            traceAggr.Aggregate(metricValues);

            Dictionary <string, double> metricResults;
            Dictionary <string, string> propResults;

            traceAggr.CurrentFormattedFieldAggregationsValues(out propResults, out metricResults);

            // checking whether metric values are properly set
            Assert.AreEqual(0.0, metricResults["metric1_Snapshot"]);
            Assert.AreEqual(1.0, metricResults["metric1_Count"]);
            Assert.AreEqual(0.0, metricResults["metric1_Minimum"]);
            Assert.AreEqual(0.0, metricResults["metric1_Maximum"]);
            Assert.AreEqual(0.0, metricResults["metric1_Sum"]);
            Assert.AreEqual(0.0, metricResults["metric1_Average"]);
            Assert.AreEqual(0.0, metricResults["metric1_Variance"]);

            Assert.AreEqual(1.0, metricResults["metric2_Snapshot"]);
            Assert.AreEqual(1.0, metricResults["metric2_Count"]);
            Assert.AreEqual(1.0, metricResults["metric2_Minimum"]);
            Assert.AreEqual(1.0, metricResults["metric2_Maximum"]);
            Assert.AreEqual(1.0, metricResults["metric2_Sum"]);
            Assert.AreEqual(1.0, metricResults["metric2_Average"]);
            Assert.AreEqual(0.0, metricResults["metric2_Variance"]);

            // creating second set of metrics to test the aggregations
            KeyValuePair <string, double>[] metricValues2 =
            {
                new KeyValuePair <string, double>("metric1", -1.0),
                new KeyValuePair <string, double>("metric2",  2.0),
                new KeyValuePair <string, double>("metric3", 3.0)
            };

            traceAggr.Aggregate(metricValues2);

            traceAggr.CurrentFormattedFieldAggregationsValues(out propResults, out metricResults);

            Assert.AreEqual(-1.0, metricResults["metric1_Snapshot"]);
            Assert.AreEqual(2.0, metricResults["metric1_Count"]);
            Assert.AreEqual(-1.0, metricResults["metric1_Minimum"]);
            Assert.AreEqual(0.0, metricResults["metric1_Maximum"]);
            Assert.AreEqual(-1.0, metricResults["metric1_Sum"]);
            Assert.AreEqual(-0.5, metricResults["metric1_Average"]);
            Assert.AreEqual(0.5, metricResults["metric1_Variance"]);

            Assert.AreEqual(2.0, metricResults["metric2_Snapshot"]);
            Assert.AreEqual(2.0, metricResults["metric2_Count"]);
            Assert.AreEqual(1.0, metricResults["metric2_Minimum"]);
            Assert.AreEqual(2.0, metricResults["metric2_Maximum"]);
            Assert.AreEqual(3.0, metricResults["metric2_Sum"]);
            Assert.AreEqual(1.5, metricResults["metric2_Average"]);
            Assert.AreEqual(0.5, metricResults["metric2_Variance"]);

            // checking whether "metric3" which is not part of of the configuration added values
            Assert.AreEqual(14, metricResults.Values.Count);

            // checking whether any value was added by mistake to the properties
            Assert.IsTrue(propResults.Count == 0);
        }
示例#13
0
        public void TestPropertiesAggregations()
        {
            // initializing the configuration of the aggregation for a single field with all types of aggregation
            string[] properties = { "prop1", "prop2", "prop3", "prop4" };
            string[] metrics    = { };

            Aggregation.Kinds[] aggrKindsProperties =
            {
                Aggregation.Kinds.Count,
                Aggregation.Kinds.Snapshot
            };

            Aggregation.Kinds[] aggrKindsMetrics = { };

            TraceAggregationConfig traceAggrconfig = TraceAggregationConfig.CreateTraceAggregatorConfig(
                "TestTaskName",
                "TestEventName",
                string.Empty,
                properties,
                aggrKindsProperties,
                metrics,
                aggrKindsMetrics);

            // create the trace aggregator
            TraceAggregator traceAggr = new TraceAggregator(traceAggrconfig);

            // creating some property values to test the aggregations
            KeyValuePair <string, double>[] metricValues = { };

            KeyValuePair <string, string>[] propertyValues =
            {
                new KeyValuePair <string, string>("prop1", null),
                new KeyValuePair <string, string>("prop2", string.Empty),
                new KeyValuePair <string, string>("prop3", "test1"),
                new KeyValuePair <string, string>("prop4", "test2")
            };

            // aggregating
            traceAggr.Aggregate(propertyValues);

            Dictionary <string, double> metricResults;
            Dictionary <string, string> propResults;

            traceAggr.CurrentFormattedFieldAggregationsValues(out propResults, out metricResults);

            // checking whether metric values are properly set
            Assert.AreEqual(null, propResults["prop1_Snapshot"]);
            Assert.AreEqual(string.Empty, propResults["prop2_Snapshot"]);
            Assert.AreEqual("test1", propResults["prop3_Snapshot"]);
            Assert.AreEqual("test2", propResults["prop4_Snapshot"]);

            // the count should go to the metrics since it is a number
            Assert.IsFalse(propResults.ContainsKey("prop1_Count"));
            Assert.IsFalse(propResults.ContainsKey("prop2_Count"));
            Assert.IsFalse(propResults.ContainsKey("prop3_Count"));
            Assert.IsFalse(propResults.ContainsKey("prop4_Count"));

            // checks that all have count of 1
            Assert.AreEqual(1.0, metricResults["prop1_Count"]);
            Assert.AreEqual(1.0, metricResults["prop2_Count"]);
            Assert.AreEqual(1.0, metricResults["prop3_Count"]);
            Assert.AreEqual(1.0, metricResults["prop4_Count"]);

            // creating second set of propertis to test the aggregations
            KeyValuePair <string, string>[] propertyValues2 =
            {
                new KeyValuePair <string, string>("prop4", "test2NewValue"),
                new KeyValuePair <string, string>("prop5", "notPartOfAggregator")
            };

            traceAggr.Aggregate(propertyValues2);

            traceAggr.CurrentFormattedFieldAggregationsValues(out propResults, out metricResults);

            // checking whether new values are properly set prop1, prop2, prop3 should have the same value
            Assert.AreEqual(null, propResults["prop1_Snapshot"]);
            Assert.AreEqual(string.Empty, propResults["prop2_Snapshot"]);
            Assert.AreEqual("test1", propResults["prop3_Snapshot"]);
            Assert.AreEqual("test2NewValue", propResults["prop4_Snapshot"]);

            Assert.IsFalse(metricResults.ContainsKey("prop5_Count"));
            Assert.IsFalse(propResults.ContainsKey("prop5_Count"));
            Assert.IsFalse(propResults.ContainsKey("prop5_Snapshot"));

            // checks that all have count of 1 but prop4 which should have 2
            Assert.AreEqual(1.0, metricResults["prop1_Count"]);
            Assert.AreEqual(1.0, metricResults["prop2_Count"]);
            Assert.AreEqual(1.0, metricResults["prop3_Count"]);
            Assert.AreEqual(2.0, metricResults["prop4_Count"]);

            // checking whether "metric3" which is not part of of the configuration added values
            Assert.AreEqual(4, metricResults.Values.Count);
            Assert.AreEqual(4, propResults.Values.Count);
        }
示例#14
0
        public static bool ReadFieldsFromEventRecord(
            EventRecord eventRecord,
            EventDefinition eventDefinition,
            TraceAggregationConfig traceAggregationConfig,
            out List <KeyValuePair <string, double> > numericalFields,
            out List <KeyValuePair <string, string> > stringFields,
            out string diffFieldValueString,
            string logSourceId)
        {
            numericalFields      = new List <KeyValuePair <string, double> >();
            stringFields         = new List <KeyValuePair <string, string> >();
            diffFieldValueString = string.Empty;

            // Figure out how many fields the event has
            int fieldCount = eventDefinition.Fields.Count;

            if (0 == fieldCount)
            {
                Utility.TraceSource.WriteError(
                    logSourceId,
                    "No fields found in event of type {0}.{1}.",
                    eventDefinition.TaskName,
                    eventDefinition.EventName);
                return(false);
            }

            // Get the field names and values
            try
            {
                ApplicationDataReader reader = new ApplicationDataReader(
                    eventRecord.UserData,
                    eventRecord.UserDataLength);

                foreach (FieldDefinition fieldDef in eventDefinition.Fields)
                {
                    var fieldValue = TelemetryUtility.GetEtwEventRecordValue(reader, fieldDef, logSourceId);
                    if (traceAggregationConfig.FieldsAndAggregationConfigs.ContainsKey(fieldDef.Name))
                    {
                        if (null != fieldValue)
                        {
                            if (fieldValue is string)
                            {
                                stringFields.Add(new KeyValuePair <string, string>(fieldDef.Name, (string)fieldValue));
                            }
                            else
                            {
                                if (fieldValue is double)
                                {
                                    numericalFields.Add(new KeyValuePair <string, double>(fieldDef.Name, (double)fieldValue));
                                }
                                else
                                {
                                    Utility.TraceSource.WriteError(
                                        logSourceId,
                                        "Unexpected field value type read. TaskName : {0}, EventName : {1}, FieldName : {2}, FieldType : {3}",
                                        eventDefinition.TaskName,
                                        eventDefinition.EventName,
                                        fieldDef.Name,
                                        fieldDef.Type.ToString());
                                }
                            }
                        }
                    }

                    // look if field is the differentiator field
                    if (traceAggregationConfig.DifferentiatorFieldName == fieldDef.Name)
                    {
                        if (null != fieldValue)
                        {
                            diffFieldValueString = fieldValue.ToString();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Utility.TraceSource.WriteError(
                    logSourceId,
                    "Failed to get all the fields of event of type {0}.{1}. Exception info: {2}.",
                    eventDefinition.TaskName,
                    eventDefinition.EventName,
                    e);
                return(false);
            }

            return(true);
        }
示例#15
0
        // extension method for telemetryCollection to aggregate from EventRecord
        public static void AggregateEventRecord(this TelemetryCollection telemetryCollection, EventRecord eventRecord, EventDefinition eventDefinition, TraceAggregationConfig traceAggregationConfig, string logSourceId)
        {
            // Reading data from eventRecord white-listed fields
            List <KeyValuePair <string, double> > numericalFields;
            List <KeyValuePair <string, string> > stringFields;
            string diffFieldValueString;

            TelemetryUtility.ReadFieldsFromEventRecord(eventRecord, eventDefinition, traceAggregationConfig, out numericalFields, out stringFields, out diffFieldValueString, logSourceId);

            telemetryCollection.Aggregate(traceAggregationConfig, diffFieldValueString, numericalFields, stringFields, DateTime.FromFileTimeUtc(eventRecord.EventHeader.TimeStamp));
        }
示例#16
0
 // checks whether the trace is whitelisted - if so outputs the traceAggregationConfig for the trace
 public bool TryGetWhitelist(string taskName, string eventName, out TraceAggregationConfig traceAggregationConfig)
 {
     // see if taskname and eventname are whitelisted and get aggregation configuration
     return(this.whiteListedEventsFromConfigFile.TryGetValue(Tuple.Create(taskName, eventName), out traceAggregationConfig));
 }
示例#17
0
        // this method implements the T production for the grammar
        // T -> T_t ; identifier ; identifier ; identifier ; A
        private ParseResult T(out TraceAggregationConfig telConfigEntry)
        {
            telConfigEntry = null;

            // getting next Token;
            Token token = this.lexAnalyzer.GetCurrentToken();

            // T_t should be 's'
            if (token.Id != TokenId.Identifier)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected u|s", this.lexAnalyzer.Position));
            }

            if (token.Text != "s")
            {
                return(new ParseResult(ParseCode.NotImplemented, "Unstructured trace not implemented yet.", this.lexAnalyzer.Position));
            }

            // look for ;
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Semicolon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected ;", this.lexAnalyzer.Position));
            }

            // look for TaskName
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected name of TaskName", this.lexAnalyzer.Position));
            }

            // save the Task name in TelemetryConfigEntry
            string telConfigEntryTaskName = token.Text;

            // look for ;
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Semicolon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected ;", this.lexAnalyzer.Position));
            }

            // look for the EventName
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected name of EventName", this.lexAnalyzer.Position));
            }

            // save the Event name in TelemetryConfigEntry
            string telConfigEntryEventName = token.Text;

            // look for ;
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Semicolon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected ;", this.lexAnalyzer.Position));
            }

            // semantics - check whether the event is defined in the etw manifest file
            ParseResult parseRes = this.semanticsAnalyzer.CheckManifestEventDefinition(telConfigEntryTaskName, telConfigEntryEventName, this.lexAnalyzer.Position);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // look for Diffentiator name which can be empty
            this.lexAnalyzer.ConsumeToken();
            token = this.lexAnalyzer.GetCurrentToken();

            if (token.Id != TokenId.Identifier && token.Id != TokenId.Semicolon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected name of field to be used as differentiator", this.lexAnalyzer.Position));
            }

            // save the Task name in TelemetryConfigEntry
            string telConfigEntryDifferentiatorFieldName;

            if (token.Id == TokenId.Identifier)
            {
                // only consume token if not empty
                this.lexAnalyzer.ConsumeToken();
                telConfigEntryDifferentiatorFieldName = token.Text;
            }
            else
            {
                telConfigEntryDifferentiatorFieldName = string.Empty;
            }

            // semantics - check whether the differentiator field exists in the manifest file in case it is provided in the config file
            if (telConfigEntryDifferentiatorFieldName != string.Empty)
            {
                parseRes = this.semanticsAnalyzer.CheckManifestFieldDefinition(telConfigEntryTaskName, telConfigEntryEventName, telConfigEntryDifferentiatorFieldName, this.lexAnalyzer.Position);
                if (parseRes.ParseCode != ParseCode.Success)
                {
                    return(parseRes);
                }
            }

            // construct the TraceAggregationConfig with the parsed TaskName, EventName, DifferentiatorField
            telConfigEntry = new TraceAggregationConfig(telConfigEntryTaskName, telConfigEntryEventName, telConfigEntryDifferentiatorFieldName);

            // look for Semicolon ;
            token = this.lexAnalyzer.GetCurrentToken();
            if (token.Id != TokenId.Semicolon)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected ;", this.lexAnalyzer.Position));
            }

            this.lexAnalyzer.ConsumeToken();

            // try to parse the aggregation information
            parseRes = this.A(ref telConfigEntry);

            if (parseRes.ParseCode != ParseCode.Success)
            {
                return(parseRes);
            }

            // look for EmptyLine
            token = this.lexAnalyzer.GetCurrentToken();
            if (token.Id != TokenId.EOL)
            {
                return(new ParseResult(ParseCode.ErrorUnexpectedToken, "Expected End of line", this.lexAnalyzer.Position));
            }

            this.lexAnalyzer.ConsumeToken();

            return(new ParseResult(ParseCode.Success));
        }