public static void Main(string[] args) { var listener = new ActivityListener { ShouldListenTo = _ => true, ActivityStopped = activity => { foreach (var(key, value) in activity.Baggage) { activity.AddTag(key, value); } } }; ActivitySource.AddActivityListener(listener); var host = CreateHostBuilder(args).Build(); SeedDb(host); host.Run(); }
public void ProcessorDoesNotBlockOnExporter() { this.activityExporter = new TestActivityExporter(async _ => await Task.Delay(500)); this.openTelemetry = Sdk.CreateTracerProvider(b => b .AddActivitySource("cijo") .AddProcessorPipeline(p => p .SetExporter(this.activityExporter) .SetExportingProcessor(e => new SimpleActivityProcessor(e)))); ActivitySource source = new ActivitySource("cijo"); var activity = source.StartActivity("somename"); // does not block var sw = Stopwatch.StartNew(); activity.Stop(); sw.Stop(); Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); var exported = this.WaitForSpans(this.activityExporter, 1, TimeSpan.FromMilliseconds(600)); Assert.Single(exported); }
public void ProcessorDoesNotBlockOnExporter() { var activityExporter = new TestActivityExporter(async _ => await Task.Delay(500)); using var openTelemetry = Sdk.CreateTracerProviderBuilder() .AddSource("random") .AddProcessor(new SimpleActivityProcessor(activityExporter)) .Build(); ActivitySource source = new ActivitySource("random"); var activity = source.StartActivity("somename"); // does not block var sw = Stopwatch.StartNew(); activity.Stop(); sw.Stop(); Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); var exported = this.WaitForSpans(activityExporter, 1, TimeSpan.FromMilliseconds(600)); Assert.Single(exported); }
public void TestActivitySourceAttachedObject() { RemoteExecutor.Invoke(() => { // All Activities created through the constructor should have same source. Assert.True(object.ReferenceEquals(new Activity("a1").Source, new Activity("a2").Source)); Assert.Equal("", new Activity("a3").Source.Name); Assert.Equal(string.Empty, new Activity("a4").Source.Version); using ActivitySource aSource = new ActivitySource("SourceToTest", "1.2.3.4"); // Ensure at least we have a listener to allow Activity creation using ActivityListener listener = new ActivityListener(); listener.ActivityStarted = activity => Assert.NotNull(activity); listener.ActivityStopped = activity => Assert.NotNull(activity); listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource); listener.SampleUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivitySamplingResult.AllData; listener.Sample = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivitySamplingResult.AllData; ActivitySource.AddActivityListener(listener); using Activity activity = aSource.StartActivity("ActivityToTest"); Assert.True(object.ReferenceEquals(aSource, activity.Source)); }).Dispose(); }
/// <summary> /// Enables OpenTelemetry. /// </summary> /// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param> /// <returns><see cref="OpenTelemetrySdk"/> instance which can be disposed on application shutdown.</returns> /// <remarks> /// Basic implementation only. Most logic from TracerBuilder will be ported here. /// </remarks> public static OpenTelemetrySdk EnableOpenTelemetry(Action <OpenTelemetryBuilder> configureOpenTelemetryBuilder) { var openTelemetryBuilder = new OpenTelemetryBuilder(); configureOpenTelemetryBuilder(openTelemetryBuilder); var openTelemetrySDK = new OpenTelemetrySdk(); ActivitySampler sampler = openTelemetryBuilder.Sampler ?? new AlwaysOnActivitySampler(); ActivityProcessor activityProcessor; if (openTelemetryBuilder.ProcessingPipelines == null || !openTelemetryBuilder.ProcessingPipelines.Any()) { // if there are no pipelines are configured, use noop processor activityProcessor = new NoopActivityProcessor(); } else if (openTelemetryBuilder.ProcessingPipelines.Count == 1) { // if there is only one pipeline - use it's outer processor as a // single processor on the tracerSdk. var processorFactory = openTelemetryBuilder.ProcessingPipelines[0]; activityProcessor = processorFactory.Build(); } else { // if there are more pipelines, use processor that will broadcast to all pipelines var processors = new ActivityProcessor[openTelemetryBuilder.ProcessingPipelines.Count]; for (int i = 0; i < openTelemetryBuilder.ProcessingPipelines.Count; i++) { processors[i] = openTelemetryBuilder.ProcessingPipelines[i].Build(); } activityProcessor = new BroadcastActivityProcessor(processors); } openTelemetrySDK.resource = openTelemetryBuilder.Resource; var activitySource = new ActivitySourceAdapter(sampler, activityProcessor, openTelemetrySDK.resource); if (openTelemetryBuilder.InstrumentationFactories != null) { foreach (var instrumentation in openTelemetryBuilder.InstrumentationFactories) { openTelemetrySDK.instrumentations.Add(instrumentation.Factory(activitySource)); } } // This is what subscribes to Activities. // Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..)); openTelemetrySDK.listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => { if (activity.IsAllDataRequested) { activity.SetResource(openTelemetrySDK.resource); } activityProcessor.OnStart(activity); }, // Callback when Activity is started. ActivityStopped = activityProcessor.OnEnd, // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames?.Contains(activitySource.Name.ToUpperInvariant()) ?? false, // The following parameter is not used now. GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> options) => ActivityDataRequest.AllData, // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => ComputeActivityDataRequest(options, sampler), }; ActivitySource.AddActivityListener(openTelemetrySDK.listener); openTelemetrySDK.activityProcessor = activityProcessor; return(openTelemetrySDK); }
public ClientSecretAuthenticationMiddleware(RequestDelegate next, IContainerResolve container, ClientSecretAuthenticationOption option) { _next = next ?? throw new ArgumentNullException(nameof(next)); if (null == container) { throw new ArgumentNullException(nameof(container)); } if (null == option) { throw new ArgumentNullException(nameof(option)); } _logger = container.Resolve <ILogger <ClientSecretAuthenticationMiddleware> >(); _option = option; if (null == option.Settings) { _logger.Technical().Warning("No settings have been provided.").Log(); return; } if (option.Settings.Values.ContainsKey(TokenKeys.ProviderIdKey)) { _hasProvider = container.TryResolve(option.Settings.Values[TokenKeys.ProviderIdKey], out _provider); } if (!_hasProvider) { _logger.Technical().Warning("No ClientSecret provider found. Skip ClientSecret capability.").Log(); return; } _hasCertificate = null != option.Certificate && !String.IsNullOrWhiteSpace(option.Certificate.SecretKey) && !String.IsNullOrWhiteSpace(option.Certificate.Name); // check the certificate exists. if (_hasCertificate) { try { var certificateInfo = new CertificateInfo { Name = option.Certificate.Name }; if (Enum.TryParse(option.Certificate.FindType, out X509FindType x509FindType)) { certificateInfo.FindType = x509FindType; } if (Enum.TryParse(option.Certificate.Location, out StoreLocation storeLocation_)) { certificateInfo.Location = storeLocation_; } if (Enum.TryParse(option.Certificate.StoreName, out StoreName storeName_)) { certificateInfo.StoreName = storeName_; } _certificate = Certificate.FindCertificate( certificateInfo.Name, certificateInfo.FindType, certificateInfo.Location, certificateInfo.StoreName); _logger.Technical().System($"Authentication with certificate secret activated.").Log(); } catch (KeyNotFoundException) { _hasCertificate = false; _logger.Technical().Error($"No certificate found with {option.Certificate.FindType} = {option.Certificate.Name} in location = {option.Certificate.Location}.").Log(); } catch (Exception ex) { _logger.Technical().Exception(ex).Log(); } } else { _logger.Technical().System($"No authentication with certificate secret.").Log(); } _activitySource = container.Resolve <IActivitySourceFactory>()?.GetArc4u(); }
public static Activity CreateActivityWithKind(ActivitySource source) { var activity = source.StartActivity("name", ActivityKind.Client); return(activity); }
public async Task IncomingRequestInstrumentationTest( bool instrument, bool filter = false, bool includeVersion = false, bool enrich = false, bool enrichmentExcecption = false) { List <Activity> stoppedActivities = new List <Activity>(); using ActivityListener activityListener = new ActivityListener { ShouldListenTo = activitySource => true, ActivityStopped = activity => stoppedActivities.Add(activity), }; ActivitySource.AddActivityListener(activityListener); TracerProvider tracerProvider = null; if (instrument) { tracerProvider = Sdk.CreateTracerProviderBuilder() .AddWcfInstrumentation(options => { if (enrich) { if (!enrichmentExcecption) { options.Enrich = (activity, eventName, message) => { switch (eventName) { case WcfEnrichEventNames.AfterReceiveRequest: activity.SetTag( "server.afterreceiverequest", WcfEnrichEventNames.AfterReceiveRequest); break; case WcfEnrichEventNames.BeforeSendReply: activity.SetTag( "server.beforesendreply", WcfEnrichEventNames.BeforeSendReply); break; } }; } else { options.Enrich = (activity, eventName, message) => { throw new Exception("Failure whilst enriching activity"); }; } } options.IncomingRequestFilter = (Message m) => { return(!filter); }; options.SetSoapMessageVersion = includeVersion; }) .Build(); } ServiceClient client = new ServiceClient( new NetTcpBinding(), new EndpointAddress(new Uri(this.serviceBaseUri, "/Service"))); try { var response = await client.ExecuteAsync( new ServiceRequest { Payload = "Hello Open Telemetry!", }).ConfigureAwait(false); } finally { if (client.State == CommunicationState.Faulted) { client.Abort(); } else { client.Close(); } tracerProvider?.Shutdown(); tracerProvider?.Dispose(); WcfInstrumentationActivitySource.Options = null; } if (instrument && !filter) { Assert.NotEmpty(stoppedActivities); Assert.Single(stoppedActivities); Activity activity = stoppedActivities[0]; Assert.Equal(WcfInstrumentationActivitySource.IncomingRequestActivityName, activity.OperationName); Assert.Equal(WcfInstrumentationConstants.WcfSystemValue, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcSystemTag).Value); Assert.Equal("http://opentelemetry.io/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcServiceTag).Value); Assert.Equal("Execute", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcMethodTag).Value); Assert.Equal(this.serviceBaseUri.Host, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostNameTag).Value); Assert.Equal(this.serviceBaseUri.Port, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostPortTag).Value); Assert.Equal("net.tcp", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelSchemeTag).Value); Assert.Equal("/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelPathTag).Value); Assert.Equal("http://opentelemetry.io/Service/ExecuteResponse", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.SoapReplyActionTag).Value); if (includeVersion) { Assert.Equal("Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.SoapMessageVersionTag).Value); } if (enrich && !enrichmentExcecption) { Assert.Equal(WcfEnrichEventNames.AfterReceiveRequest, activity.TagObjects.Single(t => t.Key == "server.afterreceiverequest").Value); Assert.Equal(WcfEnrichEventNames.BeforeSendReply, activity.TagObjects.Single(t => t.Key == "server.beforesendreply").Value); } } else { Assert.Empty(stoppedActivities); } }
public void BuildSamplingParametersHandlesCurrentActivity() { using var activitySource = new ActivitySource(nameof(this.BuildSamplingParametersHandlesCurrentActivity)); var testSampler = new TestSampler { DesiredSamplingResult = new SamplingResult(true) }; using var listener = new ActivityListener { ShouldListenTo = _ => true, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => Sdk.ComputeActivityDataRequest(options, testSampler), }; ActivitySource.AddActivityListener(listener); using (var root = activitySource.StartActivity("root")) { Assert.Equal(default(ActivitySpanId), root.ParentSpanId); // This enforces the current behavior that the traceId passed to the sampler for the // root span/activity is not the traceId actually used. Assert.NotEqual(root.TraceId, testSampler.LatestSamplingParameters.TraceId); } using (var parent = activitySource.StartActivity("parent", ActivityKind.Client)) { // This enforces the current behavior that the traceId passed to the sampler for the // root span/activity is not the traceId actually used. Assert.NotEqual(parent.TraceId, testSampler.LatestSamplingParameters.TraceId); using (var child = activitySource.StartActivity("child")) { Assert.Equal(parent.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Equal(parent.TraceId, child.TraceId); Assert.Equal(parent.SpanId, child.ParentSpanId); } } var customContext = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); using (var fromCustomContext = activitySource.StartActivity("customContext", ActivityKind.Client, customContext)) { Assert.Equal(customContext.TraceId, fromCustomContext.TraceId); Assert.Equal(customContext.SpanId, fromCustomContext.ParentSpanId); Assert.NotEqual(customContext.SpanId, fromCustomContext.SpanId); } // Preserve traceId in case span is propagated but not recorded (sampled per OpenTelemetry parlance) and // no data is requested for children spans. testSampler.DesiredSamplingResult = new SamplingResult(false); using (var root = activitySource.StartActivity("root")) { Assert.Equal(default(ActivitySpanId), root.ParentSpanId); using (var child = activitySource.StartActivity("child")) { Assert.Null(child); Assert.Equal(root.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Same(Activity.Current, root); } } }
public void TestExpectedListenersReturnValues() { RemoteExecutor.Invoke(() => { int activityStartCount = 0; int activityStopCount = 0; ActivitySource source = new ActivitySource("MultipleListenerSource"); ActivityListener [] listeners = new ActivityListener[4]; listeners[0] = new ActivityListener { ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); }, ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); }, ShouldListenTo = (activitySource) => true, GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.None, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.None }; ActivitySource.AddActivityListener(listeners[0]); Assert.Null(source.StartActivity("a1")); Assert.Equal(0, activityStartCount); Assert.Equal(0, activityStopCount); listeners[1] = new ActivityListener { ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); }, ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); }, ShouldListenTo = (activitySource) => true, GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.PropagationData, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.PropagationData }; ActivitySource.AddActivityListener(listeners[1]); using (Activity a2 = source.StartActivity("a2")) { Assert.False(a2.IsAllDataRequested); Assert.True((a2.ActivityTraceFlags & ActivityTraceFlags.Recorded) == 0); Assert.Equal(2, activityStartCount); Assert.Equal(0, activityStopCount); } Assert.Equal(activityStartCount, activityStopCount); Assert.Equal(2, activityStopCount); listeners[2] = new ActivityListener { ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); }, ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); }, ShouldListenTo = (activitySource) => true, GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.AllData, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.AllData }; ActivitySource.AddActivityListener(listeners[2]); using (Activity a3 = source.StartActivity("a3")) { Assert.True(a3.IsAllDataRequested); Assert.True((a3.ActivityTraceFlags & ActivityTraceFlags.Recorded) == 0); Assert.Equal(5, activityStartCount); Assert.Equal(2, activityStopCount); } Assert.Equal(activityStartCount, activityStopCount); Assert.Equal(5, activityStopCount); listeners[3] = new ActivityListener { ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); }, ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); }, ShouldListenTo = (activitySource) => true, GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.AllDataAndRecorded, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.AllDataAndRecorded }; ActivitySource.AddActivityListener(listeners[3]); using (Activity a4 = source.StartActivity("a4")) { Assert.True(a4.IsAllDataRequested); Assert.True((a4.ActivityTraceFlags & ActivityTraceFlags.Recorded) != 0, $"a4.ActivityTraceFlags failed: {a4.ActivityTraceFlags}"); Assert.Equal(9, activityStartCount); Assert.Equal(5, activityStopCount); } foreach (IDisposable listener in listeners) { listener.Dispose(); } Assert.Equal(activityStartCount, activityStopCount); Assert.Equal(9, activityStopCount); Assert.Null(source.StartActivity("a5")); }).Dispose(); }
public void TracerProviderSdkInvokesSamplingWithCorrectParameters() { var testSampler = new TestSampler(); using var activitySource = new ActivitySource(ActivitySourceName); using var sdk = Sdk.CreateTracerProviderBuilder() .AddSource(ActivitySourceName) .SetSampler(testSampler) .Build(); // OpenTelemetry Sdk is expected to set default to W3C. Assert.True(Activity.DefaultIdFormat == ActivityIdFormat.W3C); using (var rootActivity = activitySource.StartActivity("root")) { Assert.NotNull(rootActivity); Assert.True(rootActivity.ParentSpanId == default); // Validate that the TraceId seen by Sampler is same as the // Activity when it got created. Assert.Equal(rootActivity.TraceId, testSampler.LatestSamplingParameters.TraceId); } using (var parent = activitySource.StartActivity("parent", ActivityKind.Client)) { Assert.Equal(parent.TraceId, testSampler.LatestSamplingParameters.TraceId); using (var child = activitySource.StartActivity("child")) { Assert.Equal(child.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Equal(parent.TraceId, child.TraceId); Assert.Equal(parent.SpanId, child.ParentSpanId); } } var customContext = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); using (var fromCustomContext = activitySource.StartActivity("customContext", ActivityKind.Client, customContext)) { Assert.Equal(fromCustomContext.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Equal(customContext.TraceId, fromCustomContext.TraceId); Assert.Equal(customContext.SpanId, fromCustomContext.ParentSpanId); Assert.NotEqual(customContext.SpanId, fromCustomContext.SpanId); } // Validate that when StartActivity is called using Parent as string, // Sampling is called correctly. var act = new Activity("anything").Start(); act.Stop(); var customContextAsString = act.Id; var expectedTraceId = act.TraceId; var expectedParentSpanId = act.SpanId; using (var fromCustomContextAsString = activitySource.StartActivity("customContext", ActivityKind.Client, customContextAsString)) { Assert.Equal(fromCustomContextAsString.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Equal(expectedTraceId, fromCustomContextAsString.TraceId); Assert.Equal(expectedParentSpanId, fromCustomContextAsString.ParentSpanId); } using (var fromInvalidW3CIdParent = activitySource.StartActivity("customContext", ActivityKind.Client, "InvalidW3CIdParent")) { // OpenTelemetry ActivityContext does not support // non W3C Ids. Starting activity with non W3C Ids // will result in no activity being created. Assert.Null(fromInvalidW3CIdParent); } }
internal TracerProviderSdk( Resource resource, IEnumerable <string> sources, IEnumerable <TracerProviderBuilderSdk.DiagnosticSourceInstrumentationFactory> diagnosticSourceInstrumentationFactories, IEnumerable <TracerProviderBuilderSdk.InstrumentationFactory> instrumentationFactories, Sampler sampler, List <BaseProcessor <Activity> > processors) { this.Resource = resource; this.sampler = sampler; foreach (var processor in processors) { this.AddProcessor(processor); } if (diagnosticSourceInstrumentationFactories.Any()) { this.adapter = new ActivitySourceAdapter(sampler, this.processor); foreach (var instrumentationFactory in diagnosticSourceInstrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory(this.adapter)); } } if (instrumentationFactories.Any()) { foreach (var instrumentationFactory in instrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory()); } } var listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }, // Callback when Activity is stopped. ActivityStopped = (activity) => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }, }; if (sampler is AlwaysOnSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ActivitySamplingResult.AllDataAndRecorded : ActivitySamplingResult.None; } else if (sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ComputeActivitySamplingResult(options, sampler) : ActivitySamplingResult.None; } if (sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries // which do not depend on ActivitySources. var wildcardMode = false; // Validation of source name is already done in builder. foreach (var name in sources) { if (name.Contains('*')) { wildcardMode = true; } } if (wildcardMode) { var pattern = "^(" + string.Join("|", from name in sources select '(' + Regex.Escape(name).Replace("\\*", ".*") + ')') + ")$"; var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => regex.IsMatch(activitySource.Name); } else { var activitySources = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); foreach (var name in sources) { activitySources[name] = true; } // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name); } } ActivitySource.AddActivityListener(listener); this.listener = listener; }
internal static Activity?CreateStartedActivity(this ActivitySource source, string activityName, Dictionary <string, string>?tags = null) { if (!source.HasListeners()) { return(default);
/// <summary> /// Initializes a new instance of the <see cref="MessageMethodHandlingDecorator"/> class. /// </summary> /// <param name="handler">The handler.</param> /// <param name="tracer">The tracer.</param> /// <param name="headers">The headers.</param> public MessageMethodHandlingDecorator(IMessageMethodHandling handler, ActivitySource tracer, IStandardHeaders headers) { _handler = handler; _tracer = tracer; _headers = headers; }
internal static Activity CreateTestActivity( bool setAttributes = true, Dictionary <string, object> additionalAttributes = null, bool addEvents = true, bool addLinks = true, Resource resource = null, ActivityKind kind = ActivityKind.Client) { var startTimestamp = DateTime.UtcNow; var endTimestamp = startTimestamp.AddSeconds(60); var eventTimestamp = DateTime.UtcNow; var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan()); var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 }); var attributes = new Dictionary <string, object> { { "stringKey", "value" }, { "longKey", 1L }, { "longKey2", 1 }, { "doubleKey", 1D }, { "doubleKey2", 1F }, { "boolKey", true }, }; if (additionalAttributes != null) { foreach (var attribute in additionalAttributes) { attributes.Add(attribute.Key, attribute.Value); } } var events = new List <ActivityEvent> { new ActivityEvent( "Event1", eventTimestamp, new Dictionary <string, object> { { "key", "value" }, } ), new ActivityEvent( "Event2", eventTimestamp, new Dictionary <string, object> { { "key", "value" }, } ), }; var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan()); var activitySource = new ActivitySource(nameof(CreateTestActivity)); var activity = activitySource.StartActivity( "Name", kind, parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded), tags: setAttributes ? // TODO: reverse here for now so it matches order in tests. attributes.Reverse().Select(kvp => new KeyValuePair <string, string>(kvp.Key, kvp.Value.ToString())) : null, links: addLinks ? new[] { new ActivityLink(new ActivityContext( traceId, linkedSpanId, ActivityTraceFlags.Recorded)), } : null, startTime: startTimestamp); if (addEvents) { // TODO: reverse here for now so it matches order in tests. events.Reverse(); foreach (var evnt in events) { activity.AddEvent(evnt); } } activity.SetEndTime(endTimestamp); activity.Stop(); return(activity); }
public void ToOtlpSpanTest() { var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest)); using var rootActivity = activitySource.StartActivity("root", ActivityKind.Producer); var attributes = new Dictionary <string, object> { ["bool"] = true, ["long"] = 1L, ["string"] = "text", ["double"] = 3.14, ["unknown_attrib_type"] = new byte[] { 1 }, // TODO: update if arrays of standard attribute types are supported }; var tags = new List <KeyValuePair <string, string> >(attributes.Count); foreach (var kvp in attributes) { rootActivity.AddTag(kvp.Key, kvp.Value.ToString()); tags.Add(new KeyValuePair <string, string>(kvp.Key, kvp.Value.ToString())); } var startTime = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc); var expectedUnixTimeTicks = (ulong)(startTime.Ticks - DateTimeOffset.FromUnixTimeMilliseconds(0).Ticks); var duration = TimeSpan.FromMilliseconds(1555); rootActivity.SetStartTime(startTime); rootActivity.SetEndTime(startTime + duration); Span <byte> traceIdSpan = stackalloc byte[16]; rootActivity.TraceId.CopyTo(traceIdSpan); var traceId = traceIdSpan.ToArray(); var otlpSpan = rootActivity.ToOtlpSpan(); Assert.NotNull(otlpSpan); Assert.Equal("root", otlpSpan.Name); Assert.Equal(OtlpTrace.Span.Types.SpanKind.Producer, otlpSpan.Kind); Assert.Equal(traceId, otlpSpan.TraceId); Assert.Empty(otlpSpan.ParentSpanId); Assert.Null(otlpSpan.Status); Assert.Empty(otlpSpan.Events); Assert.Empty(otlpSpan.Links); AssertActivityTagsIntoOtlpAttributes(tags, otlpSpan.Attributes); var expectedStartTimeUnixNano = 100 * expectedUnixTimeTicks; Assert.Equal(expectedStartTimeUnixNano, otlpSpan.StartTimeUnixNano); var expectedEndTimeUnixNano = expectedStartTimeUnixNano + (duration.TotalMilliseconds * 1_000_000); Assert.Equal(expectedEndTimeUnixNano, otlpSpan.EndTimeUnixNano); var childLinks = new List <ActivityLink> { new ActivityLink(rootActivity.Context, attributes) }; var childActivity = activitySource.StartActivity( "child", ActivityKind.Client, rootActivity.Context, links: childLinks); var childEvents = new List <ActivityEvent> { new ActivityEvent("e0"), new ActivityEvent("e1", attributes) }; childActivity.AddEvent(childEvents[0]); childActivity.AddEvent(childEvents[1]); Span <byte> parentIdSpan = stackalloc byte[8]; rootActivity.Context.SpanId.CopyTo(parentIdSpan); var parentId = parentIdSpan.ToArray(); otlpSpan = childActivity.ToOtlpSpan(); Assert.NotNull(otlpSpan); Assert.Equal("child", otlpSpan.Name); Assert.Equal(OtlpTrace.Span.Types.SpanKind.Client, otlpSpan.Kind); Assert.Equal(traceId, otlpSpan.TraceId); Assert.Equal(parentId, otlpSpan.ParentSpanId); Assert.Empty(otlpSpan.Attributes); Assert.Equal(childEvents.Count, otlpSpan.Events.Count); for (var i = 0; i < childEvents.Count; i++) { Assert.Equal(childEvents[i].Name, otlpSpan.Events[i].Name); AssertOtlpAttributes(childEvents[i].Attributes.ToList(), otlpSpan.Events[i].Attributes); } childLinks.Reverse(); Assert.Equal(childLinks.Count, otlpSpan.Links.Count); for (var i = 0; i < childLinks.Count; i++) { AssertOtlpAttributes(childLinks[i].Attributes.ToList(), otlpSpan.Links[i].Attributes); } }
/// <summary> /// Initializes a new instance of the <see cref="RollbackMessageCommandHandlerDecorator"/> class. /// </summary> /// <param name="handler">The handler.</param> /// <param name="tracer">The tracer.</param> public RollbackMessageCommandHandlerDecorator(ICommandHandler <RollbackMessageCommand <string> > handler, ActivitySource tracer) { _handler = handler; _tracer = tracer; }
static void Main(string[] args) { Console.WriteLine("Peloton To Garmin"); var config = new Configuration(); Health.Set(HealthStatus.Healthy); var runtimeVersion = Environment.Version.ToString(); var os = Environment.OSVersion.Platform.ToString(); var osVersion = Environment.OSVersion.VersionString; var assembly = Assembly.GetExecutingAssembly(); var versionInfo = FileVersionInfo.GetVersionInfo(assembly.Location); var version = versionInfo.ProductVersion; try { IConfiguration configProviders = new ConfigurationBuilder() .AddJsonFile(Path.Join(Environment.CurrentDirectory, "configuration.local.json"), optional: true, reloadOnChange: true) .AddEnvironmentVariables(prefix: "P2G_") .AddCommandLine(args) .Build(); configProviders.GetSection(nameof(App)).Bind(config.App); configProviders.GetSection(nameof(Format)).Bind(config.Format); configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton); configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin); configProviders.GetSection(nameof(Observability)).Bind(config.Observability); configProviders.GetSection(nameof(Developer)).Bind(config.Developer); // https://github.com/serilog/serilog-settings-configuration Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configProviders, sectionName: $"{nameof(Observability)}:Serilog") .Enrich.WithSpan() .CreateLogger(); ChangeToken.OnChange(() => configProviders.GetReloadToken(), () => { Log.Information("Config change detected, reloading config values."); configProviders.GetSection(nameof(App)).Bind(config.App); configProviders.GetSection(nameof(Format)).Bind(config.Format); configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton); configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin); configProviders.GetSection(nameof(Developer)).Bind(config.Developer); GarminUploader.ValidateConfig(config); Log.Information("Config reloaded. Changes will take effect at the end of the current sleeping cycle."); }); Log.Debug("P2G Version: {@Version}", version); Log.Debug("Operating System: {@Os}", osVersion); Log.Debug("DotNet Runtime: {@DotnetRuntime}", runtimeVersion); PelotonService.ValidateConfig(config.Peloton); GarminUploader.ValidateConfig(config); Common.Metrics.ValidateConfig(config.Observability); Tracing.ValidateConfig(config.Observability); FlurlConfiguration.Configure(config); } catch (Exception e) { Log.Fatal(e, "Exception during config setup."); Health.Set(HealthStatus.Dead); throw; } IDisposable dotNetRuntimeMetrics = null; try { using var metrics = Common.Metrics.EnableMetricsServer(config.Observability.Prometheus); using var tracing = Tracing.EnableTracing(config.Observability.Jaeger); using var tracingSource = new ActivitySource("ROOT"); if (config.Observability.Prometheus.Enabled) { dotNetRuntimeMetrics = DotNetRuntimeStatsBuilder .Customize() .WithContentionStats() .WithJitStats() .WithThreadPoolStats() .WithGcStats() .WithExceptionStats() .StartCollecting(); } BuildInfo.WithLabels(version, os, osVersion, runtimeVersion).Set(1); if (config.Peloton.NumWorkoutsToDownload <= 0) { Console.Write("How many workouts to grab? "); int num = Convert.ToInt32(Console.ReadLine()); config.Peloton.NumWorkoutsToDownload = num; } if (config.App.EnablePolling) { while (config.App.EnablePolling) { RunAsync(config).GetAwaiter().GetResult(); Log.Information("Sleeping for {@Seconds} seconds...", config.App.PollingIntervalSeconds); var now = DateTime.UtcNow; var nextRunTime = now.AddSeconds(config.App.PollingIntervalSeconds); NextSyncTime.Set(new DateTimeOffset(nextRunTime).ToUnixTimeSeconds()); Thread.Sleep(config.App.PollingIntervalSeconds * 1000); } } else { RunAsync(config).GetAwaiter().GetResult(); } } catch (Exception e) { Log.Fatal(e, "Uncaught Exception."); Health.Set(HealthStatus.Dead); } finally { Log.CloseAndFlush(); Console.ReadLine(); dotNetRuntimeMetrics?.Dispose(); } }
public async Task CheckingZPagesProcessor() { const string ActivitySourceName = "zpages.test"; ZPagesExporterOptions options = new ZPagesExporterOptions { RetentionTime = 100_000, Url = "http://localhost:7284/rpcz/", }; ZPagesExporter exporter = new ZPagesExporter(options); var zpagesProcessor = new ZPagesProcessor(exporter); var source = new ActivitySource(ActivitySourceName); var activity0 = source.StartActivity("Test Zipkin Activity 1"); zpagesProcessor.OnStart(activity0); // checking size of dictionaries from ZPagesActivityTracker Assert.Equal(1, ZPagesActivityTracker.ProcessingList.First().Value); Assert.Equal(1, ZPagesActivityTracker.TotalCount.First().Value); Assert.Single(ZPagesActivityTracker.TotalEndedCount); Assert.Single(ZPagesActivityTracker.TotalErrorCount); Assert.Single(ZPagesActivityTracker.TotalLatency); var activity1 = source.StartActivity("Test Zipkin Activity 1"); zpagesProcessor.OnStart(activity1); // checking size of dictionaries from ZPagesActivityTracker Assert.Equal(2, ZPagesActivityTracker.ProcessingList.First().Value); Assert.Equal(2, ZPagesActivityTracker.TotalCount.First().Value); Assert.Single(ZPagesActivityTracker.TotalEndedCount); Assert.Single(ZPagesActivityTracker.TotalErrorCount); Assert.Single(ZPagesActivityTracker.TotalLatency); var activity2 = source.StartActivity("Test Zipkin Activity 2"); zpagesProcessor.OnStart(activity2); // checking size of dictionaries from ZPagesActivityTracker Assert.Equal(2, ZPagesActivityTracker.ProcessingList.Count); Assert.Equal(2, ZPagesActivityTracker.TotalCount.Count); Assert.Equal(2, ZPagesActivityTracker.TotalEndedCount.Count); Assert.Equal(2, ZPagesActivityTracker.TotalErrorCount.Count); Assert.Equal(2, ZPagesActivityTracker.TotalLatency.Count); activity0?.Stop(); activity1?.Stop(); activity2?.Stop(); zpagesProcessor.OnEnd(activity0); zpagesProcessor.OnEnd(activity1); zpagesProcessor.OnEnd(activity2); // checking if activities were processed Assert.Equal(0, ZPagesActivityTracker.ProcessingList.First().Value); Assert.Equal(0, ZPagesActivityTracker.ProcessingList.Last().Value); Assert.Empty(ZPagesActivityTracker.ZQueue); var zpagesServer = new ZPagesExporterStatsHttpServer(exporter); zpagesServer.Start(); using var httpResponseMessage = await HttpClient.GetAsync("http://localhost:7284/rpcz/"); Assert.True(httpResponseMessage.IsSuccessStatusCode); var content = await httpResponseMessage.Content.ReadAsStringAsync(); Assert.Contains($"<td>Test Zipkin Activity 1</td>", content); Assert.Contains($"<td>Test Zipkin Activity 2</td>", content); zpagesProcessor.Dispose(); zpagesServer.Stop(); zpagesServer.Dispose(); exporter.Dispose(); }
internal Tracer(ActivitySource activitySource) { this.ActivitySource = activitySource; }
internal static object Run(ConsoleOptions options) { // Enable OpenTelemetry for the source "MyCompany.MyProduct.MyWebServer" // and use a single pipeline with a custom MyProcessor, and Console exporter. using var openTelemetry = OpenTelemetrySdk.EnableOpenTelemetry( (builder) => builder.AddActivitySource("MyCompany.MyProduct.MyWebServer") .SetResource(Resources.CreateServiceResource("MyServiceName")) .UseConsoleExporter(opt => opt.DisplayAsJson = options.DisplayAsJson, (p) => p.AddProcessor((next) => new MyProcessor(next)))); // The above line is required only in applications // which decide to use Open Telemetry. // Libraries would simply write the following lines of code to // emit activities, which are the .NET representation of OT Spans. var source = new ActivitySource("MyCompany.MyProduct.MyWebServer"); // The below commented out line shows more likely code in a real world webserver. // using (var parent = source.StartActivity("HttpIn", ActivityKind.Server, HttpContext.Request.Headers["traceparent"] )) using (var parent = source.StartActivity("HttpIn", ActivityKind.Server)) { // TagNames can follow the OT guidelines // from https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions parent?.AddTag("http.method", "GET"); parent?.AddTag("http.host", "MyHostName"); if (parent != null) { parent.DisplayName = "HttpIn DisplayName"; // IsAllDataRequested is equivalent of Span.IsRecording if (parent.IsAllDataRequested) { parent.AddTag("expensive data", "This data is expensive to obtain. Avoid it if activity is not being recorded"); } } try { // Actual code to achieve the purpose of the library. // For websebserver example, this would be calling // user middlware pipeline. // There can be child activities. // In this example HttpOut is a child of HttpIn. using (var child = source.StartActivity("HttpOut", ActivityKind.Client)) { child?.AddTag("http.url", "www.mydependencyapi.com"); try { // do actual work. child?.AddEvent(new ActivityEvent("sample activity event.")); child?.AddTag("http.status_code", "200"); } catch (Exception) { child?.AddTag("http.status_code", "500"); } } parent?.AddTag("http.status_code", "200"); } catch (Exception) { parent?.AddTag("http.status_code", "500"); } } System.Console.WriteLine("Press Enter key to exit."); return(null); }
public DynamoDbItemService(Settings settings, ActivitySource activitySource) { _jsonSerializer = new JsonSerializer(); _settings = settings; _activitySource = activitySource; }
private static async Task RunAsync() { var endpoint = "/delay/5ms"; using var listener = new HttpEventListener(); source = new ActivitySource("http-client-test"); var serviceCollection = new ServiceCollection(); serviceCollection.AddHttpOptionsTelemetry(builder => builder.AddConsoleExporter()); serviceCollection.AddHttpClientOptions(options => { options.ServiceName = "service"; options.Handler.MaxConnection = 500; _server.ConfigureWireMockServer(options); }); var services = serviceCollection.BuildServiceProvider(); await Task.WhenAll(services.GetServices <IHostedService>() .Select(e => e.StartAsync(CancellationToken.None))); var factory = services.GetRequiredService <IHttpClientFactory>(); var client = factory.CreateClient("service"); var stopwatch = Stopwatch.StartNew(); Console.WriteLine("oooo: "); do { try { await client.GetAsync(endpoint).ConfigureAwait(false); } catch (Exception e) { } } while (Console.ReadKey().Key != ConsoleKey.Escape); do { try { var activityLinks = new List <ActivityLink>(); var initialTags = new ActivityTagsCollection(); initialTags["com.mycompany.product.mytag1"] = "tagValue1"; initialTags["com.mycompany.product.mytag2"] = "tagValue2"; var linkedContext1 = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); var linkedContext2 = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded); activityLinks.Add(new ActivityLink(linkedContext1)); activityLinks.Add(new ActivityLink(linkedContext2)); using var activity = source.StartActivity( "ActivityWithLinks", ActivityKind.Server, default(ActivityContext), initialTags, activityLinks); var latencyStats = await TrafficGenerator .GenerateTraffic(100, () => client.GetAsync(endpoint)) .Latency() .TakeUntil(DateTimeOffset.Now.AddSeconds(20)); Console.WriteLine(latencyStats.Print()); await client.GetAsync(endpoint).ConfigureAwait(false); System.Console.WriteLine("Press Enter key to continue."); } catch (Exception e) { Console.WriteLine(e); throw; } } while (Console.ReadKey().Key != ConsoleKey.Escape); }
internal TracerProviderSdk( Resource resource, IEnumerable <string> sources, IEnumerable <TracerProviderBuilderBase.InstrumentationFactory> instrumentationFactories, Sampler sampler, List <BaseProcessor <Activity> > processors, Dictionary <string, bool> legacyActivityOperationNames) { this.Resource = resource; this.sampler = sampler; this.supportLegacyActivity = legacyActivityOperationNames.Count > 0; bool legacyActivityWildcardMode = false; Regex legacyActivityWildcardModeRegex = null; foreach (var legacyName in legacyActivityOperationNames) { if (legacyName.Key.Contains('*')) { legacyActivityWildcardMode = true; legacyActivityWildcardModeRegex = GetWildcardRegex(legacyActivityOperationNames.Keys); break; } } foreach (var processor in processors) { this.AddProcessor(processor); } if (instrumentationFactories.Any()) { foreach (var instrumentationFactory in instrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory()); } } var listener = new ActivityListener(); if (this.supportLegacyActivity) { Func <Activity, bool> legacyActivityPredicate = null; if (legacyActivityWildcardMode) { legacyActivityPredicate = activity => legacyActivityWildcardModeRegex.IsMatch(activity.OperationName); } else { legacyActivityPredicate = activity => legacyActivityOperationNames.ContainsKey(activity.OperationName); } listener.ActivityStarted = activity => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (string.IsNullOrEmpty(activity.Source.Name)) { if (legacyActivityPredicate(activity)) { // Legacy activity matches the user configured list. // Call sampler for the legacy activity // unless suppressed. if (!Sdk.SuppressInstrumentation) { this.getRequestedDataAction(activity); } else { activity.IsAllDataRequested = false; } } else { // Legacy activity doesn't match the user configured list. No need to proceed further. return; } } if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }; listener.ActivityStopped = activity => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (string.IsNullOrEmpty(activity.Source.Name) && !legacyActivityPredicate(activity)) { // Legacy activity doesn't match the user configured list. No need to proceed further. return; } if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }; } else { listener.ActivityStarted = activity => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (activity.IsAllDataRequested && SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }; listener.ActivityStopped = activity => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }; } if (sampler is AlwaysOnSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ActivitySamplingResult.AllDataAndRecorded : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOnSampler; } else if (sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOffSampler; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ComputeActivitySamplingResult(options, sampler) : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataOtherSampler; } if (sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries // which do not depend on ActivitySources. var wildcardMode = false; // Validation of source name is already done in builder. foreach (var name in sources) { if (name.Contains('*')) { wildcardMode = true; break; } } if (wildcardMode) { var regex = GetWildcardRegex(sources); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => this.supportLegacyActivity ? string.IsNullOrEmpty(activitySource.Name) || regex.IsMatch(activitySource.Name) : regex.IsMatch(activitySource.Name); } else { var activitySources = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var name in sources) { activitySources.Add(name); } if (this.supportLegacyActivity) { activitySources.Add(string.Empty); } // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => activitySources.Contains(activitySource.Name); } } else { if (this.supportLegacyActivity) { listener.ShouldListenTo = (activitySource) => string.IsNullOrEmpty(activitySource.Name); } } ActivitySource.AddActivityListener(listener); this.listener = listener; Regex GetWildcardRegex(IEnumerable <string> collection) { var pattern = '^' + string.Join("|", from name in collection select "(?:" + Regex.Escape(name).Replace("\\*", ".*") + ')') + '$'; return(new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase)); } }
public void ToOtlpSpanTest() { var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest)); using var rootActivity = activitySource.StartActivity("root", ActivityKind.Producer); var attributes = new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>("bool", true), new KeyValuePair <string, object>("long", 1L), new KeyValuePair <string, object>("string", "text"), new KeyValuePair <string, object>("double", 3.14), new KeyValuePair <string, object>("int", 1), new KeyValuePair <string, object>("datetime", DateTime.UtcNow), new KeyValuePair <string, object>("bool_array", new bool[] { true, false }), new KeyValuePair <string, object>("int_array", new int[] { 1, 2 }), new KeyValuePair <string, object>("double_array", new double[] { 1.0, 2.09 }), new KeyValuePair <string, object>("string_array", new string[] { "a", "b" }), }; foreach (var kvp in attributes) { rootActivity.SetTag(kvp.Key, kvp.Value); } var startTime = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc); DateTimeOffset dateTimeOffset; #if NET452 dateTimeOffset = DateTimeOffsetExtensions.FromUnixTimeMilliseconds(0); #else dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(0); #endif var expectedUnixTimeTicks = (ulong)(startTime.Ticks - dateTimeOffset.Ticks); var duration = TimeSpan.FromMilliseconds(1555); rootActivity.SetStartTime(startTime); rootActivity.SetEndTime(startTime + duration); Span <byte> traceIdSpan = stackalloc byte[16]; rootActivity.TraceId.CopyTo(traceIdSpan); var traceId = traceIdSpan.ToArray(); var otlpSpan = rootActivity.ToOtlpSpan(); Assert.NotNull(otlpSpan); Assert.Equal("root", otlpSpan.Name); Assert.Equal(OtlpTrace.Span.Types.SpanKind.Producer, otlpSpan.Kind); Assert.Equal(traceId, otlpSpan.TraceId); Assert.Empty(otlpSpan.ParentSpanId); Assert.Null(otlpSpan.Status); Assert.Empty(otlpSpan.Events); Assert.Empty(otlpSpan.Links); AssertOtlpAttributes(attributes, otlpSpan.Attributes); var expectedStartTimeUnixNano = 100 * expectedUnixTimeTicks; Assert.Equal(expectedStartTimeUnixNano, otlpSpan.StartTimeUnixNano); var expectedEndTimeUnixNano = expectedStartTimeUnixNano + (duration.TotalMilliseconds * 1_000_000); Assert.Equal(expectedEndTimeUnixNano, otlpSpan.EndTimeUnixNano); var childLinks = new List <ActivityLink> { new ActivityLink(rootActivity.Context, new ActivityTagsCollection(attributes)) }; var childActivity = activitySource.StartActivity( "child", ActivityKind.Client, rootActivity.Context, links: childLinks); childActivity.SetStatus(Status.Error); var childEvents = new List <ActivityEvent> { new ActivityEvent("e0"), new ActivityEvent("e1", default, new ActivityTagsCollection(attributes))
static DotPulsarActivitySource() { ActivitySource = new ActivitySource(Constants.ClientName, Constants.ClientVersion); }
static async Task Main(string[] args) { var opts = new OptionSet() { { "u|user="******"(REQUIRED) A github user with admin access.", u => Config.Github.User = u } , { "t|token=", "(REQUIRED) A github token that has admin access to the org.", t => Config.Github.Token = t } , { "o|org=", "The organization we need to run the actions against (defaults to `sectigo-eng`)", o => Config.Github.Org = o } , { "teams=", "A file with the desired team structure in JSON format. If this is set, this will enforce that team structure (including removing members from teams). We expect a Dictionary where the key is the team name, and the value a list of string with the user login names.", ts => Config.TeamStructureFile = ts } , { "repos=", "A file with the desired repository teams access in JSON format.", rs => Config.RepoStructureFile = rs } , { "report=", "The path were we output the audit report. This defaults to ./", o => Config.ReportingPath = o } , { "d|dryrun=", "Should this run authoritative updates (`no`-dryrun), or only display changes (`yes`.Run a dryrun please). Must be either 'yes' or 'no'. Defaults to 'yes'.", (string dry) => Config.DryRunMode = dry.ToLower() } , { "no-dryrun", "Run authoritative updates. This can be destructive. This is the greedy option over --dryrun=yes|no.", d => Config.DryRunMode = "no" } , { "validate=", "Should this run include validation checks .Runes X exist or not). Excluding these (or `only` running these) saves significant api hits for rate limiting. Must be either `yes` or `no` or `only`. Defaults to `yes`", (string val) => Config.ValidationMode = val.ToLower() } , { "tags=", "Only runs the tasks listed here. Note that if this argument is specified, and is inclusive, any tasks that do not have tags will not be run. Expects a CSV. By default everything runs. Current options are `OnlyTeams`", tags => Config.WithTags = new List <string>(tags.Split(',').Where(s => !string.IsNullOrWhiteSpace(s))) } , { "e=", "Can only be used with --tags. While exclude any tags listed from the current run. Can be used as a flag, or value of `yes` or `no` Defaults to off.)", (string exclude) => Config.ExludeTagsMode = exclude } , { "contextPath=", "If set, will load all the supported manifests (yaml or yml) from that directory, and those will apply to the settings. Path has to exists.", c => Config.ContextPath = c } , { "h|help", p => Config.Help = true } }; try { opts.Parse(args); Console.WriteLine($"Current configuration: {Config.ToString()}"); } catch (OptionException e) { Console.WriteLine(e.Message); return; } if (!Config.ValidateInput() || Config.Help) { opts.WriteOptionDescriptions(Console.Out); return; } if (Config.Honeycomb.Validate()) { Console.WriteLine("Setting up telemetry"); source = new ActivitySource("gitman.App", "1.0.0"); tracer = Sdk .CreateTracerProviderBuilder() .AddHoneycomb(new HoneycombOptions { ServiceName = Config.Honeycomb.ServiceName, ApiKey = Config.Honeycomb.ApiKey, Dataset = Config.Honeycomb.Dataset }) .AddSource("gitman.*") .Build(); } using var root = source?.StartActivity("app"); if (!Config.DryRun) { Console.WriteLine("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); Console.WriteLine("!!! Non-DryRun mode !!!"); if (Config.OnlyValidate) { Console.WriteLine("!!! But w're only running in validation mode, so there shouldn't be changes. !!!"); } else { Console.WriteLine("!!! Changes WILL BE authorative !!!"); } Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); } // For the github sdk to allow us to specify our GithubHttpCache, we have to add all this other // nonsense to it. client = new GitHubClient(new Connection( new ProductHeaderValue("SuperMassiveCLI") , GitHubClient.GitHubApiUrl , new InMemoryCredentialStore(Credentials.Anonymous) // this is the only thing that really matters in this instantiation. There is no other way // to set this up. , new Octokit.Internal.HttpClientAdapter(() => new Helpers.GithubHttpCache()) , new Octokit.Internal.SimpleJsonSerializer() )); client.Credentials = new Credentials(Config.Github.User, Config.Github.Token); var loader = new ResourceLoader(); if (!string.IsNullOrEmpty(Config.ContextPath)) { loader.LoadResources(Config.ContextPath); } Console.WriteLine("\n\nChecking merge setting"); await new Merging { Client = client, Loader = loader }.Run(); Console.WriteLine("\n\nChecking branch protections"); await new Protection() { Client = client, Loader = loader }.Run(); Console.WriteLine("\n\nPerforming team audit"); var audit = new Audit(outputPath: Config.ReportingPath) { Client = client }; await audit.Run(); if (Config.HasTeamsStructureFile) { var repository_description = GetRepositoryDescription(); var proposed_teams = GetTeams(); Console.WriteLine($"\n\nChecking for solo collaborators"); await new OnlyTeams(repository_description, proposed_teams) { Client = client }.Run(); Console.WriteLine("\n\nChecking teams"); await new Teams(proposed_teams) { Client = client }.Run(); Console.WriteLine("\n\nChecking teams memberships"); await new TeamMemberships(proposed_teams) { Client = client }.Run(); if (Config.HasRepoStructureFile) { Console.WriteLine("\n\nChecking collaborators repository access"); await new RepositoryAccess(repository_description, proposed_teams.Keys) { Client = client }.Run(); } } }
public void IncomingRequestOneWayOperationInstrumentationTest() { List <Activity> stoppedActivities = new List <Activity>(); using ActivityListener activityListener = new ActivityListener { ShouldListenTo = activitySource => true, ActivityStopped = activity => stoppedActivities.Add(activity), }; ActivitySource.AddActivityListener(activityListener); TracerProvider tracerProvider = Sdk.CreateTracerProviderBuilder() .AddWcfInstrumentation() .Build(); ServiceClient client = new ServiceClient( new NetTcpBinding(), new EndpointAddress(new Uri(this.serviceBaseUri, "/Service"))); try { client.ExecuteWithOneWay(new ServiceRequest()); this.thrownExceptionsHandle.WaitOne(3000); } finally { if (client.State == CommunicationState.Faulted) { client.Abort(); } else { client.Close(); } tracerProvider?.Shutdown(); tracerProvider?.Dispose(); WcfInstrumentationActivitySource.Options = null; } // Assert Assert.Empty(this.thrownExceptions); Assert.NotEmpty(stoppedActivities); Assert.Single(stoppedActivities); Activity activity = stoppedActivities[0]; Assert.Equal("http://opentelemetry.io/Service/ExecuteWithOneWay", activity.DisplayName); Assert.Equal("ExecuteWithOneWay", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcMethodTag).Value); Assert.DoesNotContain(activity.TagObjects, t => t.Key == WcfInstrumentationConstants.SoapReplyActionTag); Assert.Equal(WcfInstrumentationActivitySource.IncomingRequestActivityName, activity.OperationName); Assert.Equal(WcfInstrumentationConstants.WcfSystemValue, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcSystemTag).Value); Assert.Equal("http://opentelemetry.io/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcServiceTag).Value); Assert.Equal(this.serviceBaseUri.Host, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostNameTag).Value); Assert.Equal(this.serviceBaseUri.Port, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostPortTag).Value); Assert.Equal("net.tcp", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelSchemeTag).Value); Assert.Equal("/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelPathTag).Value); }
internal static Activity CreateTestActivity( bool setAttributes = true, Dictionary <string, object> additionalAttributes = null, bool addEvents = true, bool addLinks = true, Resource resource = null, ActivityKind kind = ActivityKind.Client) { var startTimestamp = DateTime.UtcNow; var endTimestamp = startTimestamp.AddSeconds(60); var eventTimestamp = DateTime.UtcNow; var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan()); var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 }); var attributes = new Dictionary <string, object> { { "stringKey", "value" }, { "longKey", 1L }, { "longKey2", 1 }, { "doubleKey", 1D }, { "doubleKey2", 1F }, { "boolKey", true }, { "int_array", new int[] { 1, 2 } }, { "bool_array", new bool[] { true, false } }, { "double_array", new double[] { 1.0, 1.1 } }, { "string_array", new string[] { "a", "b" } }, }; if (additionalAttributes != null) { foreach (var attribute in additionalAttributes) { attributes.Add(attribute.Key, attribute.Value); } } var events = new List <ActivityEvent> { new ActivityEvent( "Event1", eventTimestamp, new ActivityTagsCollection(new Dictionary <string, object> { { "key", "value" }, })), new ActivityEvent( "Event2", eventTimestamp, new ActivityTagsCollection(new Dictionary <string, object> { { "key", "value" }, })), }; var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan()); var activitySource = new ActivitySource(nameof(CreateTestActivity)); var tags = setAttributes ? attributes : null; var links = addLinks ? new[] { new ActivityLink(new ActivityContext( traceId, linkedSpanId, ActivityTraceFlags.Recorded)), } : null; var activity = activitySource.StartActivity( "Name", kind, parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded), tags, links, startTime: startTimestamp); if (addEvents) { foreach (var evnt in events) { activity.AddEvent(evnt); } } activity.SetEndTime(endTimestamp); activity.Stop(); return(activity); }
/// <summary> /// Initializes a new instance of the <see cref="SendMessageCommandHandlerDecorator"/> class. /// </summary> /// <param name="handler">The handler.</param> /// <param name="tracer">The tracer.</param> /// <param name="headers">The headers.</param> /// <param name="connectionInformation">The connection information.</param> public SendMessageCommandHandlerDecorator(ICommandHandlerWithOutput <SendMessageCommand, long> handler, ActivitySource tracer, IHeaders headers, IConnectionInformation connectionInformation) { _handler = handler; _tracer = tracer; _headers = headers; _connectionInformation = connectionInformation; }