sentry-dotnet icon indicating copy to clipboard operation
sentry-dotnet copied to clipboard

Tunnel support for plain dotnet core console app

Open bobvandevijver opened this issue 2 years ago • 19 comments

Problem Statement

I am looking for tunnel support compatible with the Sentry nuget package, so I can tell my netcoreapp3.1 to use a tunnel on the local network to send Sentry logging. This is required as the machine where the console app is running on, doesn't have access to the internet, only to the machine where the tunnel is running on.

Solution Brainstorm

Implement https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option for the dotnet core SDK :)

bobvandevijver avatar Aug 17 '23 10:08 bobvandevijver

Thanks for reaching out! We'll see what we can do. :)

bitsandfoxes avatar Aug 17 '23 17:08 bitsandfoxes

Is there any reason the existing tunneling functionality we have in ASP.NET Core wouldn't work here? A simple ASP.NET Core server could be deployed on a machine that the netcoreapp3.1 app does have access to and it could use this as a gateway?

jamescrosswell avatar Aug 21 '23 05:08 jamescrosswell

@jamescrosswell I already have a machine that provides the tunnel server, but as far as I know I cannot configure my dotnet core application to use that tunnel. So this issue is about using the tunnel functionality rather than providing it.

bobvandevijver avatar Aug 21 '23 06:08 bobvandevijver

Ah, I see. I'd assumed messages sent to the /tunnel endpoint would be no different to messages sent to the Sentry DSN. It looks the tunneling middleware requires some extra "header" information specifying the DSN.

Another option might be to use something like NGINX? So you configure your DSN to be some path that NGINX will forward to the actual Sentry DSN?

jamescrosswell avatar Aug 21 '23 08:08 jamescrosswell

While that might work, it doesn't really make sense to me to be honest. We have this nice, well documented tunnel option, which should be trivial to add to the implementation of the package here (or at least, that would be my expectation), but instead I would need to create a proxy with an additional implementation to replace the DSN with the actual one. And this would be specifically for this DSN, while the others that are already going through my tunnel (which are JS based applications) work fine without it?

bobvandevijver avatar Aug 21 '23 10:08 bobvandevijver

We're also interesting in built-in tunneling capabilities for our .net app. We're using some wasm+js interop to run C# in the browser, hence the need for the tunnel to enable error reporting when adblock is enabled. We can probably implement our own tunneling capability, but we wanted to see if this feature request is under active consideration before doing so. Thank you!

benrad avatar Mar 18 '24 04:03 benrad

I think the best approach is to use ASP.NET Core with the Sentry AddSentryTunnel middleware. All the functionality is there and kestrel is an extremely fast tunnel. That can be built with AOT, single CLI executable.

https://github.com/getsentry/sentry-dotnet/blob/19320f65f15aa8c364de8630a1eef47f61c2c66f/samples/Sentry.Samples.AspNetCore.Mvc/Program.cs#L46

bruno-garcia avatar Mar 26 '24 21:03 bruno-garcia

@bruno-garcia this issue is about using an existing tunnel in a desktop application that is deployed on a protected network, not about providing a new tunnel service. As far as I know it is not possible to configure the Sentry client to use a tunnel endpoint, as that needs an additional header.

bobvandevijver avatar Mar 27 '24 05:03 bobvandevijver

I think, instead of pointing to one of our integrations that has it, we should also make the tunnel functionality available through the core package.

bitsandfoxes avatar Mar 27 '24 16:03 bitsandfoxes

In our case, we're specifically avoiding using the ASP.NET sdk because we don't otherwise need the functionality contained there, so we want to avoid the additional size and dependencies. So yes, including the tunnel functionality in the core Sentry package like @bitsandfoxes suggested so we can use it in the call to Sentry.Init would be our preferred solution.

benrad avatar Mar 27 '24 19:03 benrad

We'd be bundling an HTTP server in the core Sentry package and bind to a port and listen to connections? I don't think it makes sense to try to create a tunnel outside ASP.NET. We need an HTTP server. It's all managed code. It's super small and fast.

bruno-garcia avatar Apr 05 '24 00:04 bruno-garcia

Sorry, for clarity, my request is for a built-in means of telling a .NET client to send Sentry events to a tunnel endpoint. Something like this:

SentrySdk.Init(o => {
    o.Dsn = config.Dsn;
    o.Release = config.Release;
    o.Environment = config.Environment;
    o.Tunnel = config.TunnelEndpoint;
});

Much like the Vue plugin allows you to pass a tunnel endpoint during initialization:

export const sentry: Plugin = {
  install(app) {
    init({
      app,
      enabled: SENTRY_GLOBALS.enabled,
      environment: SENTRY_GLOBALS.environment,
      dsn: SENTRY_GLOBALS.dsn,
      tunnel: SENTRY_GLOBALS.tunnel,
      integrations: [],
    });
  },
};

