ASP.NET Core-metrik

Mått är numeriska mått som rapporteras över tid. Använd dem för att övervaka hälsotillståndet för en app och generera aviseringar. En webbtjänst kan till exempel spåra hur många:

  • Begäranden som den tar emot per sekund.
  • Millisekunder krävs för att svara.
  • Svar som skickas och innehåller ett fel.

Rapportera dessa mått till ett övervakningssystem med jämna mellanrum. Konfigurera instrumentpaneler för att visa mått och skapa aviseringar för att meddela personer om problem. Om webbtjänsten är avsedd att svara på begäranden inom 400 ms och börjar svara inom 600 ms kan övervakningssystemet meddela driftteamet att applikationssvaret är långsammare än normalt.

Den omfattande listan över alla instrument tillsammans med deras attribut beskrivs i ASP.NET Core inbyggda mått.

Använd mått

Användning av mått omfattar följande:

  • Instrumentation: Kod i .NET-bibliotek tar mätningar och kopplar dessa mätningar till ett mätvärdesnamn. .NET och ASP.NET Core innehåller många inbyggda mått.
  • Insamling och lagring: En .NET-app konfigurerar namngivna mått som ska överföras från appen för extern lagring och analys. Vissa verktyg kan utföra konfiguration utanför appen med hjälp av konfigurationsfiler eller ett gränssnittsverktyg.
  • Visualisering: Ett verktyg som kan visa måtten i ett läsbart format för människor. Till exempel Aspire instrumentpanelen, Grafana och Prometheus.
  • Varningar: Ett verktyg som ger notifikationer när ett mått överskrider ett tröskelvärde. Om den genomsnittliga svarstiden för en webbtjänst till exempel överskrider 400 ms kan en avisering skickas till driftpersonalen.
  • Analys: Ett verktyg som kan analysera måtten över tid. Det här verktyget är ofta en webbaserad instrumentpanel som kan anpassas för att visa de viktigaste måtten för en specifik app.

Instrumenterad kod kan registrera numeriska mått, men för att skapa användbara mått för övervakning måste du aggregera, överföra och lagra måtten. Processen för att aggregera, överföra och lagra data kallas insamling. Den här självstudien visar flera exempel på hur du samlar in och visar mått:

Ett annat visualiseringsalternativ finns i instrumentpanelöversiktenAspire.

Du kan också associera mått med nyckel/värde-par som kallas taggar som gör att du kan kategorisera data för analys. Mer information finns i Flerdimensionella mått.

Skapa startappen

Skapa en ny ASP.NET Core-app med följande kommando:

dotnet new web -o WebMetric
cd WebMetric
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore --prerelease
dotnet add package OpenTelemetry.Extensions.Hosting

Ersätt innehållet i Program.cs med följande kod:

using OpenTelemetry.Metrics;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
    .WithMetrics(builder =>
    {
        builder.AddPrometheusExporter();

        builder.AddMeter("Microsoft.AspNetCore.Hosting",
                         "Microsoft.AspNetCore.Server.Kestrel");
        builder.AddView("http.server.request.duration",
            new ExplicitBucketHistogramConfiguration
            {
                Boundaries = new double[] { 0, 0.005, 0.01, 0.025, 0.05,
                       0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 }
            });
    });
var app = builder.Build();

app.MapPrometheusScrapingEndpoint();

app.MapGet("/", () => "Hello OpenTelemetry! ticks:"
                     + DateTime.Now.Ticks.ToString()[^3..]);

app.Run();

Visa mätvärden med dotnet-counters

dotnet-counters är ett kommandoradsverktyg som kan visa livemått för .NET-appar på begäran. Det kräver inte konfiguration, vilket gör det användbart för ad hoc-undersökningar eller för att verifiera att måttinstrumentation fungerar. Den fungerar med både System.Diagnostics.Metrics baserade API:er och EventCounters.

Om verktyget dotnet-counters inte är installerat kör du följande kommando:

dotnet tool update -g dotnet-counters

När testappen körs startar du dotnet-counters. Följande kommando visar ett exempel på övervakning av dotnet-counters alla mått från mätarenMicrosoft.AspNetCore.Hosting.

dotnet-counters monitor -n WebMetric --counters Microsoft.AspNetCore.Hosting

Utdata som liknar följande visas:

Press p to pause, r to resume, q to quit.
    Status: Running

[Microsoft.AspNetCore.Hosting]
    http-server-current-requests
        host=localhost,method=GET,port=5045,scheme=http                    0
    http-server-request-duration (s)
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0

Mer information finns i dotnet-counters.

Utöka måttet för ASP.NET Core-begäran

