public void Constructor_InitializesWithDefaults() { var opts = new ThreadDumpEndpointOptions(); Assert.Null(opts.Enabled); Assert.Equal("dump", opts.Id); }
public void Constructor_BindsConfigurationCorrectly() { var appsettings = new Dictionary <string, string>() { ["management:endpoints:enabled"] = "false", ["management:endpoints:loggers:enabled"] = "false", ["management:endpoints:dump:enabled"] = "true", ["management:endpoints:cloudfoundry:validatecertificates"] = "true", ["management:endpoints:cloudfoundry:enabled"] = "true" }; ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddInMemoryCollection(appsettings); var config = configurationBuilder.Build(); var opts = new ThreadDumpEndpointOptions(config); var cloudOpts = new CloudFoundryEndpointOptions(config); var ep = new ThreadDumpEndpoint(opts, new ThreadDumper(opts)); Assert.True(cloudOpts.Enabled); Assert.Equal(string.Empty, cloudOpts.Id); Assert.Equal(string.Empty, cloudOpts.Path); Assert.True(cloudOpts.ValidateCertificates); Assert.True(opts.Enabled); Assert.Equal("dump", opts.Id); Assert.Equal("dump", opts.Path); Assert.True(ep.Enabled); }
/// <summary> /// Add Thread Dump actuator endpoint to OWIN Pipeline /// </summary> /// <param name="builder">OWIN <see cref="IAppBuilder" /></param> /// <param name="config"><see cref="IConfiguration"/> of application for configuring thread dump endpoint</param> /// <param name="loggerFactory">For logging within the middleware</param> /// <param name="version">MediaTypeVersion for endpoint response</param> /// <returns>OWIN <see cref="IAppBuilder" /> with Thread Dump Endpoint added</returns> public static IAppBuilder UseThreadDumpActuator(this IAppBuilder builder, IConfiguration config, ILoggerFactory loggerFactory, MediaTypeVersion version) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (config == null) { throw new ArgumentNullException(nameof(config)); } var options = new ThreadDumpEndpointOptions(config); if (version == MediaTypeVersion.V2 && options.Id == "dump") { options.Id = "threaddump"; } var mgmtOptions = ManagementOptions.Get(config); foreach (var mgmt in mgmtOptions) { mgmt.EndpointOptions.Add(options); } var threadDumper = new ThreadDumper(options, loggerFactory?.CreateLogger <ThreadDumper>()); return(builder.UseThreadDumpActuator(options, threadDumper, loggerFactory, version)); }
public void ThreadDumpEndpointMiddleware_PathAndVerbMatching_ReturnsExpected() { var actOptions = new ActuatorManagementOptions() { Path = "/", Exposure = new Exposure { Include = new List <string> { "*" } } }; var opts = new ThreadDumpEndpointOptions(); actOptions.EndpointOptions.Add(opts); ThreadDumper obs = new ThreadDumper(opts); var ep = new ThreadDumpEndpoint(opts, obs); var middle = new ThreadDumpEndpointMiddleware(null, ep, new List <IManagementOptions> { actOptions }); Assert.True(middle.RequestVerbAndPathMatch("GET", "/dump")); Assert.False(middle.RequestVerbAndPathMatch("PUT", "/dump")); Assert.False(middle.RequestVerbAndPathMatch("GET", "/badpath")); }
public static void UseThreadDumpActuator(IConfiguration configuration, MediaTypeVersion version, IThreadDumper threadDumper = null, ILoggerFactory loggerFactory = null) { var options = new ThreadDumpEndpointOptions(configuration); if (version == MediaTypeVersion.V2 && options.Id == "dump") { options.Id = "threaddump"; } _mgmtOptions.RegisterEndpointOptions(configuration, options); threadDumper = threadDumper ?? new ThreadDumper(options); IActuatorHandler handler; switch (version) { case MediaTypeVersion.V1: var ep = new ThreadDumpEndpoint(options, threadDumper, CreateLogger <ThreadDumpEndpoint>(loggerFactory)); handler = new ThreadDumpHandler(ep, SecurityServices, _mgmtOptions, CreateLogger <ThreadDumpHandler>(loggerFactory)); break; default: var ep2 = new ThreadDumpEndpoint_v2(options, threadDumper, CreateLogger <ThreadDumpEndpoint_v2>(loggerFactory)); handler = new ThreadDumpHandler_v2(ep2, SecurityServices, _mgmtOptions, CreateLogger <ThreadDumpHandler_v2>(loggerFactory)); break; } ConfiguredHandlers.Add(handler); }
/// <summary> /// Adds the services used by the Thread Dump actuator /// </summary> /// <param name="services">Reference to the service collection</param> /// <param name="configuration">Reference to the configuration system</param> /// <param name="version">The media version to use</param> /// <returns>A reference to the service collection</returns> public static IServiceCollection AddThreadDumpActuatorServices(this IServiceCollection services, IConfiguration configuration, MediaTypeVersion version) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } var options = new ThreadDumpEndpointOptions(configuration); if (version == MediaTypeVersion.V1) { services.TryAddSingleton <ThreadDumpEndpoint>(); } else { if (options.Id == "dump") { options.Id = "threaddump"; } services.TryAddSingleton <ThreadDumpEndpoint_v2>(); } services.TryAddSingleton <IThreadDumpOptions>(options); services.TryAddSingleton <IThreadDumper, ThreadDumper>(); services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IEndpointOptions), options)); return(services); }
public void UseThreadDumpActuator_ThrowsIfDumperNull() { IAppBuilder builder = new AppBuilder(); var config = new ConfigurationBuilder().Build(); var options = new ThreadDumpEndpointOptions(config); var exception = Assert.Throws <ArgumentNullException>(() => builder.UseThreadDumpActuator(options, null)); Assert.Equal("threadDumper", exception.ParamName); }
public void RoutesByPathAndVerb() { var options = new ThreadDumpEndpointOptions(); Assert.True(options.ExactMatch); Assert.Equal("/actuator/dump", options.GetContextPath(new ActuatorManagementOptions())); Assert.Equal("/cloudfoundryapplication/dump", options.GetContextPath(new CloudFoundryManagementOptions())); Assert.Null(options.AllowedVerbs); }
public void ThreadDumpEndpointMiddleware_PathAndVerbMatching_ReturnsExpected() { var opts = new ThreadDumpEndpointOptions(); var mgmtOptions = TestHelpers.GetManagementOptions(opts); ThreadDumper obs = new ThreadDumper(opts); var ep = new ThreadDumpEndpoint(opts, obs); var middle = new EndpointOwinMiddleware <List <ThreadInfo> >(null, ep, mgmtOptions); Assert.True(middle.RequestVerbAndPathMatch("GET", "/cloudfoundryapplication/dump")); Assert.False(middle.RequestVerbAndPathMatch("PUT", "/cloudfoundryapplication/dump")); Assert.False(middle.RequestVerbAndPathMatch("GET", "/cloudfoundryapplication/badpath")); }
public static void RegisterThreadDumpActuator(this ContainerBuilder container, IConfiguration config, MediaTypeVersion version) { if (container == null) { throw new ArgumentNullException(nameof(container)); } if (config == null) { throw new ArgumentNullException(nameof(config)); } container.RegisterType <ThreadDumper>().As <IThreadDumper>().SingleInstance(); container.Register(c => { var options = new ThreadDumpEndpointOptions(config); if (options.Id == "dump" && version == MediaTypeVersion.V2) { options.Id = "threaddump"; } var mgmtOptions = c.Resolve <IEnumerable <IManagementOptions> >(); foreach (var mgmt in mgmtOptions) { mgmt.EndpointOptions.Add(options); } return(options); }).As <IThreadDumpOptions>().IfNotRegistered(typeof(IThreadDumpOptions)); if (version == MediaTypeVersion.V1) { container.RegisterType <ThreadDumpEndpoint>().As <IEndpoint <List <ThreadInfo> > >().SingleInstance(); container.RegisterType <EndpointOwinMiddleware <List <ThreadInfo> > >().SingleInstance(); } else { container.RegisterType <ThreadDumpEndpoint_v2>().As <IEndpoint <ThreadDumpResult> >().SingleInstance(); container.RegisterType <EndpointOwinMiddleware <ThreadDumpResult> >().SingleInstance(); } }
public async void HandleThreadDumpRequestAsync_ReturnsExpected() { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { var opts = new ThreadDumpEndpointOptions(); var mopts = TestHelper.GetManagementOptions(opts); ThreadDumper obs = new ThreadDumper(opts); var ep = new ThreadDumpEndpoint(opts, obs); var middle = new ThreadDumpEndpointMiddleware(null, ep, mopts); var context = CreateRequest("GET", "/dump"); await middle.HandleThreadDumpRequestAsync(context); context.Response.Body.Seek(0, SeekOrigin.Begin); StreamReader rdr = new StreamReader(context.Response.Body); string json = await rdr.ReadToEndAsync(); Assert.StartsWith("[", json); Assert.EndsWith("]", json); } }
public async void ThreadDumpInvoke_ReturnsExpected() { // arrange var opts = new ThreadDumpEndpointOptions(); var mgmtOptions = TestHelpers.GetManagementOptions(opts); var middle = new EndpointOwinMiddleware <List <ThreadInfo> >(null, new ThreadDumpEndpoint(opts, new ThreadDumper(opts)), mgmtOptions); var context = OwinTestHelpers.CreateRequest("GET", "/cloudfoundryapplication/dump"); // act var json = await middle.InvokeAndReadResponse(context); // assert (that it looks kinda like what we expect... ?) Assert.StartsWith("[", json); Assert.Contains("blockedCount", json); Assert.Contains("blockedTime", json); Assert.Contains("lockedMonitors", json); Assert.Contains("lockedSynchronizers", json); Assert.Contains("lockInfo", json); Assert.Contains("stackTrace", json); Assert.EndsWith("]", json); }
public async void HandleThreadDumpRequestAsync_ReturnsExpected() { if (Platform.IsWindows) { var opts = new ThreadDumpEndpointOptions(); var mgmtOptions = new ActuatorManagementOptions(); mgmtOptions.EndpointOptions.Add(opts); ThreadDumper obs = new ThreadDumper(opts); var ep = new ThreadDumpEndpoint(opts, obs); var middle = new ThreadDumpEndpointMiddleware(null, ep, mgmtOptions); var context = CreateRequest("GET", "/dump"); await middle.HandleThreadDumpRequestAsync(context); context.Response.Body.Seek(0, SeekOrigin.Begin); var rdr = new StreamReader(context.Response.Body); var json = await rdr.ReadToEndAsync(); Assert.StartsWith("[", json); Assert.EndsWith("]", json); } }