public void TestApplicationTags() { var customTags = new Dictionary <string, string> { { "customTag1", "customValue1" }, { "customTag2", "customValue2" } }; var applicationTags = new ApplicationTags.Builder("myApplication", "myServDefaultSource") .Cluster("myCluster") .Shard("myShard") .CustomTags(customTags) .Build(); var tracer = new WavefrontTracer .Builder(new ConsoleReporter(DefaultSource), applicationTags) .Build(); var span = (WavefrontSpan)tracer.BuildSpan("testOp").Start(); Assert.NotNull(span); var spanTags = span.GetTagsAsMap(); Assert.NotNull(spanTags); Assert.Equal(6, spanTags.Count); Assert.Contains(applicationTags.Application, spanTags[ApplicationTagKey]); Assert.Contains(applicationTags.Service, spanTags[ServiceTagKey]); Assert.Contains(applicationTags.Cluster, spanTags[ClusterTagKey]); Assert.Contains(applicationTags.Shard, spanTags[ShardTagKey]); Assert.Contains("customValue1", spanTags["customTag1"]); Assert.Contains("customValue2", spanTags["customTag2"]); }
public static IServiceCollection AddWavefrontProxy(this IServiceCollection services, IConfiguration configuration) { var waveFrontProxyConfiguration = configuration.GetSection(WavefrontProxyOptions.WavefrontProxy).Get <WavefrontProxyOptions>(); var wfProxyClientBuilder = new WavefrontProxyClient.Builder(waveFrontProxyConfiguration.Hostname); wfProxyClientBuilder.MetricsPort(waveFrontProxyConfiguration.Port); wfProxyClientBuilder.DistributionPort(waveFrontProxyConfiguration.DistributionPort); wfProxyClientBuilder.TracingPort(waveFrontProxyConfiguration.TracingPort); wfProxyClientBuilder.FlushIntervalSeconds(waveFrontProxyConfiguration.TracingPort); var wavefrontSender = wfProxyClientBuilder.Build(); var applicationTags = new ApplicationTags.Builder(waveFrontProxyConfiguration.Application, waveFrontProxyConfiguration.Service) .Cluster(waveFrontProxyConfiguration.Cluster) .Shard(waveFrontProxyConfiguration.Shard) .Build(); var wfAspNetCoreReporter = new WavefrontAspNetCoreReporter.Builder(applicationTags) .WithSource(waveFrontProxyConfiguration.Source) .ReportingIntervalSeconds(waveFrontProxyConfiguration.ReportingIntervalSeconds) .Build(wavefrontSender); System.Console.WriteLine(wfAspNetCoreReporter); var wavefrontSpanReporter = new WavefrontSpanReporter.Builder() .Build(wavefrontSender); ITracer tracer = new WavefrontTracer.Builder(wavefrontSpanReporter, applicationTags).Build(); services.AddWavefrontForMvc(wfAspNetCoreReporter, tracer); return(services); }
public static IServiceCollection AddWavefrontDirectIngestion(this IServiceCollection services, IConfiguration configuration) { var waveFrontDirectIngestionConfiguration = configuration.GetSection(WavefrontDirectIngestionOptions.WavefrontDirectIngestion) .Get <WavefrontDirectIngestionOptions>(); var applicationTags = new ApplicationTags.Builder(waveFrontDirectIngestionConfiguration.Application, waveFrontDirectIngestionConfiguration.Service) .Cluster(waveFrontDirectIngestionConfiguration.Cluster) .Shard(waveFrontDirectIngestionConfiguration.Shard) .Build(); var wfDirectIngestionClientBuilder = new WavefrontDirectIngestionClient.Builder(waveFrontDirectIngestionConfiguration.Hostname, waveFrontDirectIngestionConfiguration.Token); wfDirectIngestionClientBuilder.MaxQueueSize(waveFrontDirectIngestionConfiguration.MaxQueueSize); wfDirectIngestionClientBuilder.BatchSize(waveFrontDirectIngestionConfiguration.BatchSize); wfDirectIngestionClientBuilder.FlushIntervalSeconds(waveFrontDirectIngestionConfiguration.FlushIntervalSeconds); var wavefrontSender = wfDirectIngestionClientBuilder.Build(); var wfAspNetCoreReporter = new WavefrontAspNetCoreReporter.Builder(applicationTags) .WithSource(waveFrontDirectIngestionConfiguration.Source) .ReportingIntervalSeconds(waveFrontDirectIngestionConfiguration.ReportingIntervalSeconds) .Build(wavefrontSender); var wavefrontSpanReporter = new WavefrontSpanReporter.Builder() .Build(wavefrontSender); ITracer tracer = new WavefrontTracer.Builder(wavefrontSpanReporter, applicationTags).Build(); services.AddWavefrontForMvc(wfAspNetCoreReporter, tracer); return(services); }
public void TestTagFromEnv() { SetEnvVar(); var pointTags = new ApplicationTags.Builder("app1", "service1") .CustomTags(new Dictionary <string, string> { { "env", "production" }, { "location", "SF" } }) .tagFromEnv("VERSION", "ver") .Build() .ToPointTags(); Assert.Contains(new KeyValuePair <string, string>("env", "production"), pointTags); Assert.Contains(new KeyValuePair <string, string>("location", "SF"), pointTags); Assert.Contains(new KeyValuePair <string, string>("ver", "1.0"), pointTags); }
private ApplicationTags ConstructApplicationTags(IConfiguration appTagsConfig) { var appTagsBuilder = new ApplicationTags .Builder(appTagsConfig["application"], appTagsConfig["service"]) .Cluster(appTagsConfig["cluster"]) .Shard(appTagsConfig["shard"]); var customTagsConfig = appTagsConfig.GetSection("CustomTags"); var customTagsDict = new Dictionary <string, string>(); foreach (var tag in customTagsConfig.GetChildren()) { customTagsDict.Add(tag.Key, tag.Value); } appTagsBuilder.CustomTags(customTagsDict); return(appTagsBuilder.Build()); }
public void TestTagsFromEnv() { SetEnvVar(); var pointTags = new ApplicationTags.Builder("app1", "service1") .CustomTags(new Dictionary <string, string> { { "env", "production" }, { "location", "SF" } }) .tagsFromEnv("^MY.*$") .Build() .ToPointTags(); Assert.Contains(new KeyValuePair <string, string>("env", "production"), pointTags); Assert.Contains(new KeyValuePair <string, string>("location", "SF"), pointTags); Assert.Contains(new KeyValuePair <string, string>("my_var1", "var_value1"), pointTags); Assert.Contains(new KeyValuePair <string, string>("my_var2", "var_value2"), pointTags); Assert.DoesNotContain(new KeyValuePair <string, string>("not_my_var3", "var_value3"), pointTags); Assert.DoesNotContain(new KeyValuePair <string, string>("VERSION", "1.0"), pointTags); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { //Begin code instrumentation - reference https://github.com/wavefrontHQ/wavefront-opentracing-sdk-csharp //The application, service, cluster, and shard variables are all metadata to be added to each span created. string application = "VMworld2020Demo"; string service = "GlobalDataAggregator"; string cluster = "Azure"; string shard = "networknerd4"; //The URL and token are for direct ingestion of metrics, traces, and spans (no proxy in use here). //The API token can be found inside the Tanzu Observability (Wavefront) web UI and is unique to your environment. Click the gear icon in the upper right, click your e-mail address, and then select API Access. string wfURL = "https://vmware.wavefront.com"; string token = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Create ApplicationTags - for tracing purposes ApplicationTags applicationTags = new ApplicationTags.Builder(application, service).Cluster(cluster).Shard(shard).Build(); //Configure a MetricsBuilder object - for custom metrics sent via the Metrics SDK var MyMetricsBuilder = new MetricsBuilder(); //Initialize WavefrontDirectIngestionClient WavefrontDirectIngestionClient.Builder wfDirectIngestionClientBuilder = new WavefrontDirectIngestionClient.Builder(wfURL, token); // Create an IWavefrontSender instance for sending data via direct ingestion. IWavefrontSender wavefrontSender = wfDirectIngestionClientBuilder.Build(); //Configure MeetricsBuilder to Report to Wavefront with proper sender object and source tag specified. In this case my source is the function name. MyMetricsBuilder.Report.ToWavefront( options => { options.WavefrontSender = wavefrontSender; options.Source = "TruckGlobalDataAggregator"; }); //Build IMetrics instance var MyMetrics = MyMetricsBuilder.Build(); //These are arrays for key value pairs to add as metric tags. You can add some or many here as you instrument your code. string[] keys = new string[3] { "FunctionApp", "Cloud", "Region" }; string[] values = new string[3] { "networknerd4", "Azure", "Central-US" }; // Configure and instantiate a DeltaCounter using DeltaCounterOptions.Builder. The metric name is azure.function.execution.deltacounter. var myDeltaCounter = new DeltaCounterOptions.Builder("azure.function.execution.deltacounter").MeasurementUnit(Unit.Calls).Tags(new MetricTags(keys, values)).Build(); // Increment the counter by 1 MyMetrics.Measure.Counter.Increment(myDeltaCounter); //Force reporting all custom metrics await Task.WhenAll(MyMetrics.ReportRunner.RunAllAsync()); //Create a WavefrontSpanReporter for reporting trace data that originates on <sourceName>. The source is the function name in this case. IReporter wfSpanReporter = new WavefrontSpanReporter.Builder() .WithSource("TruckGlobalDataAggregator").Build(wavefrontSender); //Create CompositeReporter and ConsoleReporter objects for more OpenTracing metrics IReporter consoleReporter = new ConsoleReporter("TruckGlobalDataAggregator"); IReporter compositeReporter = new CompositeReporter(wfSpanReporter, consoleReporter); //Create the WavefrontTracer. WavefrontTracer MyTracer = new WavefrontTracer.Builder(wfSpanReporter, applicationTags).Build(); //The variable MyDictionary is needed to extract span context in case a call is made from another function / outside this function. IDictionary <string, string> MyDictionary = new Dictionary <string, string>(); foreach (var entry in req.Headers) { MyDictionary.TryAdd(entry.Key, entry.Value); } //Attempt to pull span fontext from HTTP headers passed into this function to continue a span across environments. The proper context will be loaded into the variable //ctx if so. The second line of code loads all metadata from the span context. ITextMap carrier = new TextMapExtractAdapter(MyDictionary); OpenTracing.ISpanContext ctx = MyTracer.Extract(BuiltinFormats.HttpHeaders, carrier); OpenTracing.IScope receivingScope = MyTracer.BuildSpan("TruckGlobalDataAggregator.Execute").AsChildOf(ctx).StartActive(true); //Start building a new span called TruckGlobalDataAggregator.Execute if there was no context passed into headers. if (MyTracer.ActiveSpan != null) { MyTracer.BuildSpan("TruckGlobalDataAggregator.Execute").StartActive(); } log.LogInformation("C# HTTP trigger function processed a request."); string name = req.Query["name"]; string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); name = name ?? data?.name; //Add function execution delays based on input - for personal testing only. if (string.Equals(name, "0.5")) { await Task.Delay(500); } if (string.Equals(name, "1")) { await Task.Delay(1000); } if (string.Equals(name, "1.5")) { await Task.Delay(1500); } if (string.Equals(name, "2")) { await Task.Delay(2000); } string responseMessage = string.IsNullOrEmpty(name) ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response." : $"Hello, {name}. This HTTP triggered function executed successfully."; //Finish the span MyTracer.ActiveSpan.Finish(); //Close the tracer before application exit MyTracer.Close(); return(new OkObjectResult(responseMessage)); }