ASP.NET Core har många inbyggda mått. Måttet http.server.request.duration :

  • Registrerar varaktigheten för HTTP-begäranden på servern.
  • Samlar in information om begäranden i taggar, till exempel den matchade vägen och svarsstatuskoden.

Måttet http.server.request.duration har stöd för taggberikning med hjälp av IHttpMetricsTagsFeature. Berikning är när ett bibliotek eller en app lägger till egna taggar i ett mått. Den här funktionen är användbar om en app vill lägga till en egen kategorisering i instrumentpaneler eller aviseringar som skapats med mätvärden.

using Microsoft.AspNetCore.Http.Features;

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async (context, next) =>
{
    var tagsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (tagsFeature != null)
    {
        var source = context.Request.Query["utm_medium"].ToString() switch
        {
            "" => "none",
            "social" => "social",
            "email" => "email",
            "organic" => "organic",
            _ => "other"
        };
        tagsFeature.Tags.Add(new KeyValuePair<string, object?>("mkt_medium", source));
    }

    await next.Invoke();
});

app.MapGet("/", () => "Hello World!");

app.Run();

Föregående exempel:

  • Lägger till middleware för att berika ASP.NET Core-förfrågningsmätning.
  • Hämtar IHttpMetricsTagsFeature från HttpContext. Funktionen är bara tillgänglig i kontexten om någon övervakar mätvärdet. Kontrollera att IHttpMetricsTagsFeature inte är null innan du använder det.
  • Lägger till en anpassad tagg som innehåller förfrågans marknadsföringskälla till http.server.request.duration-måttet.
    • Taggen har namnet mkt_medium och ett värde baserat på utm_medium frågesträngsvärdet. Värdet utm_medium tilldelas ett känt intervall av värden.
    • Taggen tillåter att begäranden kategoriseras efter marknadsföringsmediumtyp, vilket kan vara användbart när du analyserar webbappstrafik.

Note

Följ metodtipsen för flerdimensionella mått när du utökar med anpassade taggar. Taggar som är för många eller har ett obundet intervall skapar många taggkombinationer, vilket resulterar i höga dimensioner. Samlingsverktyg har gränser för dimensioner som stöds för en räknare och kan filtrera resultat för att förhindra överdriven minnesanvändning.

Välj bort HTTP-mätvärden för vissa ändpunkter och förfrågningar

Att välja bort inspelningsmått är fördelaktigt för slutpunkter som ofta anropas av automatiserade system, till exempel hälsokontroller. Det är vanligtvis onödigt att registrera mått för dessa begäranden. Oönskad telemetri använder resurser för att samla in och lagra och kan förvränga resultat som visas på en telemetriinstrumentpanel.

Du kan exkludera HTTP-begäranden till en slutpunkt från mått genom att lägga till metadata, antingen med attributet DisableHttpMetrics eller metoden DisableHttpMetrics :

  • Lägg till attributet DisableHttpMetrics till webb-API-kontrollanten, SignalR hubben eller gRPC-tjänsten.
  • Anropa DisableHttpMetrics när du mappar slutpunkter under appens startfas.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();

Du kan också lägga till egenskapen IHttpMetricsTagsFeature.MetricsDisabled för:

  • Avancerade scenarier där en begäran inte mappas till en slutpunkt.
  • Dynamiskt inaktiverar måttsamling för specifika HTTP-begäranden.
// Middleware that conditionally opts-out HTTP requests.
app.Use(async (context, next) =>
{
    var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (metricsFeature != null &&
        context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        metricsFeature.MetricsDisabled = true;
    }

    await next(context);
});

Skapa anpassade mått

Du skapar mått med hjälp av API:er i System.Diagnostics.Metrics namnområdet. Mer information finns i Skapa anpassade mått.

Skapa mått i ASP.NET Core-appar med IMeterFactory

Skapa Meter instanser i ASP.NET Core appar med IMeterFactory.

ASP.NET Core registrerar IMeterFactory i beroendeinjektionen (DI) som standard. Mätvärdesfabriken integrerar mätvärden med DI, vilket gör det enkelt att isolera och samla in mätvärden. IMeterFactory är särskilt användbart för testning. Det gör att flera tester kan köras sida vid sida och samlar bara in måttvärden som registreras i ett test.

Om du vill använda IMeterFactory i en app skapar du en typ som använder IMeterFactory för att skapa appens anpassade mått:

public class ContosoMetrics
{
    private readonly Counter<int> _productSoldCounter;

    public ContosoMetrics(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("Contoso.Web");
        _productSoldCounter = meter.CreateCounter<int>("contoso.product.sold");
    }

