Skip to content
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

No example for ASP.NET Core #16002

Closed
breyed opened this issue Oct 2, 2018 — with docs.microsoft.com · 19 comments
Closed

No example for ASP.NET Core #16002

breyed opened this issue Oct 2, 2018 — with docs.microsoft.com · 19 comments

Comments

Copy link
Contributor

breyed commented Oct 2, 2018

Microsoft.AspNetCore.Http.HttpContext differs from the HttpContext in the example.


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@kobulloc-MSFT
Copy link
Contributor

@breyed Thank you for the feedback! We will assign this to the author so they can update the document accordingly.

Copy link

It would be great to still see an example for ASP.NET Core. Can't seem to access session in my ITelemetryInitializer as it's null.

@aherrick
Copy link

aherrick commented Nov 8, 2018

Below is how I'm doing it:

services.AddSingleton<ITelemetryInitializer, WebSessionTelemetryInitializer>();
	public class WebSessionTelemetryInitializer : TelemetryInitializerBase
	{
		public WebSessionTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
			 : base(httpContextAccessor)
		{
		}

		/// <summary>
		/// Called when initialize telemetry.
		/// </summary>
		/// <param name="platformContext">The platform context.</param>
		/// <param name="requestTelemetry">The request telemetry.</param>
		/// <param name="telemetry">The telemetry.</param>
		protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
		{
			if (platformContext?.User?.Identity == null)
			{
				return;
			}

			telemetry.Context.User.Id = platformContext.User.Identity.Name;
			telemetry.Context.User.AccountId = // get account from claims

			if (platformContext.Request.Cookies != null && platformContext.Request.Cookies.ContainsKey(UIConstants.WebSessionCookieName))
			{
				var sessionCookieValue = platformContext.Request.Cookies[UIConstants.WebSessionCookieName];
				if (!string.IsNullOrEmpty(sessionCookieValue))
				{
					var sessionCookieParts = sessionCookieValue.Split('|');
					if (sessionCookieParts.Length > 0)
					{
						// Currently SessionContext takes in only SessionId. The cookies has
						// SessionAcquisitionDate and SessionRenewDate as well that we are not
						// picking for now.
						requestTelemetry.Context.Session.Id = sessionCookieParts[0];
					}
				}
			}
		}
	}

@gilmishal
Copy link

@aherrick Tried that, and my identity is always empty - there are no claims in the claimprincipal.

@spottedmahn
Copy link
Contributor

@aherrick thanks! 👏

Our code for reference for others:

using Microsoft.ApplicationInsights.AspNetCore.TelemetryInitializers;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace OurApp.Web.Services
{
    //source: https://github.com/MicrosoftDocs/azure-docs/issues/16002#issuecomment-437146249
    public class OurTelemetryInitializer : TelemetryInitializerBase
    {
        public OurTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
             : base(httpContextAccessor) { }

        protected override void OnInitializeTelemetry(HttpContext httpContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
        {
            if (httpContext.RequestServices == null)
                return;

            var userService = httpContext.RequestServices.GetService<IUserService>();
            if (userService == null)
                return;

            var userId = userService.GetUserId();

            if (userId == null)
                return;

            telemetry.Context.User.Id = userId;
            telemetry.Context.User.AccountId = userId;
        }
    }
}

@janhurst
Copy link

@aherrick Tried that, and my identity is always empty - there are no claims in the claimprincipal.

Same here, the claims principal is always empty. I am using Windows Integrated Authentication, and I can see my custom authorization handlers being triggered.

@PRMerger7 PRMerger7 added the Pri2 label Aug 26, 2019
@mrbullwinkle
Copy link
Contributor

adding @cijothomas

@rmarskell
Copy link
Contributor

This is what I used. The claims principal has values after the user has logged in as expected.

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Security.Claims;

namespace My.App.Namespace {
    public class TelemetryInitializer : ITelemetryInitializer {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public TelemetryInitializer(
            IHttpContextAccessor httpContextAccessor) {
            _httpContextAccessor = httpContextAccessor;
        }

        public void Initialize( ITelemetry telemetry ) {

            //Make sure this is a request telemetry entry
            if ( telemetry as RequestTelemetry == null ) { return; }

            //Get the current http context
            HttpContext httpCtx = _httpContextAccessor.HttpContext;

            //Check if the user is authenticated
            if ( httpCtx?.User?.Identity.IsAuthenticated ?? false ) {
                //Add the details to the telemetry
                telemetry.Context.User.AuthenticatedUserId = httpCtx.User.Claims.FirstOrDefault( c => c.Type == ClaimTypes.NameIdentifier )?.Value;
            }
        }
    }
}

And then in Startup.cs:

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;
using My.App.Namespace;

And in ConfigureServices():

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<ITelemetryInitializer, TelemetryInitializer>();

@cijothomas
Copy link
Contributor

@rmarskell
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); is added by SDK so you don't need to add again. There are several threading issues with using HttpContextAccessor, - https://github.com/microsoft/ApplicationInsights-aspnetcore/issues/373

