-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Console Trace link writer #222
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution 👍🏻
I like what you've done and I think it's heading in the right direction. I've left some comments to make use of existing Options values and suggested some other things.
I've focused on external config & behaviour as internals can be updated later and this is likely a debug tool rather than being activated in production systems.
namespace Honeycomb.OpenTelemetry | ||
{ | ||
/// <summary> | ||
/// Writes links to the Honeycomb for all root spans |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Writes links to the Honeycomb for all root spans | |
/// Writes links to the Console for all root spans | |
/// </summary> | ||
public class ConsoleLinkExporter : BaseExporter<Activity> | ||
{ | ||
private readonly HoneycombOptions _options; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only need the service name outside of init, let's capture that instead directly instead of keeping a reference to the whole options object.
public class ConsoleLinkExporter : BaseExporter<Activity> | ||
{ | ||
private readonly HoneycombOptions _options; | ||
private string _teamSlug; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think getting the team and environment slugs could be reusable so may end up being passed in instead of being resolved inside this span processor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we should be calling out via http as part of startup in any other environment than production. It's an async call in a sync method, and I don't like it all. As it stands, because it's in the ConsoleLinkExporter, it won't be triggered unless you ask for tracelinks.
I think that's probably an internal decision too, so we can refactor that as and when we need it.
var httpClient = new HttpClient(); | ||
httpClient.BaseAddress = new Uri("https://api.honeycomb.io/1/auth"); | ||
httpClient.DefaultRequestHeaders.Add("X-Honeycomb-Team", _options.ApiKey); | ||
|
||
var response = httpClient.GetAsync("").GetAwaiter().GetResult(); | ||
if (!response.IsSuccessStatusCode) { | ||
Console.WriteLine("Didn't get a valid response from Honeycomb"); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use _options.TracesEndpoint instead of hardcoding.
var httpClient = new HttpClient(); | |
httpClient.BaseAddress = new Uri("https://api.honeycomb.io/1/auth"); | |
httpClient.DefaultRequestHeaders.Add("X-Honeycomb-Team", _options.ApiKey); | |
var response = httpClient.GetAsync("").GetAwaiter().GetResult(); | |
if (!response.IsSuccessStatusCode) { | |
Console.WriteLine("Didn't get a valid response from Honeycomb"); | |
return; | |
} | |
var httpClient = new HttpClient(); | |
httpClient.BaseAddress = new Uri(_options.TracesEndpoint); | |
httpClient.DefaultRequestHeaders.Add("X-Honeycomb-Team", _options.ApiKey); | |
var response = httpClient.GetAsync("1/auth").GetAwaiter().GetResult(); | |
if (!response.IsSuccessStatusCode) { | |
Console.WriteLine("Didn't get a valid response from Honeycomb"); | |
return; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that someone can override the traces endpoint, is that an issue? My worry would be people overriding that, and not having the auth API... maybe I'm being a little over cautious?
var authResponse = JsonSerializer.Deserialize<AuthResponse>(responseString); | ||
_environmentSlug = authResponse.Environment.Slug; | ||
_teamSlug = authResponse.Team.Slug; | ||
if (string.IsNullOrEmpty(_environmentSlug) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can generate trace links for classic datasets, it just needs to omit the environment segments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we detect if it's a classic dataset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we detect if it's a classic dataset?
Classic (nee Legacy) API key is 32 characters:
internal bool IsTracesLegacyKey() |
{ | ||
if (string.IsNullOrEmpty(activity.ParentId)) | ||
{ | ||
Console.WriteLine($"Trace Emitted for {activity.DisplayName}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to expand this in the future to write to an ILogger
instead of directly to console. Then users can select where they want these to appear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually don't want it going through the logging framework, as that could take it into other pipelines, and this is specifically for local development.
@@ -16,6 +16,7 @@ internal class EnvironmentOptions | |||
private const string SampleRateKey = "HONEYCOMB_SAMPLE_RATE"; | |||
private const string ServiceNameKey = "SERVICE_NAME"; | |||
private const string ServiceVersionKey = "SERVICE_VERSION"; | |||
private const string WriteTraceLinksToConsoleKey = "WRITE_TRACE_LINKS_TO_CONSOLE"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels long, maybe LOG_TRACE_LINKS
. If we do go along the route of using an ILogger in the future, these trace links may go elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using Console is more universal I think, and also keeps it specific to enviroments where you have access to the console.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in zoom convo, we thought ENABLE_LOCAL_VISUALIZATIONS
would work nicely, as a more generic "mode" setting that is not too specific with what we're writing where
/// <summary> | ||
/// Write links to honeycomb traces as they come in | ||
/// </summary> | ||
public bool WriteTraceLinksToConsole |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should match env var above.
@@ -193,7 +203,8 @@ public string MetricsEndpoint | |||
/// (Optional) Options delegate to configure StackExchange.Redis instrumentation. | |||
/// </summary> | |||
public Action<StackExchangeRedisCallsInstrumentationOptions> | |||
ConfigureStackExchangeRedisClientInstrumentationOptions { get; set; } | |||
ConfigureStackExchangeRedisClientInstrumentationOptions | |||
{ get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this intentional, or did your IDE move this?
@@ -220,6 +231,7 @@ public string MetricsEndpoint | |||
{ "--honeycomb-traces-endpoint", "tracesendpoint" }, | |||
{ "--honeycomb-metrics-endpoint", "metricsendpoint" }, | |||
{ "--honeycomb-samplerate", "samplerate" }, | |||
{ "--honeycomb-write-trace-links-to-console", "writetracelinkstoconsole" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should match env var
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed feedback
@@ -16,6 +16,7 @@ internal class EnvironmentOptions | |||
private const string SampleRateKey = "HONEYCOMB_SAMPLE_RATE"; | |||
private const string ServiceNameKey = "SERVICE_NAME"; | |||
private const string ServiceVersionKey = "SERVICE_VERSION"; | |||
private const string WriteTraceLinksToConsoleKey = "WRITE_TRACE_LINKS_TO_CONSOLE"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using Console is more universal I think, and also keeps it specific to enviroments where you have access to the console.
public class ConsoleLinkExporter : BaseExporter<Activity> | ||
{ | ||
private readonly HoneycombOptions _options; | ||
private string _teamSlug; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we should be calling out via http as part of startup in any other environment than production. It's an async call in a sync method, and I don't like it all. As it stands, because it's in the ConsoleLinkExporter, it won't be triggered unless you ask for tracelinks.
I think that's probably an internal decision too, so we can refactor that as and when we need it.
var httpClient = new HttpClient(); | ||
httpClient.BaseAddress = new Uri("https://api.honeycomb.io/1/auth"); | ||
httpClient.DefaultRequestHeaders.Add("X-Honeycomb-Team", _options.ApiKey); | ||
|
||
var response = httpClient.GetAsync("").GetAwaiter().GetResult(); | ||
if (!response.IsSuccessStatusCode) { | ||
Console.WriteLine("Didn't get a valid response from Honeycomb"); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that someone can override the traces endpoint, is that an issue? My worry would be people overriding that, and not having the auth API... maybe I'm being a little over cautious?
var authResponse = JsonSerializer.Deserialize<AuthResponse>(responseString); | ||
_environmentSlug = authResponse.Environment.Slug; | ||
_teamSlug = authResponse.Team.Slug; | ||
if (string.IsNullOrEmpty(_environmentSlug) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we detect if it's a classic dataset?
{ | ||
if (string.IsNullOrEmpty(activity.ParentId)) | ||
{ | ||
Console.WriteLine($"Trace Emitted for {activity.DisplayName}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually don't want it going through the logging framework, as that could take it into other pipelines, and this is specifically for local development.
Console.WriteLine($"Trace Emitted for {activity.DisplayName}"); | ||
Console.WriteLine($"TraceLink: {GetTraceLink(activity.TraceId.ToString())}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind that this is just for the root span, not all spans, so even in large volume applications, we should only see a small amount of spans.
1 line is actually pretty long as the url is already quite long, which is why I extended it to 2. Happy to hear thoughts though, I'm not 100% convinced this is right.
private string GetTraceLink(string traceId) | ||
{ | ||
var dataset = _options.ServiceName; | ||
return $"http://ui.honeycomb.io/{_teamSlug}/environments/{_environmentSlug}/datasets/{dataset}/trace?trace_id={traceId}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I have a way of knowing that it's a classic just from the ApiKey or settings, then I'm happy to add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good - thanks @martinjt 👍🏻
I'm happy with the changes to external API (env var / settings.json) and what it outputs. The remainder is internal logic and can be iterated on as we wish.
Circle is being weird, but I triggered the run by creating another branch off this PR. There's an error trying to run tests: |
Looks like Circle may not have .NET 6 in their orb |
STILL?! ugh |
That's my bad... I didn't mean to upgrade the projects to .NET 6. I'll
revert
…On Thu, 28 Jul 2022, 19:10 Phillip Carter, ***@***.***> wrote:
STILL?! ugh
—
Reply to this email directly, view it on GitHub
<#222 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAM66AYSEZSRS563N2D3UIDVWLEJRANCNFSM54N2ZTTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***
com>
|
It's quite reasonable to do that, though. Blegh. It also means having a minimal apis example can't be done yet either. :shakes-fist-at-circle-ci: |
I've added an install step to the CI build @cartermp , happy to revert to .NET 5 if we need to though. I can't trigger the build, so let me know if it works. |
Reverted this to .NET 5.0 as it was only the test project at this stage. I'll investigate separately how we add .NET 6.0 inside the pipeline. |
Adds a link exporter that writes all root spans to the console with a link to honeycomb for viewing it.