    public void ProductSold(string productName, int quantity)
    {
        _productSoldCounter.Add(quantity,
            new KeyValuePair<string, object?>("contoso.product.name", productName));
    }
}

Registrera måtttypen med DI i Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ContosoMetrics>();

Mata in måttyp och registrera värden där det behövs. Eftersom måtttypen är registrerad i DI kan den användas med MVC-styrenheter, minimala API:er eller någon annan typ som skapas av DI:

app.MapPost("/complete-sale", (SaleModel model, ContosoMetrics metrics) =>
{
    // ... business logic such as saving the sale to a database ...

    metrics.ProductSold(model.ProductName, model.QuantitySold);
});

Om du vill övervaka mätaren "Contoso.Web" använder du följande dotnet-counters-kommando .

dotnet-counters monitor -n WebMetric --counters Contoso.Web

Utdata som liknar följande visas:

Press p to pause, r to resume, q to quit.
    Status: Running

[Contoso.Web]
    contoso.product.sold (Count / 1 sec)
        contoso.product.name=Eggs            12    
        contoso.product.name=Milk            0    

Visa mått i Grafana med OpenTelemetry och Prometheus

Overview

OpenTelemetry:

  • Är ett leverantörsneutralt projekt med öppen källkod som stöds av Cloud Native Computing Foundation.
  • Standardiserar generering och insamling av telemetri för molnbaserad programvara.
  • Fungerar med .NET genom att använda .NET-mått-API.
  • Stöds av Azure Monitor och många APM-leverantörer.

Från och med ASP.NET Core 11 följer ramverkets inbyggda HTTP-servermått och -spårningar de nödvändiga delarna i OpenTelemetry HTTP-serverns semantiska konventioner. AKTIVITETEN FÖR HTTP-serverbegäran genererar dessa attribut som standard och matchar de inbyggda måtten. Därför OpenTelemetry.Instrumentation.AspNetCore är NuGet-paketet valfritt för insamling av HTTP-servermått och -spårningar. Exemplet i den här artikeln använder endast inbyggda mätare (Microsoft.AspNetCore.Hosting och Microsoft.AspNetCore.Server.Kestrel) och refererar inte till instrumentationspaketet. En lista över inbyggda instrument och deras attribut finns i ASP.NET Core inbyggda HTTP-mått.

Även om paketet är valfritt är det inte en drop-in-motsvarighet till den inbyggda instrumentationen. Den inbyggda instrumentationen täcker endast de nödvändiga delarna av semantiska konventioner. Överväg följande skillnader innan du tar bort paketet:

  • Vissa rekommenderade HTTP-serverattribut genereras inte av den inbyggda instrumentationen, till exempel vissa klient- och nätverksattribut (till exempel client.address). Fullständigt stöd för det villkorsstyrda attributeturl.query , inklusive redigering, pågår fortfarande. Om du förlitar dig på dessa attribut behåller du paketet. Mer information finns i dotnet/aspnetcore#65873.
  • Paketet är också en bekvämlighet för att aktivera telemetri utanför HTTP-servern, inklusive Blazor och SignalR. För spårning registrerar den extra aktivitetskällor för SignalR (Microsoft.AspNetCore.SignalR.Server den .NET 9 och senare) och Blazor (Microsoft.AspNetCore.Components och Microsoft.AspNetCore.Components.Server.Circuits den .NET 10 och senare). För mätvärden aktiverar den de relaterade inbyggda mätarna (till exempel Microsoft.AspNetCore.Components). Utan paketet registrerar du källorna med AddSource och mätarna med AddMeter dig själv för att samla in samma telemetri.

När du lägger till telemetri i en app som bara behöver HTTP-servermått och -spårningar kan du förlita dig på den inbyggda instrumentationen och utelämna paketet. När du uppgraderar en befintlig app från .NET 10 till .NET 11 som redan refererar till paketet behåller du den om du är beroende av de attribut, källor eller mätare som beskrivs i föregående lista. Att ta bort paketet gör att den telemetrin försvinner utan förvarning.

Viktigt!

När du aktiverar OpenTelemetry-spårning (utöver mått) utan OpenTelemetry.Instrumentation.AspNetCore paketet registrerar du ramverkets HTTP-server ActivitySource så att begärandeaktiviteten registreras. ASP.NET Core HTTP-serveraktivitetskälla heter Microsoft.AspNetCore, och ramverket skapar en begärandeaktivitet med namnet Microsoft.AspNetCore.Hosting.HttpRequestIn för varje begäran för att sprida spårningskontext. Om källan Microsoft.AspNetCore inte är registrerad med OpenTelemetry SDK:n registreras inte begärandeaktiviteten, och standardsamplern ParentBased utelämnar tyst alla anpassade underordnade spann som startas under begäran.

