Elastic APM - Object reference not set to an instance of an object

Kibana version: N/A

Elasticsearch version: N/A

APM Server version: N/A

APM Agent language and version: C# .NET 4.6.1, agent v1.7.1

Browser version: N/A

Original install method (e.g. download page, yum, deb, from source, etc.) and version: nuget

Fresh install or upgraded from other version? fresh

Is there anything special in your setup? n/a

Description of the problem including expected versus actual behavior. Please include screenshots (if relevant):

Hi, I am trying to have a semi-dynamic agent on a .net stack.
It worked on previous version, but now I get an

Object reference not set to an instance of an object.
   at Elastic.Apm.Helpers.WildcardMatcher.AnyMatch(IReadOnlyCollection`1 matchers, String firstPart, String secondPart)
   at Elastic.Apm.Metrics.MetricsCollector..ctor(IApmLogger logger, IPayloadSender payloadSender, IConfigSnapshotProvider configSnapshotProvider)
   at Elastic.Apm.AgentComponents..ctor(IApmLogger logger, IConfigurationReader configurationReader, IPayloadSender payloadSender, IMetricsCollector metricsCollector, ICurrentExecutionSegmentsContainer currentExecutionSegmentsContainer, ICentralConfigFetcher centralConfigFetcher, IApmServerInfo apmServerInfo)

My code is as follows:

class ConfigReader : IConfigurationReader
	{
		public string CaptureBody { get; set; } = "all";
		public List<string> CaptureBodyContentTypes { get; set; } = null;
		public bool CaptureHeaders { get; set; } = true;
		public bool CentralConfig { get; set; } = true;
		public string Environment { get; set; } = "production";
		public TimeSpan FlushInterval { get; set; } = TimeSpan.FromSeconds(10);
		public IReadOnlyDictionary<string, string> GlobalLabels => new Dictionary<string, string>();
		public Elastic.Apm.Logging.LogLevel LogLevel { get; set; } = Elastic.Apm.Logging.LogLevel.Debug;
		public int MaxBatchEventCount { get; set; } = 1000;
		public int MaxQueueEventCount { get; set; } = 1000;
		public double MetricsIntervalInMilliseconds { get; set; }
		public IReadOnlyList<WildcardMatcher> SanitizeFieldNames { get; set; }
		public string SecretToken { get; set; }
		public IReadOnlyList<Uri> ServerUrls { get; set; }
		public string ServiceName{ get; set; }
		public string ServiceVersion { get; set; }
		public double SpanFramesMinDurationInMilliseconds { get; set; } = 100;
		public int StackTraceLimit { get; set; } = 100;
		public int TransactionMaxSpans { get; set; } = 500;
		public double TransactionSampleRate { get; set; } = 1.0;
        public string ApiKey { get; set; }
		public IReadOnlyCollection<string> ApplicationNamespaces { get; set; }
		public string CloudProvider { get; set; }
		public IReadOnlyList<WildcardMatcher> DisableMetrics { get; set; }
		public bool Enabled { get; set; } = true;
        public IReadOnlyCollection<string> ExcludedNamespaces { get; set; }
		public string HostName { get; set; }
		public bool Recording { get; set; } = true;
		public string ServiceNodeName { get; set; }
		public IReadOnlyList<WildcardMatcher> TransactionIgnoreUrls { get; set; }
		public bool UseElasticTraceparentHeader { get; set; }
		public bool VerifyServerCert { get; set; }
		public ConfigReader(string ssServerUrl, string ssSecretToken, string ssServiceName, string ssServiceVersion, int ssMetricsIntervalMs)
		{
			ServerUrls = new List<Uri>	{new Uri(ssServerUrl)};
			ServiceName = ssServiceName;
			ServiceVersion = ssServiceVersion;
			SecretToken = ssSecretToken;
			MetricsIntervalInMilliseconds = ssMetricsIntervalMs;
		}
	}

someInitAction(...) {
if (!Agent.IsConfigured)
    			{
    				var configReader = new ConfigReader(ssServerUrl, ssSecretToken, ssServiceName, ssServiceVersion, ssMetricsIntervalMs)
    				{
    					Environment = AppInfo.GetAppInfo().EnvironmentName
    				};
    				Agent.Setup(new AgentComponents(null, configReader, null));
    				Agent.Subscribe(new HttpDiagnosticsSubscriber());
    			}
    			ssSuccess = Agent.IsConfigured;
}

Hi @LandgrafJ,

My first candidate is the IReadOnlyList<WildcardMatcher> DisableMetrics in your ConfigReader.

It seems our Elastic.Apm.Helpers.WildcardMatcher can't handle when it gets a null in the IReadOnlyList<WildcardMatcher> parameter and that comes from the DisableMetrics property of IConfigurationReader.

Could you try to return an empty list for the DisableMetrics property instead of null as an immediate workaround?

Having said that - I'd say the agent should be able to deal with an IConfigurationReader which returns null for DisableMetrics. I'll look into that and try to see if we can fix it in a future version.

Hi,

Yes, that workaround did the trick.
But indeed it's a bit unexpected.

I opened a PR to make sure this doesn't happen in the future.

1 Like