We do have a server-side application built with the ASP.NET SDK that's listening for tunneled events with builder.Services.AddSentryTunneling() and SentryTunnelMiddleware. It works well for tunneling events from our Vue application, but there's no way to tell the non-ASP .NET app which endpoint it should use for tunneled events. I think this is what the OP was requesting too, but apologies if I've taken the issue off topic.

benrad avatar Apr 05 '24 01:04 benrad

That is exactly what I am asking for @benrad 👍🏻

bobvandevijver avatar Apr 05 '24 06:04 bobvandevijver

Oh, I missed that point.

The JS SDK has a tunnel because it runs on the browser, where ad-blockers can be around blocking some requests. What's the use case for the .NET SDK to use the tunnel endpoint instead?

This is required as the machine where the console app is running on, doesn't have access to the internet, only to the machine where the tunnel is running on.

If your goal is to proxy the data through your infrastructure, would running your own Relay help instead?

Relay was built for that. It can also store things on disk.

bruno-garcia avatar Apr 10 '24 02:04 bruno-garcia

I appreciate the reply. We have a C# application that we run in the browser via WASM, so our use case is the same in that we want to send error events to our tunnel to avoid ad-blocking. The tunnel option is preferable because the configuration is similar across our usages of different Sentry SDKs.

I suppose a Relay could work, but we’d prefer the tunnel as we already have one set up, configuration is simpler and lighter weight, and we don’t need any of the features or have any of the use cases that the Relay product is built for.

On Tue, Apr 9, 2024 at 7:33 PM Bruno Garcia @.***> wrote:

Oh, I missed that point.

The JS SDK has a tunnel because it runs on the browser, where ad-blockers can be around blocking some requests. What's the use case for the .NET SDK to use the tunnel endpoint instead?

If your goal is to proxy the data through your infrastructure, would running your own Relay https://docs.sentry.io/product/relay/ help instead?

— Reply to this email directly, view it on GitHub https://github.com/getsentry/sentry-dotnet/issues/2548#issuecomment-2046371786, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHFSARFBKNY3PO3IHU5TRLY4SQIDAVCNFSM6AAAAAA3T2DMEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBWGM3TCNZYGY . You are receiving this because you were mentioned.Message ID: @.***>

benrad avatar Apr 10 '24 03:04 benrad

Tunnel option for .NET Wasm does make sense!

Is this something you could help with a PR? the reference implementation is probably looking at the JS SDK, don't think we have anything on https://develop.sentry.dev/ about Tunneling. @cleptric might know

bruno-garcia avatar Apr 10 '24 16:04 bruno-garcia

https://docs.sentry.io/platforms/javascript/troubleshooting/#dealing-with-ad-blockers

We do show some snippets there, one is in C#.


// This functionality is now built-in to the Sentry.AspNetCore package.
// See https://docs.sentry.io/platforms/dotnet/guides/aspnetcore/#tunnel
// docs for more information.

// This example shows how you could implement it yourself:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text.Json;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;

// Change host appropriately if you run your own Sentry instance.
const string host = "sentry.io";
// Set knownProjectIds to a list with your Sentry project IDs which you
// want to accept through this proxy.
var knownProjectIds = new HashSet<string>() {  };

var client = new HttpClient();
WebHost.CreateDefaultBuilder(args).Configure(a =>
    a.Run(async context =>
    {
        context.Request.EnableBuffering();
        using var reader = new StreamReader(context.Request.Body);
        var header = await reader.ReadLineAsync();
        var headerJson = JsonSerializer.Deserialize<Dictionary<string, object>>(header);
        if (headerJson.TryGetValue("dsn", out var dsnString)
            && Uri.TryCreate(dsnString.ToString(), UriKind.Absolute, out var dsn))
        {
            var projectId = dsn.AbsolutePath.Trim('/');
            if (knownProjectIds.Contains(projectId) && string.Equals(dsn.Host, host, StringComparison.OrdinalIgnoreCase)) {
              context.Request.Body.Position = 0;
              await client.PostAsync($"https://{dsn.Host}/api/{projectId}/envelope/",
                  new StreamContent(context.Request.Body));
            }
        }
    })).Build().Run();

cleptric avatar Apr 10 '24 17:04 cleptric

@cleptric right, I wrote that 😅

I was referring to the client side of it. the option tunnel and its internal behavior. Folks have .NET on the browser, and would like to use it just as we offer for JS today

bruno-garcia avatar Apr 10 '24 17:04 bruno-garcia

Ahh, sorry. I don't think we have anything documented, as this was always scoped to JS only.

cleptric avatar Apr 10 '24 18:04 cleptric