Registrera källan explicit i din befintliga spårningspipeline:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Microsoft.AspNetCore")
        .AddSource("MyApp"));

I föregående exempel:

  • AddSource("Microsoft.AspNetCore") registrerar ASP.NET Cores aktivitetskälla för HTTP-servern så att begärandeaktiviteten registreras.
  • AddSource("MyApp") registrerar appens egna ActivitySource. Ersätt MyApp med namnet som appen använder.
  • En exportör visas inte. Det här exemplet förutsätter att en exportör redan är konfigurerad i din spårningspipeline.

Alternativt kan du anropa AddAspNetCoreInstrumentation() från OpenTelemetry.Instrumentation.AspNetCore paketet, som registrerar källan åt dig.

Om du vill förhindra ASP.NET Core från att lägga till HTTP-semantikkonventionsattribut för OpenTelemetry i den inbyggda request-aktiviteten anger du växeln trueMicrosoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData till AppContext tidigt i appstarten:

AppContext.SetSwitch(
    "Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", true);

Inställningen undertrycker endast OpenTelemetry-attributen som ASP.NET Core lägger till i aktiviteten. Den inaktiverar inte aktivitetsskapande, spårningsspridning eller insamling av mått.

Den här handledningen visar en av de integreringar som är tillgängliga för OpenTelemetry-metrik med hjälp av OSS-projekten Prometheus och Grafana. Dataflödet för mått:

  1. API:erna för ASP.NET Core-mått registrerar mått från exempelappen.

  2. OpenTelemetry .NET-biblioteket som körs i appen aggregerar måtten.

  3. Prometheus-exporteringsbiblioteket gör aggregerade data tillgängliga via en HTTP-måttslutpunkt. "Exporter" är vad OpenTelemetry kallar de bibliotek som överför telemetri till leverantörsspecifika backend-system.

  4. En Prometheusserver:

    • Avsöker måttslutpunkten.
    • Läser datan.
    • Lagrar data i en databas för långsiktig beständighet. Prometheus refererar till att läsa och lagra data som att skrapa en slutpunkt.
    • Kan köras på en annan dator.
  5. Grafana-servern:

    • Frågar data som lagras i Prometheus och visar det på ett webbaserat övervakningsgränssnitt.
    • Kan köras på en annan dator.

Visa mått från exempelappen

Gå till exempelappen. Webbläsaren visar Hello OpenTelemetry! ticks:<3digits> var 3digits är de tre sista siffrorna i aktuella DateTime.Ticks.

/metrics Lägg till i URL:en för att visa måttslutpunkten. Webbläsaren visar de mått som samlas in:

mått 2

Ställ in och konfigurera Prometheus

Följ de första stegen i Prometheus för att konfigurera en Prometheus-server och bekräfta att den fungerar.

Ändra prometheus.yml konfigurationsfilen så att Prometheus skrapar måttslutpunkten som exempelappen exponerar. Lägg till följande markerade text i avsnittet scrape_configs :

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  - job_name: 'MyASPNETApp'
    scrape_interval: 5s # Poll every 5 seconds for a more responsive demo.
    static_configs:
      - targets: ["localhost:5045"]  ## Enter the HTTP port number of the demo app.

I föregående markerade YAML ersätter du 5045 med det portnummer som exempelappen använder.

Starta Prometheus

  1. Ladda om konfigurationen eller starta om Prometheus-servern.
  2. Bekräfta att OpenTelemetryTest är i UP-tillståndet på sidan Statusmål> i Prometheus-webbportalen.

Prometheus-status

Välj ikonen Öppna måttutforskaren för att se tillgängliga mått:

Prometheus open_metric_exp

Ange en räknarkategori, till exempel http_ i indatarutan Uttryck för att se tillgängliga mått:

tillgängliga mått

Du kan också ange en räknarkategori, till exempel kestrel i rutan Uttrycksindata för att se tillgängliga mått:

Prometheus kestrel

Visa mått på en Grafana-instrumentpanel

dashboard-screenshot2

Testa mått i ASP.NET Core-appar

Du kan testa mått i ASP.NET Core appar. Ett sätt att göra detta är att samla in och kontrollera måttvärden i ASP.NET Core integrationstester med hjälp MetricCollector<T>av .