@ideoclickVanessa
Copy link

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); is added by SDK so you don't need to add again. There are several threading issues with using HttpContextAccessor, - microsoft/ApplicationInsights-aspnetcore#373

@cijothomas
What is the recommended way of attaching details about the currently logged on user to the telemetry then?

@rmarskell
Copy link
Contributor

Hmm. I don't really understand why it's so difficult to properly add the user ID to the telemetry. Until yesterday, I had assumed this was handled automatically.

@cijothomas
Copy link
Contributor

Its easy to add user id to telemetry. The tricky part is retrieving userid from HttpContextAccessor.
ApplicationInsights is doing it after taking a lock (https://github.com/microsoft/ApplicationInsights-aspnetcore/blob/develop/NETCORE/src/Microsoft.ApplicationInsights.AspNetCore/TelemetryInitializers/TelemetryInitializerBase.cs#L41)
If you are doing this yourself (i.e reading from context and populating,) then it should be protected with locks as sdk does.

Also this issue (dotnet/aspnetcore#14975) about HttpContextAccessor.

Copy link

jordanchang commented Nov 6, 2019

I wanted to include User-Agent to all my request telemetry and this worked for me on ASP .NET Core app.

  1. Create a custom telemetry initializer that inherits from the ITelemetryInitilizer. Inject HttpContext so that the user-agent can be retrieved from the current HTTP request. If a telemetry is of type request, set the the user-agent as UserId.
 public class MyCustomTelemetryInitializer: ITelemetryInitializer
    {
        readonly IHttpContextAccessor _httpContextAccessor;

        public MyCustomTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            if (telemetry is RequestTelemetry requestTelemetry)
            {
                requestTelemetry.Context.User.Id = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"];
            }
        }
    }
  1. Register the custom initilizer in your app startup
    builder.Services.AddSingleton<ITelemetryInitializer, MyCustomTelemetryInitializer>();

  2. The User-Agent will now appear on the UserId column of request telemetry.

@breyed
Copy link
Contributor Author

breyed commented Nov 7, 2019

@jordanchang User-Agent specifies the user's web browser (Chrome, Edge, etc.); it doesn't identify the human who is signed in.

@mbrennan376
Copy link

I have tried all the solutions above and Identity.Name is null, except for database dependency calls. Is there a requirement for what order the services are added to the container?

@mbrennan376
Copy link

mbrennan376 commented Jan 7, 2020

I have tried all the solutions above and Identity.Name is null, except for database dependency calls. Is there a requirement for what order the services are added to the container?

I worked this through with Microsoft support and it appears as if the cause in my case was adding the accessor to the container in startup cs. I removed the extra call to add the accessor and it appears to be working now #16002 (comment)

@empz
Copy link

empz commented Apr 14, 2020

Can we please have an updated working example for ASP.NET Core written in this doc. page?

@SamaraSoucy-MSFT SamaraSoucy-MSFT removed their assignment Oct 15, 2020
@NumberByColors
Copy link
Contributor

@SamaraSoucy-MSFT Remove me from this, I haven't worked on it in years.

@lgayhardt
Copy link
Contributor

Thank you for all the feedback. We are actually retiring this doc so I will close this issue.

#please-close

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment