Hey, I've been trying to find an answer to this in the forum but I'm not able to find anything relevant.
I want to be able to create transaction for different methods in our code.
Filtering data/db transactions etc...
The application is an standard windows service application.
If I understand correctly I need to use the Agent Public API?
I've tried to configure it but I can't seem to get it right.
Anyone here that has done this or is it impossible?
We have several windows services in our team that we want to do this for.
Some of them are TopShelf services if that makes any difference.
GregKalapos
Yes I've already added the code for the transactions.
The issue is how should I configure the APM agent?
For the application I'm working with now we have our APM settings in our app.config.
And it just hit me, is the Public Agent Api available for ECE?
The issue is how should I configure the APM agent?
You can use environment variables. If you look at the list of our configs then for every config setting you'll have a column with "Environment variable name" - e.g. to set the APM Server url the environment variable name is ELASTIC_APM_SERVER_URLS. Just make sure that the process with the agent can read this environment variable.
For the application I'm working with now we have our APM settings in our app.config.
Unfortunately if you only use the Public Agent API the agent won't read app.config - it'll only work with environment variables. You could extend the agent to read app.config, but that needs some coding. Wouldn't just using environment variables be enough?
And it just hit me, is the Public Agent Api available for ECE?
Yes, you can basically use it anywhere - once you have an APM Server that sends the data to Elasticsearch, all parts of the agent should work. ECE should be also ok.
The first .cs file helps but isn't there any code example of how to set up the agent?
Maybe I'm stupid here but I'm not quite sure on which properties to set on which object.
I just have 4 properties I want to assign my APM Agent:
ServerUrls
ServiceName
TransactionSampleRate
SecretToken
When I try to use the Elastic.Apm.Agent.Setup() method it needs a ApmLogger/IConfigurationReader/IPayLoadSender.
I can't find any documentation on how to use this method. Which I assume is the one that I should use in order to configure the APM Agent?
BR
Frutty
EDIT: It just hit me, is the intented way to implement each of the interfaces?....
EDIT 2: And to use it like this?
public class ApmConfigurationReader : IConfigurationReader
{
public ApmConfigurationReader()
{
ServiceName = ConfigurationManager.AppSettings["elasticapm.ServiceName"].Trim();
ServerUrls = new List<Uri> { new Uri(ConfigurationManager.AppSettings["elasticapm.ServerUrls"].Trim()) };
TransactionSampleRate = double.Parse(ConfigurationManager.AppSettings["elasticapm.TransactionSampleRate"].Trim());
SecretToken = ConfigurationManager.AppSettings["elasticapm.SecretToken"].Trim();
}
public string CaptureBody { get; }
public List<string> CaptureBodyContentTypes { get; }
public bool CaptureHeaders { get; }
public bool CentralConfig { get; }
public IReadOnlyList<WildcardMatcher> DisableMetrics { get; }
public string Environment { get; }
public TimeSpan FlushInterval { get; }
public IReadOnlyDictionary<string, string> GlobalLabels { get; }
public LogLevel LogLevel { get; }
public int MaxBatchEventCount { get; }
public int MaxQueueEventCount { get; }
public double MetricsIntervalInMilliseconds { get; }
public IReadOnlyList<WildcardMatcher> SanitizeFieldNames { get; }
public string SecretToken { get; }
public string ApiKey { get; }
public IReadOnlyList<Uri> ServerUrls { get; }
public string ServiceName { get; }
public string ServiceNodeName { get; }
public string ServiceVersion { get; }
public double SpanFramesMinDurationInMilliseconds { get; }
public int StackTraceLimit { get; }
public int TransactionMaxSpans { get; }
public double TransactionSampleRate { get; }
public bool UseElasticTraceparentHeader { get; }
public bool VerifyServerCert { get; }
}
//In program.cs
Agent.Setup(new AgentComponents(null, new ApmConfigurationReader(), null));
EDIT 3: Just tried this.
The Apm.Agent.Setup() relies on assembly System.Net.Http version 4.2.0.0 and I've tried to install several versions of the System.Net.Http nuget but with zero success.
@frutty you can customize the agent by passing custom components to it with Apm.Agent.Setup(), but that's optional.
If you don't call Setup(), the agent will read configs from environment variable. For all configs you pointed out in your question (ServerUrls, ServiceName, etc.), you can find the corresponding environment variable in this list (just click on each and it'll lead you to a page with the info about the setting including the environment variable names).
So unless there is a good reason to pass custom components to the agent (like a custom config reader) I'd not bother with that. Also, it's ok to just set the environment variable in C# when your service starts - this is an easy workaround I see people sometimes do.
I am also struggling with the same issue for how to setup Agent for a TopShelf .NET Core Windows service using EF Core. Do I need to use Elastic.Apm.NetCoreAll or Elastic.Apm package? Of which Object shall I set the Environment Variable? You have given good example of doing it in WEB API however it is missing for Windows Service.
Need to know what is the use of this method in your Public API sample - PassDistributedTracingData. Why it is only setting Service Name? Do I need to set others like Server Url, etc. in this function. How can I use this function and I put the transaction on my start of the process however, don't know how and where to setup the Agent. Please provide some working code sample.
public override void Work()
{
var transaction = Agent.Tracer.StartTransaction("DataUploadServiceTransaction", "DataUploadService");
try
{
Process();
}
catch(Exception ex)
{
transaction.CaptureException(ex);
}
finally
{
transaction.End();
}
}
You have given good example of doing it in WEB API however it is missing for Windows Service.
That should not change this - config reading is the same on both.
Need to know what is the use of this method in your Public API sample - PassDistributedTracingData
The DistributedTracingData parameter is documented here
Why it is only setting Service Name?
I assume you mean this line - as some of the doc above describes you can start the agent without setting any setting, in those case the agent starts with default values - it sends data to an APM server on localhost and sets the service name to the name of the entry assembly. The Public API sample is a bit special in this regard, because it starts the same assembly (executable in this case) twice to showcase distributed tracing - but given it's the same assembly it'd have the same service name. In order to avoid this, we change the service name from default to a specific one before we start the app the 2. time, this way it'll be 2 different services which is needed to better showcase distributed tracing.
Do I need to set others like Server Url, etc. in this function. How can I use this function and I put the transaction on my start of the process however, don't know how and where to setup the Agent.
I think all those were covered in above links - if not let me know.
Thanks Greg, I have gone through those links already. I have tried setting up environment variables in the Windows and also through the following code however I am not getting anything logged on Kibana APM module. I can successfully log for Web APIs. I am pasting my code below, let me know if this is not the way to do it and what is missing:
public override void Work()
{
Agent.Subscribe(new EfCoreDiagnosticsSubscriber());
var startInfo = new ProcessStartInfo();
startInfo.Environment["ELASTIC_APM_SERVICE_NAME"] = "DataUploadService";
startInfo.Environment["ELASTIC_APM_SERVER_URLS"] = "http://ec2-42-85-137-237.ap-southeast-2.compute.amazonaws.com:8200";
var outgoingDistributedTracingData = (Agent.Tracer.CurrentSpan?.OutgoingDistributedTracingData
?? Agent.Tracer.CurrentTransaction?.OutgoingDistributedTracingData)?.SerializeToString();
var transaction = Agent.Tracer.StartTransaction("DataUploadServiceTransaction", ApiConstants.ActionExec,
DistributedTracingData.TryDeserializeFromString(outgoingDistributedTracingData));
System.Diagnostics.Process.Start(startInfo);
try
{
MyProcess();
}
catch(Exception ex)
{
transaction.CaptureException(ex);
}
finally
{
transaction.End();
}
}
Yes Greg, it is running in cloud and I didn't use secret token for Web APIs and they are loggin data. BTW, can also use your help in knowing how to generate the token.
Hi Greg, I will try the secret token part and get back to you if it doesn't work. However, I got it working now without secret token. Thanks for your help.
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.