public class BasicTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    public BasicTests(WebApplicationFactory<Program> factory) => _factory = factory;

    [Fact]
    public async Task Get_RequestCounterIncreased()
    {
        // Arrange
        var client = _factory.CreateClient();
        var meterFactory = _factory.Services.GetRequiredService<IMeterFactory>();
        var collector = new MetricCollector<double>(meterFactory,
            "Microsoft.AspNetCore.Hosting", "http.server.request.duration");

        // Act
        var response = await client.GetAsync("/");

        // Assert
        Assert.Contains("Hello OpenTelemetry!", await response.Content.ReadAsStringAsync());

        await collector.WaitForMeasurementsAsync(minCount: 1).WaitAsync(TimeSpan.FromSeconds(5));
        Assert.Collection(collector.GetMeasurementSnapshot(),
            measurement =>
            {
                Assert.Equal("http", measurement.Tags["url.scheme"]);
                Assert.Equal("GET", measurement.Tags["http.request.method"]);
                Assert.Equal("/", measurement.Tags["http.route"]);
            });
    }
}

Föregående test:

  • Bootstraps en webbapp i minnet med WebApplicationFactory<TEntryPoint>. Program i den generiska argumenten för fabriken specificerar webbappen.
  • Samlar in måttvärden med MetricCollector<T>
    • Kräver en paketreferens till Microsoft.Extensions.Diagnostics.Testing.
    • MetricCollector<T> skapas med webbappens IMeterFactory. På så sätt kan insamlaren endast rapportera måttvärden som registrerats av tester.
    • Innehåller mätarnamnet, Microsoft.AspNetCore.Hosting, och räknarnamnet, som ska samlas in, http.server.request.duration.
  • Gör en HTTP-begäran till webbappen.
  • Bekräftar testet med hjälp av resultat från måttinsamlaren.

ASP.NET Core Identity prestandamått

Identity ASP.NET Core observerbarhet hjälper dig att övervaka användarhanteringsaktiviteter och autentiseringsprocesser.

Måtten finns i mätaren Microsoft.AspNetCore.Identity och beskrivs i följande avsnitt.

Mått för användarhantering

  • aspnetcore.identity.user.create.duration mäter varaktigheten för användarskapandeåtgärder.
  • aspnetcore.identity.user.update.duration mäter varaktigheten för användaruppdateringsåtgärder.
  • aspnetcore.identity.user.delete.duration mäter varaktigheten för användarborttagningsåtgärder.
  • aspnetcore.identity.user.check_password_attempts räknar försök till lösenordsverifiering.
  • aspnetcore.identity.user.generated_tokens räknar token som genererats för användare, till exempel token för lösenordsåterställning.
  • aspnetcore.identity.user.verify_token_attempts räknar tokenverifieringsförsök.

Autentiseringsmått

  • aspnetcore.identity.sign_in.authenticate.duration mäter varaktigheten för autentiseringsåtgärder.
  • aspnetcore.identity.sign_in.check_password_attempts räknar försök till lösenordskontroll under inloggningen.
  • aspnetcore.identity.sign_in.sign_ins räknar lyckade inloggningar.
  • aspnetcore.identity.sign_in.sign_outs räknar utloggningar.
  • aspnetcore.identity.sign_in.two_factor_clients_remembered räknar ihågkomna tvåfaktorsautentiseringsklienter.
  • aspnetcore.identity.sign_in.two_factor_clients_forgotten räknar antalet bortglömda tvåfaktorklienter.

Använd dessa mått för att:

  • Övervaka användarregistrering och hantering.
  • Spåra autentiseringsmönster och potentiella säkerhetsproblem.
  • Mät prestanda för Identity åtgärder.
  • Observera användning av tvåfaktorautentisering.

Se Identity metrik

Använd dotnet-counters för att visa dessa mått och övervaka dem i realtid. Eller exportera dem till Prometheus och visualisera dem i Grafana med hjälp av de tekniker som beskrivs tidigare i den här artikeln.

Om du till exempel vill övervaka alla Identity mått med dotnet-counters:

dotnet-counters monitor -n YourAppName --counters Microsoft.AspNetCore.Identity

ASP.NET Core-mätare och räknare

En lista över ASP.NET Core-mätvärden och -räknare finns i ASP.NET Core-mått. I ASP.NET Core 11 och senare genererar de inbyggda HTTP-servermätarna (till exempel Microsoft.AspNetCore.Hosting och ) data som överensstämmer med de nödvändiga delarna i OpenTelemetry HTTP-serverns semantiska konventionerMicrosoft.AspNetCore.Server.Kestrel. Du kan använda dessa mätare med OpenTelemetry SDK utan OpenTelemetry.Instrumentation.AspNetCore paketet.

Ytterligare resurser