Smdn.Net.MuninNode version 2.5.0
·
33 commits
to main
since this release
Released package
Release notes
The full release notes are available at gist.
Change log
Change log in this release:
- 2025-06-01 update assembly version
- 2025-05-31 mark IMuninNodeBuilder obsolete
- 2025-05-31 add support for specifying the service type and implementation type of registering nodes
- 2025-05-29 add support for building with custom MuninNodeBuilder types
- 2025-05-29 add support for configuring with custom MuninNodeOptions types
- 2025-05-29 expose MuninNodeBuilder
- 2025-05-29 add PluginGraphAttributesBuilder.WithTitle() to be able to overwrite graph_title
- 2025-05-26 add Starting/Started/Stopping/Stopped async methods
API changes
API changes in this release:
diff --git a/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-net8.0.apilist.cs b/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-net8.0.apilist.cs
index 3caafc0..a379024 100644
--- a/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-net8.0.apilist.cs
+++ b/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-net8.0.apilist.cs
@@ -1,509 +1,546 @@
-// Smdn.Net.MuninNode.dll (Smdn.Net.MuninNode-2.4.0)
+// Smdn.Net.MuninNode.dll (Smdn.Net.MuninNode-2.5.0)
// Name: Smdn.Net.MuninNode
-// AssemblyVersion: 2.4.0.0
-// InformationalVersion: 2.4.0+6578cec572157dafbc9518cc746aae28f7f1ce6d
+// AssemblyVersion: 2.5.0.0
+// InformationalVersion: 2.5.0+41ff114bf69b864033a05a389896010d3eefe4d5
// TargetFramework: .NETCoreApp,Version=v8.0
// Configuration: Release
// Referenced assemblies:
// Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.Extensions.Options, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// System.Collections, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Collections.Concurrent, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.ComponentModel, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// System.Linq, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Memory, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// System.Net.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Net.Sockets, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Security.Cryptography, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Text.RegularExpressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Threading, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
#nullable enable annotations
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Smdn.Net.MuninNode;
using Smdn.Net.MuninNode.DependencyInjection;
using Smdn.Net.MuninNode.Protocol;
using Smdn.Net.MuninNode.Transport;
using Smdn.Net.MuninPlugin;
namespace Smdn.Net.MuninNode {
public interface IAccessRule {
bool IsAcceptable(IPEndPoint remoteEndPoint);
}
public interface IMuninNode {
EndPoint EndPoint { get; }
string HostName { get; }
Task RunAsync(CancellationToken cancellationToken);
}
public static class IAccessRuleServiceCollectionExtensions {
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IAccessRule accessRule) {}
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IReadOnlyList<IPAddress> addressListAllowFrom) {}
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IReadOnlyList<IPAddress> addressListAllowFrom, bool shouldConsiderIPv4MappedIPv6Address) {}
public static IServiceCollection AddMuninNodeLoopbackOnlyAccessRule(this IServiceCollection services) {}
}
public abstract class LocalNode : NodeBase {
public static LocalNode Create(IPluginProvider pluginProvider, int port, string? hostName = null, IReadOnlyList<IPAddress>? addressListAllowFrom = null, IServiceProvider? serviceProvider = null) {}
public static LocalNode Create(IReadOnlyCollection<IPlugin> plugins, int port, string? hostName = null, IReadOnlyList<IPAddress>? addressListAllowFrom = null, IServiceProvider? serviceProvider = null) {}
[Obsolete("Use a constructor overload that takes IMuninNodeListenerFactory as an argument.")]
protected LocalNode(IAccessRule? accessRule, ILogger? logger = null) {}
protected LocalNode(IMuninNodeListenerFactory? listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
[Obsolete("Use IMuninNodeListenerFactory and StartAsync instead.")]
protected override Socket CreateServerSocket() {}
}
- public sealed class MuninNodeOptions {
+ public class MuninNodeOptions {
public const string DefaultHostName = "munin-node.localhost";
public const int DefaultPort = 4949;
public static IPAddress DefaultAddress { get; }
public MuninNodeOptions() {}
public IAccessRule? AccessRule { get; set; }
public IPAddress Address { get; set; }
public string HostName { get; set; }
public int Port { get; set; }
public MuninNodeOptions AllowFrom(IReadOnlyList<IPAddress> addresses, bool shouldConsiderIPv4MappedIPv6Address = true) {}
public MuninNodeOptions AllowFromLoopbackOnly() {}
+ internal protected virtual void Configure(MuninNodeOptions baseOptions) {}
public MuninNodeOptions UseAnyAddress() {}
public MuninNodeOptions UseAnyAddress(int port) {}
public MuninNodeOptions UseLoopbackAddress() {}
public MuninNodeOptions UseLoopbackAddress(int port) {}
}
public abstract class NodeBase :
IAsyncDisposable,
IDisposable,
IMuninNode,
IMuninNodeProfile
{
[Obsolete("Use a constructor overload that takes IMuninNodeListenerFactory as an argument.")]
protected NodeBase(IAccessRule? accessRule, ILogger? logger) {}
protected NodeBase(IMuninNodeListenerFactory listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
protected NodeBase(IMuninProtocolHandlerFactory protocolHandlerFactory, IMuninNodeListenerFactory listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
public virtual Encoding Encoding { get; }
public EndPoint EndPoint { get; }
public abstract string HostName { get; }
protected IMuninNodeListener? Listener { get; }
[Obsolete("Use EndPoint instead.")]
public EndPoint LocalEndPoint { get; }
protected ILogger? Logger { get; }
public virtual Version NodeVersion { get; }
public abstract IPluginProvider PluginProvider { get; }
string IMuninNodeProfile.Version { get; }
public async ValueTask AcceptAsync(bool throwIfCancellationRequested, CancellationToken cancellationToken) {}
public async ValueTask AcceptSingleSessionAsync(CancellationToken cancellationToken = default) {}
[Obsolete("Use IMuninNodeListenerFactory and StartAsync instead.")]
protected virtual Socket CreateServerSocket() {}
protected virtual void Dispose(bool disposing) {}
public void Dispose() {}
public async ValueTask DisposeAsync() {}
protected virtual async ValueTask DisposeAsyncCore() {}
protected virtual EndPoint GetLocalEndPointToBind() {}
protected virtual IMuninNodeProfile GetNodeProfile() {}
public Task RunAsync(CancellationToken cancellationToken) {}
[Obsolete("This method will be deprecated in the future.Use IMuninNodeListenerFactory and StartAsync instead.Make sure to override CreateServerSocket if you need to use this method.")]
public void Start() {}
public ValueTask StartAsync(CancellationToken cancellationToken = default) {}
+ protected virtual ValueTask StartedAsync(CancellationToken cancellationToken) {}
+ protected virtual ValueTask StartingAsync(CancellationToken cancellationToken) {}
public ValueTask StopAsync(CancellationToken cancellationToken = default) {}
+ protected virtual ValueTask StoppedAsync(CancellationToken cancellationToken) {}
+ protected virtual ValueTask StoppingAsync(CancellationToken cancellationToken) {}
protected void ThrowIfDisposed() {}
protected void ThrowIfPluginProviderIsNull() {}
}
}
namespace Smdn.Net.MuninNode.DependencyInjection {
+ [Obsolete("Use or inherit MuninNodeBuilder instead.")]
public interface IMuninNodeBuilder {
string ServiceKey { get; }
IServiceCollection Services { get; }
IMuninNode Build(IServiceProvider serviceProvider);
}
public interface IMuninServiceBuilder {
IServiceCollection Services { get; }
}
+ [Obsolete("Use MuninNodeBuilderExtensions instead.")]
public static class IMuninNodeBuilderExtensions {
public static IMuninNodeBuilder AddPlugin(this IMuninNodeBuilder builder, Func<IServiceProvider, IPlugin> buildPlugin) {}
public static IMuninNodeBuilder AddPlugin(this IMuninNodeBuilder builder, IPlugin plugin) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, IMuninNodeListenerFactory listenerFactory) {}
public static IMuninNodeBuilder UsePluginProvider(this IMuninNodeBuilder builder, Func<IServiceProvider, IPluginProvider> buildPluginProvider) {}
public static IMuninNodeBuilder UsePluginProvider(this IMuninNodeBuilder builder, IPluginProvider pluginProvider) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, Func<IServiceProvider, INodeSessionCallback> buildSessionCallback) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc, Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, INodeSessionCallback sessionCallback) {}
}
public static class IMuninServiceBuilderExtensions {
public static IMuninNodeBuilder AddNode(this IMuninServiceBuilder builder) {}
public static IMuninNodeBuilder AddNode(this IMuninServiceBuilder builder, Action<MuninNodeOptions> configure) {}
+ public static TMuninNodeBuilder AddNode<TMuninNode, TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNode : class, IMuninNode where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddNode<TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddNode<TMuninNodeService, TMuninNodeImplementation, TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNodeService : class, IMuninNode where TMuninNodeImplementation : class, TMuninNodeService where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
}
public static class IServiceCollectionExtensions {
public static IServiceCollection AddMunin(this IServiceCollection services, Action<IMuninServiceBuilder> configure) {}
}
+
+ public class MuninNodeBuilder : IMuninNodeBuilder {
+ internal protected MuninNodeBuilder(IMuninServiceBuilder serviceBuilder, string serviceKey) {}
+
+ public string ServiceKey { get; }
+ public IServiceCollection Services { get; }
+
+ protected virtual IMuninNode Build(IPluginProvider pluginProvider, IMuninNodeListenerFactory? listenerFactory, IServiceProvider serviceProvider) {}
+ public IMuninNode Build(IServiceProvider serviceProvider) {}
+ protected TMuninNodeOptions GetConfiguredOptions<TMuninNodeOptions>(IServiceProvider serviceProvider) where TMuninNodeOptions : MuninNodeOptions {}
+ }
+
+ public static class MuninNodeBuilderExtensions {
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IPlugin> buildPlugin) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IPlugin plugin) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNode Build<TMuninNode>(this MuninNodeBuilder builder, IServiceProvider serviceProvider) where TMuninNode : IMuninNode {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IMuninNodeListenerFactory listenerFactory) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IPluginProvider> buildPluginProvider) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IPluginProvider pluginProvider) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, INodeSessionCallback> buildSessionCallback) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc, Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, INodeSessionCallback sessionCallback) where TMuninNodeBuilder : MuninNodeBuilder {}
+ }
}
namespace Smdn.Net.MuninNode.Protocol {
public interface IMuninNodeProfile {
Encoding Encoding { get; }
string HostName { get; }
IPluginProvider PluginProvider { get; }
string Version { get; }
}
public interface IMuninProtocolHandler {
ValueTask HandleCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken);
ValueTask HandleTransactionEndAsync(IMuninNodeClient client, CancellationToken cancellationToken);
ValueTask HandleTransactionStartAsync(IMuninNodeClient client, CancellationToken cancellationToken);
}
public interface IMuninProtocolHandlerFactory {
ValueTask<IMuninProtocolHandler> CreateAsync(IMuninNodeProfile profile, CancellationToken cancellationToken);
}
public class MuninProtocolHandler : IMuninProtocolHandler {
public MuninProtocolHandler(IMuninNodeProfile profile) {}
protected bool IsDirtyConfigEnabled { get; }
protected bool IsMultigraphEnabled { get; }
protected virtual ValueTask HandleCapCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
public ValueTask HandleCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleCommandAsyncCore(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleConfigCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual async ValueTask HandleFetchCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleListCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleNodesCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleQuitCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
public ValueTask HandleTransactionEndAsync(IMuninNodeClient client, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleTransactionEndAsyncCore(IMuninNodeClient client, CancellationToken cancellationToken) {}
public ValueTask HandleTransactionStartAsync(IMuninNodeClient client, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleTransactionStartAsyncCore(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleVersionCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected ValueTask SendResponseAsync(IMuninNodeClient client, IEnumerable<string> responseLines, CancellationToken cancellationToken) {}
}
public static class MuninProtocolHandlerFactory {
public static IMuninProtocolHandlerFactory Default { get; }
}
}
namespace Smdn.Net.MuninNode.Transport {
public interface IMuninNodeClient :
IAsyncDisposable,
IDisposable
{
EndPoint? EndPoint { get; }
ValueTask DisconnectAsync(CancellationToken cancellationToken);
ValueTask<int> ReceiveAsync(IBufferWriter<byte> buffer, CancellationToken cancellationToken);
ValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken);
}
public interface IMuninNodeListener :
IAsyncDisposable,
IDisposable
{
EndPoint? EndPoint { get; }
ValueTask<IMuninNodeClient> AcceptAsync(CancellationToken cancellationToken);
ValueTask StartAsync(CancellationToken cancellationToken);
}
public interface IMuninNodeListenerFactory {
ValueTask<IMuninNodeListener> CreateAsync(EndPoint endPoint, IMuninNode node, CancellationToken cancellationToken);
}
public sealed class MuninNodeClientDisconnectedException : InvalidOperationException {
public MuninNodeClientDisconnectedException() {}
public MuninNodeClientDisconnectedException(string message) {}
public MuninNodeClientDisconnectedException(string message, Exception innerException) {}
}
}
namespace Smdn.Net.MuninPlugin {
public interface IMultigraphPlugin : IPlugin {
IReadOnlyCollection<IPlugin> Plugins { get; }
}
public interface INodeSessionCallback {
ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken);
ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken);
}
public interface IPlugin {
IPluginDataSource DataSource { get; }
IPluginGraphAttributes GraphAttributes { get; }
string Name { get; }
INodeSessionCallback? SessionCallback { get; }
}
public interface IPluginDataSource {
IReadOnlyCollection<IPluginField> Fields { get; }
}
public interface IPluginField {
PluginFieldAttributes Attributes { get; }
string Name { get; }
ValueTask<string> GetFormattedValueStringAsync(CancellationToken cancellationToken);
}
public interface IPluginGraphAttributes {
IEnumerable<string> EnumerateAttributes();
}
public interface IPluginProvider {
IReadOnlyCollection<IPlugin> Plugins { get; }
INodeSessionCallback? SessionCallback { get; }
}
public enum PluginFieldGraphStyle : int {
Area = 1,
AreaStack = 3,
Default = 0,
Line = 100,
LineStack = 200,
LineStackWidth1 = 201,
LineStackWidth2 = 202,
LineStackWidth3 = 203,
LineWidth1 = 101,
LineWidth2 = 102,
LineWidth3 = 103,
Stack = 2,
}
public enum WellKnownCategory : int {
AntiVirus = 2,
ApplicationServer = 3,
AuthenticationServer = 4,
Backup = 5,
Cloud = 7,
ContentManagementSystem = 8,
Cpu = 9,
DatabaseServer = 10,
DevelopmentTool = 11,
Disk = 12,
Dns = 13,
FileSystem = 16,
FileTransfer = 14,
Forum = 15,
GameServer = 18,
HighThroughputComputing = 19,
LoadBalancer = 20,
Mail = 21,
MailingList = 22,
Memory = 23,
MessagingServer = 6,
Munin = 24,
Network = 25,
NetworkFiltering = 17,
OneSec = 1,
Other = 0,
Printing = 26,
Process = 27,
Radio = 28,
Search = 30,
Security = 31,
Sensor = 32,
SpamFilter = 33,
StorageAreaNetwork = 29,
Streaming = 34,
System = 35,
TimeSynchronization = 36,
Video = 37,
Virtualization = 38,
VoIP = 39,
WebServer = 40,
Wiki = 41,
Wireless = 42,
}
public sealed class AggregatePluginProvider :
ReadOnlyCollection<IPluginProvider>,
INodeSessionCallback,
IPluginProvider
{
public AggregatePluginProvider(IList<IPluginProvider> pluginProviders) {}
public IReadOnlyCollection<IPlugin> Plugins { get; }
INodeSessionCallback? IPluginProvider.SessionCallback { get; }
async ValueTask INodeSessionCallback.ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
async ValueTask INodeSessionCallback.ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
}
public class MultigraphPlugin : IMultigraphPlugin {
public MultigraphPlugin(string name, IReadOnlyCollection<IPlugin> plugins) {}
public IPluginDataSource DataSource { get; }
public IPluginGraphAttributes GraphAttributes { get; }
public string Name { get; }
public IReadOnlyCollection<IPlugin> Plugins { get; }
public INodeSessionCallback? SessionCallback { get; }
}
public class Plugin :
INodeSessionCallback,
IPlugin,
IPluginDataSource
{
public Plugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
public IReadOnlyCollection<IPluginField> Fields { get; }
public PluginGraphAttributes GraphAttributes { get; }
public string Name { get; }
IPluginDataSource IPlugin.DataSource { get; }
IPluginGraphAttributes IPlugin.GraphAttributes { get; }
INodeSessionCallback? IPlugin.SessionCallback { get; }
IReadOnlyCollection<IPluginField> IPluginDataSource.Fields { get; }
protected virtual ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
protected virtual ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
ValueTask INodeSessionCallback.ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
ValueTask INodeSessionCallback.ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
}
public static class PluginFactory {
public static IPluginField CreateField(string label, Func<double?> fetchValue) {}
public static IPluginField CreateField(string label, PluginFieldGraphStyle graphStyle, Func<double?> fetchValue) {}
public static IPluginField CreateField(string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, Func<double?> fetchValue) {}
public static IPluginField CreateField(string name, string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, Func<double?> fetchValue) {}
public static IPluginField CreateField(string name, string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName, Func<double?> fetchValue) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, IReadOnlyCollection<PluginFieldBase> fields) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, PluginFieldBase field) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<PluginFieldBase> fields) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, PluginFieldBase field) {}
public static IPlugin CreatePlugin(string name, string fieldLabel, Func<double?> fetchFieldValue, IPluginGraphAttributes graphAttributes) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, string fieldLabel, Func<double?> fetchFieldValue, PluginGraphAttributes graphAttributes) {}
public static IPlugin CreatePlugin(string name, string fieldLabel, PluginFieldGraphStyle fieldGraphStyle, Func<double?> fetchFieldValue, IPluginGraphAttributes graphAttributes) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, string fieldLabel, PluginFieldGraphStyle fieldGraphStyle, Func<double?> fetchFieldValue, PluginGraphAttributes graphAttributes) {}
}
public abstract class PluginFieldBase : IPluginField {
protected PluginFieldBase(string label, string? name, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default, PluginFieldNormalValueRange normalRangeForWarning = default, PluginFieldNormalValueRange normalRangeForCritical = default) {}
protected PluginFieldBase(string label, string? name, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName) {}
public PluginFieldGraphStyle GraphStyle { get; }
public string Label { get; }
public string Name { get; }
public string? NegativeFieldName { get; }
public PluginFieldNormalValueRange NormalRangeForCritical { get; }
public PluginFieldNormalValueRange NormalRangeForWarning { get; }
PluginFieldAttributes IPluginField.Attributes { get; }
protected abstract ValueTask<double?> FetchValueAsync(CancellationToken cancellationToken);
async ValueTask<string> IPluginField.GetFormattedValueStringAsync(CancellationToken cancellationToken) {}
}
public sealed class PluginGraphAttributes : IPluginGraphAttributes {
public PluginGraphAttributes(string title, string category, string verticalLabel, bool scale, string arguments) {}
public PluginGraphAttributes(string title, string category, string verticalLabel, bool scale, string arguments, TimeSpan? updateRate, int? width, int? height, IEnumerable<string>? order, string? totalValueLabel) {}
public string Arguments { get; }
public string Category { get; }
public int? Height { get; }
public string? Order { get; }
public bool Scale { get; }
public string Title { get; }
public string? TotalValueLabel { get; }
public TimeSpan? UpdateRate { get; }
public string VerticalLabel { get; }
public int? Width { get; }
public IEnumerable<string> EnumerateAttributes() {}
}
public class PluginGraphAttributesBuilder {
public static Regex RegexCategory { get; }
public static Regex RegexTitle { get; }
public PluginGraphAttributesBuilder(string title) {}
public PluginGraphAttributesBuilder(string title, PluginGraphAttributesBuilder baseBuilder) {}
public PluginGraphAttributesBuilder AddGraphArgument(string argument) {}
public IPluginGraphAttributes Build() {}
public PluginGraphAttributesBuilder ClearGraphArguments() {}
public PluginGraphAttributesBuilder DisableUnitScaling() {}
public PluginGraphAttributesBuilder EnableUnitScaling() {}
public PluginGraphAttributesBuilder HideGraph() {}
public PluginGraphAttributesBuilder ShowGraph() {}
public PluginGraphAttributesBuilder WithCategory(WellKnownCategory category) {}
public PluginGraphAttributesBuilder WithCategory(string category) {}
public PluginGraphAttributesBuilder WithCategoryOther() {}
public PluginGraphAttributesBuilder WithFieldOrder(IEnumerable<string> order) {}
public PluginGraphAttributesBuilder WithFormatString(string printf) {}
public PluginGraphAttributesBuilder WithGraphBinaryBase() {}
public PluginGraphAttributesBuilder WithGraphDecimalBase() {}
public PluginGraphAttributesBuilder WithGraphLimit(double lowerLimitValue, double upperLimitValue) {}
public PluginGraphAttributesBuilder WithGraphLogarithmic() {}
public PluginGraphAttributesBuilder WithGraphLowerLimit(double @value) {}
public PluginGraphAttributesBuilder WithGraphRigid() {}
public PluginGraphAttributesBuilder WithGraphUpperLimit(double @value) {}
public PluginGraphAttributesBuilder WithHeight(int height) {}
public PluginGraphAttributesBuilder WithSize(int width, int height) {}
+ [MemberNotNull("title")]
+ public PluginGraphAttributesBuilder WithTitle(string title) {}
public PluginGraphAttributesBuilder WithTotal(string labelForTotal) {}
public PluginGraphAttributesBuilder WithUpdateRate(TimeSpan updateRate) {}
public PluginGraphAttributesBuilder WithVerticalLabel(string verticalLabel) {}
public PluginGraphAttributesBuilder WithWidth(int width) {}
}
public readonly struct PluginFieldAttributes {
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default) {}
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default, PluginFieldNormalValueRange normalRangeForWarning = default, PluginFieldNormalValueRange normalRangeForCritical = default) {}
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName) {}
public PluginFieldGraphStyle GraphStyle { get; }
public string Label { get; }
public string? NegativeFieldName { get; }
public PluginFieldNormalValueRange NormalRangeForCritical { get; }
public PluginFieldNormalValueRange NormalRangeForWarning { get; }
}
public readonly struct PluginFieldNormalValueRange {
public static readonly PluginFieldNormalValueRange None; // = "Smdn.Net.MuninPlugin.PluginFieldNormalValueRange"
public static PluginFieldNormalValueRange CreateMax(double max) {}
public static PluginFieldNormalValueRange CreateMin(double min) {}
public static PluginFieldNormalValueRange CreateRange(double min, double max) {}
public bool HasValue { get; }
public double? Max { get; }
public double? Min { get; }
}
}
// API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.5.0.0.
// Smdn.Reflection.ReverseGenerating.ListApi.Core v1.3.1.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-netstandard2.1.apilist.cs b/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-netstandard2.1.apilist.cs
index 640a17f..1cf4e93 100644
--- a/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-netstandard2.1.apilist.cs
+++ b/doc/api-list/Smdn.Net.MuninNode/Smdn.Net.MuninNode-netstandard2.1.apilist.cs
@@ -1,501 +1,537 @@
-// Smdn.Net.MuninNode.dll (Smdn.Net.MuninNode-2.4.0)
+// Smdn.Net.MuninNode.dll (Smdn.Net.MuninNode-2.5.0)
// Name: Smdn.Net.MuninNode
-// AssemblyVersion: 2.4.0.0
-// InformationalVersion: 2.4.0+6578cec572157dafbc9518cc746aae28f7f1ce6d
+// AssemblyVersion: 2.5.0.0
+// InformationalVersion: 2.5.0+41ff114bf69b864033a05a389896010d3eefe4d5
// TargetFramework: .NETStandard,Version=v2.1
// Configuration: Release
// Referenced assemblies:
// Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.Extensions.Options, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Smdn.Fundamental.Encoding.Buffer, Version=3.0.0.0, Culture=neutral
// Smdn.Fundamental.Exception, Version=3.0.0.0, Culture=neutral
// System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
#nullable enable annotations
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Smdn.Net.MuninNode;
using Smdn.Net.MuninNode.DependencyInjection;
using Smdn.Net.MuninNode.Protocol;
using Smdn.Net.MuninNode.Transport;
using Smdn.Net.MuninPlugin;
namespace Smdn.Net.MuninNode {
public interface IAccessRule {
bool IsAcceptable(IPEndPoint remoteEndPoint);
}
public interface IMuninNode {
EndPoint EndPoint { get; }
string HostName { get; }
Task RunAsync(CancellationToken cancellationToken);
}
public static class IAccessRuleServiceCollectionExtensions {
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IAccessRule accessRule) {}
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IReadOnlyList<IPAddress> addressListAllowFrom) {}
public static IServiceCollection AddMuninNodeAccessRule(this IServiceCollection services, IReadOnlyList<IPAddress> addressListAllowFrom, bool shouldConsiderIPv4MappedIPv6Address) {}
public static IServiceCollection AddMuninNodeLoopbackOnlyAccessRule(this IServiceCollection services) {}
}
public abstract class LocalNode : NodeBase {
public static LocalNode Create(IPluginProvider pluginProvider, int port, string? hostName = null, IReadOnlyList<IPAddress>? addressListAllowFrom = null, IServiceProvider? serviceProvider = null) {}
public static LocalNode Create(IReadOnlyCollection<IPlugin> plugins, int port, string? hostName = null, IReadOnlyList<IPAddress>? addressListAllowFrom = null, IServiceProvider? serviceProvider = null) {}
[Obsolete("Use a constructor overload that takes IMuninNodeListenerFactory as an argument.")]
protected LocalNode(IAccessRule? accessRule, ILogger? logger = null) {}
protected LocalNode(IMuninNodeListenerFactory? listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
[Obsolete("Use IMuninNodeListenerFactory and StartAsync instead.")]
protected override Socket CreateServerSocket() {}
}
- public sealed class MuninNodeOptions {
+ public class MuninNodeOptions {
public const string DefaultHostName = "munin-node.localhost";
public const int DefaultPort = 4949;
public static IPAddress DefaultAddress { get; }
public MuninNodeOptions() {}
public IAccessRule? AccessRule { get; set; }
public IPAddress Address { get; set; }
public string HostName { get; set; }
public int Port { get; set; }
public MuninNodeOptions AllowFrom(IReadOnlyList<IPAddress> addresses, bool shouldConsiderIPv4MappedIPv6Address = true) {}
public MuninNodeOptions AllowFromLoopbackOnly() {}
+ internal protected virtual void Configure(MuninNodeOptions baseOptions) {}
public MuninNodeOptions UseAnyAddress() {}
public MuninNodeOptions UseAnyAddress(int port) {}
public MuninNodeOptions UseLoopbackAddress() {}
public MuninNodeOptions UseLoopbackAddress(int port) {}
}
public abstract class NodeBase :
IAsyncDisposable,
IDisposable,
IMuninNode,
IMuninNodeProfile
{
[Obsolete("Use a constructor overload that takes IMuninNodeListenerFactory as an argument.")]
protected NodeBase(IAccessRule? accessRule, ILogger? logger) {}
protected NodeBase(IMuninNodeListenerFactory listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
protected NodeBase(IMuninProtocolHandlerFactory protocolHandlerFactory, IMuninNodeListenerFactory listenerFactory, IAccessRule? accessRule, ILogger? logger) {}
public virtual Encoding Encoding { get; }
public EndPoint EndPoint { get; }
public abstract string HostName { get; }
protected IMuninNodeListener? Listener { get; }
[Obsolete("Use EndPoint instead.")]
public EndPoint LocalEndPoint { get; }
protected ILogger? Logger { get; }
public virtual Version NodeVersion { get; }
public abstract IPluginProvider PluginProvider { get; }
string IMuninNodeProfile.Version { get; }
public async ValueTask AcceptAsync(bool throwIfCancellationRequested, CancellationToken cancellationToken) {}
public async ValueTask AcceptSingleSessionAsync(CancellationToken cancellationToken = default) {}
[Obsolete("Use IMuninNodeListenerFactory and StartAsync instead.")]
protected virtual Socket CreateServerSocket() {}
protected virtual void Dispose(bool disposing) {}
public void Dispose() {}
public async ValueTask DisposeAsync() {}
protected virtual async ValueTask DisposeAsyncCore() {}
protected virtual EndPoint GetLocalEndPointToBind() {}
protected virtual IMuninNodeProfile GetNodeProfile() {}
public Task RunAsync(CancellationToken cancellationToken) {}
[Obsolete("This method will be deprecated in the future.Use IMuninNodeListenerFactory and StartAsync instead.Make sure to override CreateServerSocket if you need to use this method.")]
public void Start() {}
public ValueTask StartAsync(CancellationToken cancellationToken = default) {}
+ protected virtual ValueTask StartedAsync(CancellationToken cancellationToken) {}
+ protected virtual ValueTask StartingAsync(CancellationToken cancellationToken) {}
public ValueTask StopAsync(CancellationToken cancellationToken = default) {}
+ protected virtual ValueTask StoppedAsync(CancellationToken cancellationToken) {}
+ protected virtual ValueTask StoppingAsync(CancellationToken cancellationToken) {}
protected void ThrowIfDisposed() {}
protected void ThrowIfPluginProviderIsNull() {}
}
}
namespace Smdn.Net.MuninNode.DependencyInjection {
+ [Obsolete("Use or inherit MuninNodeBuilder instead.")]
public interface IMuninNodeBuilder {
string ServiceKey { get; }
IServiceCollection Services { get; }
IMuninNode Build(IServiceProvider serviceProvider);
}
public interface IMuninServiceBuilder {
IServiceCollection Services { get; }
}
+ [Obsolete("Use MuninNodeBuilderExtensions instead.")]
public static class IMuninNodeBuilderExtensions {
public static IMuninNodeBuilder AddPlugin(this IMuninNodeBuilder builder, Func<IServiceProvider, IPlugin> buildPlugin) {}
public static IMuninNodeBuilder AddPlugin(this IMuninNodeBuilder builder, IPlugin plugin) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory) {}
public static IMuninNodeBuilder UseListenerFactory(this IMuninNodeBuilder builder, IMuninNodeListenerFactory listenerFactory) {}
public static IMuninNodeBuilder UsePluginProvider(this IMuninNodeBuilder builder, Func<IServiceProvider, IPluginProvider> buildPluginProvider) {}
public static IMuninNodeBuilder UsePluginProvider(this IMuninNodeBuilder builder, IPluginProvider pluginProvider) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, Func<IServiceProvider, INodeSessionCallback> buildSessionCallback) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc, Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc) {}
public static IMuninNodeBuilder UseSessionCallback(this IMuninNodeBuilder builder, INodeSessionCallback sessionCallback) {}
}
public static class IMuninServiceBuilderExtensions {
public static IMuninNodeBuilder AddNode(this IMuninServiceBuilder builder) {}
public static IMuninNodeBuilder AddNode(this IMuninServiceBuilder builder, Action<MuninNodeOptions> configure) {}
+ public static TMuninNodeBuilder AddNode<TMuninNode, TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNode : class, IMuninNode where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddNode<TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddNode<TMuninNodeService, TMuninNodeImplementation, TMuninNodeOptions, TMuninNodeBuilder>(this IMuninServiceBuilder builder, Action<TMuninNodeOptions> configure, Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder) where TMuninNodeService : class, IMuninNode where TMuninNodeImplementation : class, TMuninNodeService where TMuninNodeOptions : MuninNodeOptions, new() where TMuninNodeBuilder : MuninNodeBuilder {}
}
public static class IServiceCollectionExtensions {
public static IServiceCollection AddMunin(this IServiceCollection services, Action<IMuninServiceBuilder> configure) {}
}
+
+ public class MuninNodeBuilder : IMuninNodeBuilder {
+ internal protected MuninNodeBuilder(IMuninServiceBuilder serviceBuilder, string serviceKey) {}
+
+ public string ServiceKey { get; }
+ public IServiceCollection Services { get; }
+
+ protected virtual IMuninNode Build(IPluginProvider pluginProvider, IMuninNodeListenerFactory? listenerFactory, IServiceProvider serviceProvider) {}
+ public IMuninNode Build(IServiceProvider serviceProvider) {}
+ protected TMuninNodeOptions GetConfiguredOptions<TMuninNodeOptions>(IServiceProvider serviceProvider) where TMuninNodeOptions : MuninNodeOptions {}
+ }
+
+ public static class MuninNodeBuilderExtensions {
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IPlugin> buildPlugin) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IPlugin plugin) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNode Build<TMuninNode>(this MuninNodeBuilder builder, IServiceProvider serviceProvider) where TMuninNode : IMuninNode {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IMuninNodeListenerFactory listenerFactory) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, IPluginProvider> buildPluginProvider) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(this TMuninNodeBuilder builder, IPluginProvider pluginProvider) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<IServiceProvider, INodeSessionCallback> buildSessionCallback) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc, Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc) where TMuninNodeBuilder : MuninNodeBuilder {}
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(this TMuninNodeBuilder builder, INodeSessionCallback sessionCallback) where TMuninNodeBuilder : MuninNodeBuilder {}
+ }
}
namespace Smdn.Net.MuninNode.Protocol {
public interface IMuninNodeProfile {
Encoding Encoding { get; }
string HostName { get; }
IPluginProvider PluginProvider { get; }
string Version { get; }
}
public interface IMuninProtocolHandler {
ValueTask HandleCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken);
ValueTask HandleTransactionEndAsync(IMuninNodeClient client, CancellationToken cancellationToken);
ValueTask HandleTransactionStartAsync(IMuninNodeClient client, CancellationToken cancellationToken);
}
public interface IMuninProtocolHandlerFactory {
ValueTask<IMuninProtocolHandler> CreateAsync(IMuninNodeProfile profile, CancellationToken cancellationToken);
}
public class MuninProtocolHandler : IMuninProtocolHandler {
public MuninProtocolHandler(IMuninNodeProfile profile) {}
protected bool IsDirtyConfigEnabled { get; }
protected bool IsMultigraphEnabled { get; }
protected virtual ValueTask HandleCapCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
public ValueTask HandleCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleCommandAsyncCore(IMuninNodeClient client, ReadOnlySequence<byte> commandLine, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleConfigCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual async ValueTask HandleFetchCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleListCommandAsync(IMuninNodeClient client, ReadOnlySequence<byte> arguments, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleNodesCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleQuitCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
public ValueTask HandleTransactionEndAsync(IMuninNodeClient client, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleTransactionEndAsyncCore(IMuninNodeClient client, CancellationToken cancellationToken) {}
public ValueTask HandleTransactionStartAsync(IMuninNodeClient client, CancellationToken cancellationToken = default) {}
protected virtual ValueTask HandleTransactionStartAsyncCore(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected virtual ValueTask HandleVersionCommandAsync(IMuninNodeClient client, CancellationToken cancellationToken) {}
protected ValueTask SendResponseAsync(IMuninNodeClient client, IEnumerable<string> responseLines, CancellationToken cancellationToken) {}
}
public static class MuninProtocolHandlerFactory {
public static IMuninProtocolHandlerFactory Default { get; }
}
}
namespace Smdn.Net.MuninNode.Transport {
public interface IMuninNodeClient :
IAsyncDisposable,
IDisposable
{
EndPoint? EndPoint { get; }
ValueTask DisconnectAsync(CancellationToken cancellationToken);
ValueTask<int> ReceiveAsync(IBufferWriter<byte> buffer, CancellationToken cancellationToken);
ValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken);
}
public interface IMuninNodeListener :
IAsyncDisposable,
IDisposable
{
EndPoint? EndPoint { get; }
ValueTask<IMuninNodeClient> AcceptAsync(CancellationToken cancellationToken);
ValueTask StartAsync(CancellationToken cancellationToken);
}
public interface IMuninNodeListenerFactory {
ValueTask<IMuninNodeListener> CreateAsync(EndPoint endPoint, IMuninNode node, CancellationToken cancellationToken);
}
public sealed class MuninNodeClientDisconnectedException : InvalidOperationException {
public MuninNodeClientDisconnectedException() {}
public MuninNodeClientDisconnectedException(string message) {}
public MuninNodeClientDisconnectedException(string message, Exception innerException) {}
}
}
namespace Smdn.Net.MuninPlugin {
public interface IMultigraphPlugin : IPlugin {
IReadOnlyCollection<IPlugin> Plugins { get; }
}
public interface INodeSessionCallback {
ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken);
ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken);
}
public interface IPlugin {
IPluginDataSource DataSource { get; }
IPluginGraphAttributes GraphAttributes { get; }
string Name { get; }
INodeSessionCallback? SessionCallback { get; }
}
public interface IPluginDataSource {
IReadOnlyCollection<IPluginField> Fields { get; }
}
public interface IPluginField {
PluginFieldAttributes Attributes { get; }
string Name { get; }
ValueTask<string> GetFormattedValueStringAsync(CancellationToken cancellationToken);
}
public interface IPluginGraphAttributes {
IEnumerable<string> EnumerateAttributes();
}
public interface IPluginProvider {
IReadOnlyCollection<IPlugin> Plugins { get; }
INodeSessionCallback? SessionCallback { get; }
}
public enum PluginFieldGraphStyle : int {
Area = 1,
AreaStack = 3,
Default = 0,
Line = 100,
LineStack = 200,
LineStackWidth1 = 201,
LineStackWidth2 = 202,
LineStackWidth3 = 203,
LineWidth1 = 101,
LineWidth2 = 102,
LineWidth3 = 103,
Stack = 2,
}
public enum WellKnownCategory : int {
AntiVirus = 2,
ApplicationServer = 3,
AuthenticationServer = 4,
Backup = 5,
Cloud = 7,
ContentManagementSystem = 8,
Cpu = 9,
DatabaseServer = 10,
DevelopmentTool = 11,
Disk = 12,
Dns = 13,
FileSystem = 16,
FileTransfer = 14,
Forum = 15,
GameServer = 18,
HighThroughputComputing = 19,
LoadBalancer = 20,
Mail = 21,
MailingList = 22,
Memory = 23,
MessagingServer = 6,
Munin = 24,
Network = 25,
NetworkFiltering = 17,
OneSec = 1,
Other = 0,
Printing = 26,
Process = 27,
Radio = 28,
Search = 30,
Security = 31,
Sensor = 32,
SpamFilter = 33,
StorageAreaNetwork = 29,
Streaming = 34,
System = 35,
TimeSynchronization = 36,
Video = 37,
Virtualization = 38,
VoIP = 39,
WebServer = 40,
Wiki = 41,
Wireless = 42,
}
public sealed class AggregatePluginProvider :
ReadOnlyCollection<IPluginProvider>,
INodeSessionCallback,
IPluginProvider
{
public AggregatePluginProvider(IList<IPluginProvider> pluginProviders) {}
public IReadOnlyCollection<IPlugin> Plugins { get; }
INodeSessionCallback? IPluginProvider.SessionCallback { get; }
async ValueTask INodeSessionCallback.ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
async ValueTask INodeSessionCallback.ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
}
public class MultigraphPlugin : IMultigraphPlugin {
public MultigraphPlugin(string name, IReadOnlyCollection<IPlugin> plugins) {}
public IPluginDataSource DataSource { get; }
public IPluginGraphAttributes GraphAttributes { get; }
public string Name { get; }
public IReadOnlyCollection<IPlugin> Plugins { get; }
public INodeSessionCallback? SessionCallback { get; }
}
public class Plugin :
INodeSessionCallback,
IPlugin,
IPluginDataSource
{
public Plugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
public IReadOnlyCollection<IPluginField> Fields { get; }
public PluginGraphAttributes GraphAttributes { get; }
public string Name { get; }
IPluginDataSource IPlugin.DataSource { get; }
IPluginGraphAttributes IPlugin.GraphAttributes { get; }
INodeSessionCallback? IPlugin.SessionCallback { get; }
IReadOnlyCollection<IPluginField> IPluginDataSource.Fields { get; }
protected virtual ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
protected virtual ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
ValueTask INodeSessionCallback.ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken) {}
ValueTask INodeSessionCallback.ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken) {}
}
public static class PluginFactory {
public static IPluginField CreateField(string label, Func<double?> fetchValue) {}
public static IPluginField CreateField(string label, PluginFieldGraphStyle graphStyle, Func<double?> fetchValue) {}
public static IPluginField CreateField(string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, Func<double?> fetchValue) {}
public static IPluginField CreateField(string name, string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, Func<double?> fetchValue) {}
public static IPluginField CreateField(string name, string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName, Func<double?> fetchValue) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, IReadOnlyCollection<PluginFieldBase> fields) {}
public static IPlugin CreatePlugin(string name, IPluginGraphAttributes graphAttributes, PluginFieldBase field) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<IPluginField> fields) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, IReadOnlyCollection<PluginFieldBase> fields) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, PluginGraphAttributes graphAttributes, PluginFieldBase field) {}
public static IPlugin CreatePlugin(string name, string fieldLabel, Func<double?> fetchFieldValue, IPluginGraphAttributes graphAttributes) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, string fieldLabel, Func<double?> fetchFieldValue, PluginGraphAttributes graphAttributes) {}
public static IPlugin CreatePlugin(string name, string fieldLabel, PluginFieldGraphStyle fieldGraphStyle, Func<double?> fetchFieldValue, IPluginGraphAttributes graphAttributes) {}
[Obsolete("Use overloads that accept IPluginGraphAttributes instead.")]
public static IPlugin CreatePlugin(string name, string fieldLabel, PluginFieldGraphStyle fieldGraphStyle, Func<double?> fetchFieldValue, PluginGraphAttributes graphAttributes) {}
}
public abstract class PluginFieldBase : IPluginField {
protected PluginFieldBase(string label, string? name, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default, PluginFieldNormalValueRange normalRangeForWarning = default, PluginFieldNormalValueRange normalRangeForCritical = default) {}
protected PluginFieldBase(string label, string? name, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName) {}
public PluginFieldGraphStyle GraphStyle { get; }
public string Label { get; }
public string Name { get; }
public string? NegativeFieldName { get; }
public PluginFieldNormalValueRange NormalRangeForCritical { get; }
public PluginFieldNormalValueRange NormalRangeForWarning { get; }
PluginFieldAttributes IPluginField.Attributes { get; }
protected abstract ValueTask<double?> FetchValueAsync(CancellationToken cancellationToken);
async ValueTask<string> IPluginField.GetFormattedValueStringAsync(CancellationToken cancellationToken) {}
}
public sealed class PluginGraphAttributes : IPluginGraphAttributes {
public PluginGraphAttributes(string title, string category, string verticalLabel, bool scale, string arguments) {}
public PluginGraphAttributes(string title, string category, string verticalLabel, bool scale, string arguments, TimeSpan? updateRate, int? width, int? height, IEnumerable<string>? order, string? totalValueLabel) {}
public string Arguments { get; }
public string Category { get; }
public int? Height { get; }
public string? Order { get; }
public bool Scale { get; }
public string Title { get; }
public string? TotalValueLabel { get; }
public TimeSpan? UpdateRate { get; }
public string VerticalLabel { get; }
public int? Width { get; }
public IEnumerable<string> EnumerateAttributes() {}
}
public class PluginGraphAttributesBuilder {
public static Regex RegexCategory { get; }
public static Regex RegexTitle { get; }
public PluginGraphAttributesBuilder(string title) {}
public PluginGraphAttributesBuilder(string title, PluginGraphAttributesBuilder baseBuilder) {}
public PluginGraphAttributesBuilder AddGraphArgument(string argument) {}
public IPluginGraphAttributes Build() {}
public PluginGraphAttributesBuilder ClearGraphArguments() {}
public PluginGraphAttributesBuilder DisableUnitScaling() {}
public PluginGraphAttributesBuilder EnableUnitScaling() {}
public PluginGraphAttributesBuilder HideGraph() {}
public PluginGraphAttributesBuilder ShowGraph() {}
public PluginGraphAttributesBuilder WithCategory(WellKnownCategory category) {}
public PluginGraphAttributesBuilder WithCategory(string category) {}
public PluginGraphAttributesBuilder WithCategoryOther() {}
public PluginGraphAttributesBuilder WithFieldOrder(IEnumerable<string> order) {}
public PluginGraphAttributesBuilder WithFormatString(string printf) {}
public PluginGraphAttributesBuilder WithGraphBinaryBase() {}
public PluginGraphAttributesBuilder WithGraphDecimalBase() {}
public PluginGraphAttributesBuilder WithGraphLimit(double lowerLimitValue, double upperLimitValue) {}
public PluginGraphAttributesBuilder WithGraphLogarithmic() {}
public PluginGraphAttributesBuilder WithGraphLowerLimit(double @value) {}
public PluginGraphAttributesBuilder WithGraphRigid() {}
public PluginGraphAttributesBuilder WithGraphUpperLimit(double @value) {}
public PluginGraphAttributesBuilder WithHeight(int height) {}
public PluginGraphAttributesBuilder WithSize(int width, int height) {}
+ public PluginGraphAttributesBuilder WithTitle(string title) {}
public PluginGraphAttributesBuilder WithTotal(string labelForTotal) {}
public PluginGraphAttributesBuilder WithUpdateRate(TimeSpan updateRate) {}
public PluginGraphAttributesBuilder WithVerticalLabel(string verticalLabel) {}
public PluginGraphAttributesBuilder WithWidth(int width) {}
}
public readonly struct PluginFieldAttributes {
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default) {}
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle = PluginFieldGraphStyle.Default, PluginFieldNormalValueRange normalRangeForWarning = default, PluginFieldNormalValueRange normalRangeForCritical = default) {}
public PluginFieldAttributes(string label, PluginFieldGraphStyle graphStyle, PluginFieldNormalValueRange normalRangeForWarning, PluginFieldNormalValueRange normalRangeForCritical, string? negativeFieldName) {}
public PluginFieldGraphStyle GraphStyle { get; }
public string Label { get; }
public string? NegativeFieldName { get; }
public PluginFieldNormalValueRange NormalRangeForCritical { get; }
public PluginFieldNormalValueRange NormalRangeForWarning { get; }
}
public readonly struct PluginFieldNormalValueRange {
public static readonly PluginFieldNormalValueRange None; // = "Smdn.Net.MuninPlugin.PluginFieldNormalValueRange"
public static PluginFieldNormalValueRange CreateMax(double max) {}
public static PluginFieldNormalValueRange CreateMin(double min) {}
public static PluginFieldNormalValueRange CreateRange(double min, double max) {}
public bool HasValue { get; }
public double? Max { get; }
public double? Min { get; }
}
}
// API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.5.0.0.
// Smdn.Reflection.ReverseGenerating.ListApi.Core v1.3.1.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
Full changes
Full changes in this release:
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilder.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilder.cs
index b17d19c..cc82372 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilder.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilder.cs
@@ -14,6 +14,7 @@ namespace Smdn.Net.MuninNode.DependencyInjection;
/// <see cref="IMuninNodeBuilderExtensions.AddPlugin"/>
/// <see cref="IMuninNodeBuilderExtensions.UseListenerFactory"/>
/// <see cref="IMuninNodeBuilderExtensions.UseSessionCallback"/>
+[Obsolete($"Use or inherit {nameof(MuninNodeBuilder)} instead.")]
public interface IMuninNodeBuilder {
/// <summary>
/// Gets the <see cref="IServiceCollection"/> where the <c>Munin-Node</c> services are configured.
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilderExtensions.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilderExtensions.cs
index 07c8689..6098230 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilderExtensions.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninNodeBuilderExtensions.cs
@@ -11,7 +11,16 @@ using Smdn.Net.MuninPlugin;
namespace Smdn.Net.MuninNode.DependencyInjection;
+[Obsolete($"Use {nameof(MuninNodeBuilderExtensions)} instead.")]
public static class IMuninNodeBuilderExtensions {
+ private static MuninNodeBuilder ThrowIfBuilderTypeIsNotSupported(IMuninNodeBuilder builder)
+ {
+ if (builder is not MuninNodeBuilder muninNodeBuilder)
+ throw new NotSupportedException($"The builder implementation of type `{builder.GetType().FullName}` does not support service key configuration.");
+
+ return muninNodeBuilder;
+ }
+
#pragma warning disable CS0419
/// <remarks>
/// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
@@ -21,17 +30,10 @@ public static class IMuninNodeBuilderExtensions {
IPlugin plugin
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (plugin is null)
- throw new ArgumentNullException(nameof(plugin));
-
- return AddPlugin(
- builder: builder,
- buildPlugin: _ => plugin
+ => MuninNodeBuilderExtensions.AddPlugin(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ plugin: plugin ?? throw new ArgumentNullException(nameof(plugin))
);
- }
#pragma warning disable CS0419
/// <remarks>
@@ -42,19 +44,10 @@ public static class IMuninNodeBuilderExtensions {
Func<IServiceProvider, IPlugin> buildPlugin
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (buildPlugin is null)
- throw new ArgumentNullException(nameof(buildPlugin));
-
- if (builder is not DefaultMuninNodeBuilder defaultMuninNodeBuilder)
- throw new NotSupportedException($"The builder implementation of type `{builder.GetType().FullName}` does not support service key configuration.");
-
- defaultMuninNodeBuilder.AddPluginFactory(buildPlugin);
-
- return builder;
- }
+ => MuninNodeBuilderExtensions.AddPlugin(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ buildPlugin: buildPlugin ?? throw new ArgumentNullException(nameof(buildPlugin))
+ );
#pragma warning disable CS0419
/// <remarks>
@@ -66,17 +59,10 @@ public static class IMuninNodeBuilderExtensions {
IPluginProvider pluginProvider
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (pluginProvider is null)
- throw new ArgumentNullException(nameof(pluginProvider));
-
- return UsePluginProvider(
- builder: builder,
- buildPluginProvider: _ => pluginProvider
+ => MuninNodeBuilderExtensions.UsePluginProvider(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ pluginProvider: pluginProvider ?? throw new ArgumentNullException(nameof(pluginProvider))
);
- }
#pragma warning disable CS0419
/// <remarks>
@@ -88,19 +74,10 @@ public static class IMuninNodeBuilderExtensions {
Func<IServiceProvider, IPluginProvider> buildPluginProvider
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (buildPluginProvider is null)
- throw new ArgumentNullException(nameof(buildPluginProvider));
-
- if (builder is not DefaultMuninNodeBuilder defaultMuninNodeBuilder)
- throw new NotSupportedException($"The builder implementation of type `{builder.GetType().FullName}` does not support service key configuration.");
-
- defaultMuninNodeBuilder.SetPluginProviderFactory(buildPluginProvider);
-
- return builder;
- }
+ => MuninNodeBuilderExtensions.UsePluginProvider(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ buildPluginProvider: buildPluginProvider ?? throw new ArgumentNullException(nameof(buildPluginProvider))
+ );
#pragma warning disable CS0419
/// <remarks>
@@ -111,17 +88,10 @@ public static class IMuninNodeBuilderExtensions {
INodeSessionCallback sessionCallback
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (sessionCallback is null)
- throw new ArgumentNullException(nameof(sessionCallback));
-
- return UseSessionCallback(
- builder: builder,
- buildSessionCallback: _ => sessionCallback
+ => MuninNodeBuilderExtensions.UseSessionCallback(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ sessionCallback: sessionCallback ?? throw new ArgumentNullException(nameof(sessionCallback))
);
- }
#pragma warning disable CS0419
/// <remarks>
@@ -133,29 +103,12 @@ public static class IMuninNodeBuilderExtensions {
Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc
)
#pragma warning restore CS0419
- => UseSessionCallback(
- builder: builder,
- buildSessionCallback: _ => new SessionCallbackFuncWrapper(
- reportSessionStartedAsyncFunc,
- reportSessionClosedAsyncFunc
- )
+ => MuninNodeBuilderExtensions.UseSessionCallback(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ reportSessionStartedAsyncFunc: reportSessionStartedAsyncFunc,
+ reportSessionClosedAsyncFunc: reportSessionClosedAsyncFunc
);
- private sealed class SessionCallbackFuncWrapper(
- Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc,
- Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc
- ) : INodeSessionCallback {
- public ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken)
- => reportSessionStartedAsyncFunc is null
- ? default
- : reportSessionStartedAsyncFunc(sessionId, cancellationToken);
-
- public ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken)
- => reportSessionClosedAsyncFunc is null
- ? default
- : reportSessionClosedAsyncFunc(sessionId, cancellationToken);
- }
-
#pragma warning disable CS0419
/// <remarks>
/// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
@@ -165,78 +118,35 @@ public static class IMuninNodeBuilderExtensions {
Func<IServiceProvider, INodeSessionCallback> buildSessionCallback
)
#pragma warning restore CS0419
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (buildSessionCallback is null)
- throw new ArgumentNullException(nameof(buildSessionCallback));
-
- if (builder is not DefaultMuninNodeBuilder defaultMuninNodeBuilder)
- throw new NotSupportedException($"The builder implementation of type `{builder.GetType().FullName}` does not support service key configuration.");
-
- defaultMuninNodeBuilder.SetSessionCallbackFactory(buildSessionCallback);
-
- return builder;
- }
+ => MuninNodeBuilderExtensions.UseSessionCallback(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ buildSessionCallback: buildSessionCallback ?? throw new ArgumentNullException(nameof(buildSessionCallback))
+ );
public static IMuninNodeBuilder UseListenerFactory(
this IMuninNodeBuilder builder,
IMuninNodeListenerFactory listenerFactory
)
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (listenerFactory is null)
- throw new ArgumentNullException(nameof(listenerFactory));
-
- return UseListenerFactory(
- builder: builder,
- buildListenerFactory: _ => listenerFactory
+ => MuninNodeBuilderExtensions.UseListenerFactory(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ listenerFactory: listenerFactory ?? throw new ArgumentNullException(nameof(listenerFactory))
);
- }
public static IMuninNodeBuilder UseListenerFactory(
this IMuninNodeBuilder builder,
Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc
)
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (createListenerAsyncFunc is null)
- throw new ArgumentNullException(nameof(createListenerAsyncFunc));
-
- return UseListenerFactory(
- builder: builder,
- buildListenerFactory: serviceProvider => new CreateListenerAsyncFuncWrapper(
- serviceProvider,
- createListenerAsyncFunc
- )
+ => MuninNodeBuilderExtensions.UseListenerFactory(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ createListenerAsyncFunc: createListenerAsyncFunc ?? throw new ArgumentNullException(nameof(createListenerAsyncFunc))
);
- }
-
- private sealed class CreateListenerAsyncFuncWrapper(
- IServiceProvider serviceProvider,
- Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc
- ) : IMuninNodeListenerFactory {
- public ValueTask<IMuninNodeListener> CreateAsync(EndPoint endPoint, IMuninNode node, CancellationToken cancellationToken)
- => createListenerAsyncFunc(serviceProvider, endPoint, node, cancellationToken);
- }
public static IMuninNodeBuilder UseListenerFactory(
this IMuninNodeBuilder builder,
Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory
)
- {
- if (builder is null)
- throw new ArgumentNullException(nameof(builder));
- if (buildListenerFactory is null)
- throw new ArgumentNullException(nameof(buildListenerFactory));
-
- if (builder is not DefaultMuninNodeBuilder defaultMuninNodeBuilder)
- throw new NotSupportedException($"The builder implementation of type `{builder.GetType().FullName}` does not support service key configuration.");
-
- defaultMuninNodeBuilder.SetListenerFactory(buildListenerFactory);
-
- return builder;
- }
+ => MuninNodeBuilderExtensions.UseListenerFactory(
+ builder: ThrowIfBuilderTypeIsNotSupported(builder ?? throw new ArgumentNullException(nameof(builder))),
+ buildListenerFactory: buildListenerFactory ?? throw new ArgumentNullException(nameof(buildListenerFactory))
+ );
}
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninServiceBuilderExtensions.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninServiceBuilderExtensions.cs
index e89bf75..8579ac9 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninServiceBuilderExtensions.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/IMuninServiceBuilderExtensions.cs
@@ -11,11 +11,15 @@ public static class IMuninServiceBuilderExtensions {
/// <summary>
/// Adds a <c>Munin-Node</c> to the <see cref="IMuninServiceBuilder"/> with default configurations.
/// </summary>
- /// <param name="builder">An <see cref="IMuninNodeBuilder"/> to build the <c>Munin-Node</c> to be added.</param>
+ /// <param name="builder">
+ /// An <see cref="IMuninServiceBuilder"/> that the built <c>Munin-Node</c> will be added to.
+ /// </param>
/// <returns>The current <see cref="IMuninNodeBuilder"/> so that additional calls can be chained.</returns>
+#pragma warning disable CS0618 // TODO: return IMuninNodeBuilder instead of MuninNodeBuilder
public static IMuninNodeBuilder AddNode(
this IMuninServiceBuilder builder
)
+#pragma warning restore CS0618
=> AddNode(
builder: builder,
configure: _ => { }
@@ -25,44 +29,202 @@ public static class IMuninServiceBuilderExtensions {
/// Adds a <c>Munin-Node</c> to the <see cref="IMuninServiceBuilder"/> with specified configurations.
/// </summary>
/// <param name="builder">
- /// An <see cref="IMuninNodeBuilder"/> to build the <c>Munin-Node</c> to be added.
+ /// An <see cref="IMuninServiceBuilder"/> that the built <c>Munin-Node</c> will be added to.
/// </param>
/// <param name="configure">
/// An <see cref="Action{MuninNodeOptions}"/> to setup <see cref="MuninNodeOptions"/> to
/// configure the <c>Munin-Node</c> to be built.
/// </param>
/// <returns>The current <see cref="IMuninNodeBuilder"/> so that additional calls can be chained.</returns>
+#pragma warning disable CS0618 // TODO: return IMuninNodeBuilder instead of MuninNodeBuilder
public static IMuninNodeBuilder AddNode(
this IMuninServiceBuilder builder,
Action<MuninNodeOptions> configure
)
+#pragma warning restore CS0618
+ => AddNode<
+ IMuninNode,
+ IMuninNode,
+ MuninNodeOptions,
+ MuninNodeBuilder
+ >(
+ builder: builder ?? throw new ArgumentNullException(nameof(builder)),
+ configure: configure ?? throw new ArgumentNullException(nameof(configure)),
+ createBuilder: static (serviceBuilder, serviceKey) => new(serviceBuilder, serviceKey)
+ );
+
+ /// <summary>
+ /// Adds a <c>Munin-Node</c> to the <see cref="IMuninServiceBuilder"/> with specified configurations.
+ /// </summary>
+ /// <typeparam name="TMuninNodeOptions">
+ /// The extended type of <see cref="MuninNodeOptions"/> to configure the <c>Munin-Node</c>.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeBuilder">
+ /// The extended type of <see cref="MuninNodeBuilder"/> to build the <c>Munin-Node</c>.
+ /// </typeparam>
+ /// <param name="builder">
+ /// An <see cref="IMuninServiceBuilder"/> that the built <c>Munin-Node</c> will be added to.
+ /// </param>
+ /// <param name="configure">
+ /// An <see cref="Action{TMuninNodeOptions}"/> to setup <typeparamref name="TMuninNodeOptions"/> to
+ /// configure the <c>Munin-Node</c> to be built.
+ /// </param>
+ /// <param name="createBuilder">
+ /// An <see cref="Func{TMuninNodeBuilder}"/> to create <typeparamref name="TMuninNodeBuilder"/> to build
+ /// the <c>Munin-Node</c>.
+ /// </param>
+ /// <returns>The current <typeparamref name="TMuninNodeBuilder"/> so that additional calls can be chained.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="builder"/> is <see langword="null"/>, or
+ /// <paramref name="configure"/> is <see langword="null"/>, or
+ /// <paramref name="createBuilder"/> is <see langword="null"/>.
+ /// </exception>
+ public static
+ TMuninNodeBuilder AddNode<
+ TMuninNodeOptions,
+ TMuninNodeBuilder
+ >(
+ this IMuninServiceBuilder builder,
+ Action<TMuninNodeOptions> configure,
+ Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder
+ )
+ where TMuninNodeOptions : MuninNodeOptions, new()
+ where TMuninNodeBuilder : MuninNodeBuilder
+ => AddNode<
+ IMuninNode,
+ IMuninNode,
+ TMuninNodeOptions,
+ TMuninNodeBuilder
+ >(
+ builder: builder ?? throw new ArgumentNullException(nameof(builder)),
+ configure: configure ?? throw new ArgumentNullException(nameof(configure)),
+ createBuilder: createBuilder ?? throw new ArgumentNullException(nameof(createBuilder))
+ );
+
+ /// <summary>
+ /// Adds a <typeparamref name="TMuninNode"/> to the <see cref="IMuninServiceBuilder"/> with specified configurations.
+ /// </summary>
+ /// <typeparam name="TMuninNode">
+ /// The type of <see cref="IMuninNode"/> service to add to the <seealso cref="IServiceCollection"/>.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeOptions">
+ /// The extended type of <see cref="MuninNodeOptions"/> to configure the <typeparamref name="TMuninNode"/>.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeBuilder">
+ /// The extended type of <see cref="MuninNodeBuilder"/> to build the <typeparamref name="TMuninNode"/>.
+ /// </typeparam>
+ /// <param name="builder">
+ /// An <see cref="IMuninServiceBuilder"/> that the built <typeparamref name="TMuninNode"/> will be added to.
+ /// </param>
+ /// <param name="configure">
+ /// An <see cref="Action{TMuninNodeOptions}"/> to setup <typeparamref name="TMuninNodeOptions"/> to
+ /// configure the <typeparamref name="TMuninNode"/> to be built.
+ /// </param>
+ /// <param name="createBuilder">
+ /// An <see cref="Func{TMuninNodeBuilder}"/> to create <typeparamref name="TMuninNodeBuilder"/> to build
+ /// the <typeparamref name="TMuninNode"/>.
+ /// </param>
+ /// <returns>The current <typeparamref name="TMuninNodeBuilder"/> so that additional calls can be chained.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="builder"/> is <see langword="null"/>, or
+ /// <paramref name="configure"/> is <see langword="null"/>, or
+ /// <paramref name="createBuilder"/> is <see langword="null"/>.
+ /// </exception>
+ public static
+ TMuninNodeBuilder AddNode<
+ TMuninNode,
+ TMuninNodeOptions,
+ TMuninNodeBuilder
+ >(
+ this IMuninServiceBuilder builder,
+ Action<TMuninNodeOptions> configure,
+ Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder
+ )
+ where TMuninNode : class, IMuninNode
+ where TMuninNodeOptions : MuninNodeOptions, new()
+ where TMuninNodeBuilder : MuninNodeBuilder
+ => AddNode<
+ TMuninNode,
+ TMuninNode,
+ TMuninNodeOptions,
+ TMuninNodeBuilder
+ >(
+ builder: builder ?? throw new ArgumentNullException(nameof(builder)),
+ configure: configure ?? throw new ArgumentNullException(nameof(configure)),
+ createBuilder: createBuilder ?? throw new ArgumentNullException(nameof(createBuilder))
+ );
+
+ /// <summary>
+ /// Adds a <typeparamref name="TMuninNodeImplementation"/> to the <see cref="IMuninServiceBuilder"/> with specified configurations.
+ /// </summary>
+ /// <typeparam name="TMuninNodeService">
+ /// The type of <see cref="IMuninNode"/> service to add to the <seealso cref="IServiceCollection"/>.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeImplementation">
+ /// The type of <typeparamref name="TMuninNodeService"/> implementation.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeOptions">
+ /// The extended type of <see cref="MuninNodeOptions"/> to configure the <typeparamref name="TMuninNodeImplementation"/>.
+ /// </typeparam>
+ /// <typeparam name="TMuninNodeBuilder">
+ /// The extended type of <see cref="MuninNodeBuilder"/> to build the <typeparamref name="TMuninNodeImplementation"/>.
+ /// </typeparam>
+ /// <param name="builder">
+ /// An <see cref="IMuninServiceBuilder"/> that the built <typeparamref name="TMuninNodeImplementation"/> will be added to.
+ /// </param>
+ /// <param name="configure">
+ /// An <see cref="Action{TMuninNodeOptions}"/> to setup <typeparamref name="TMuninNodeOptions"/> to
+ /// configure the <typeparamref name="TMuninNodeImplementation"/> to be built.
+ /// </param>
+ /// <param name="createBuilder">
+ /// An <see cref="Func{TMuninNodeBuilder}"/> to create <typeparamref name="TMuninNodeBuilder"/> to build
+ /// the <typeparamref name="TMuninNodeImplementation"/>.
+ /// </param>
+ /// <returns>The current <see cref="IMuninNodeBuilder"/> so that additional calls can be chained.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="builder"/> is <see langword="null"/>, or
+ /// <paramref name="configure"/> is <see langword="null"/>, or
+ /// <paramref name="createBuilder"/> is <see langword="null"/>.
+ /// </exception>
+ public static
+ TMuninNodeBuilder AddNode<
+ TMuninNodeService,
+ TMuninNodeImplementation,
+ TMuninNodeOptions,
+ TMuninNodeBuilder
+ >(
+ this IMuninServiceBuilder builder,
+ Action<TMuninNodeOptions> configure,
+ Func<IMuninServiceBuilder, string, TMuninNodeBuilder> createBuilder
+ )
+ where TMuninNodeService : class, IMuninNode
+ where TMuninNodeImplementation : class, TMuninNodeService
+ where TMuninNodeOptions : MuninNodeOptions, new()
+ where TMuninNodeBuilder : MuninNodeBuilder
{
if (builder is null)
throw new ArgumentNullException(nameof(builder));
if (configure is null)
throw new ArgumentNullException(nameof(configure));
+ if (createBuilder is null)
+ throw new ArgumentNullException(nameof(createBuilder));
- var options = new MuninNodeOptions();
+ var configuredOptions = new TMuninNodeOptions();
- configure(options);
+ configure(configuredOptions);
- var nodeBuilder = new DefaultMuninNodeBuilder(
- serviceBuilder: builder,
- serviceKey: options.HostName // use configured hostname as a service key and option name
+ var nodeBuilder = createBuilder(
+ /* serviceBuilder: */ builder,
+ /* serviceKey: */ configuredOptions.HostName // use configured hostname as a service key and option name
);
- _ = builder.Services.Configure<MuninNodeOptions>(
+ _ = builder.Services.Configure<TMuninNodeOptions>(
name: nodeBuilder.ServiceKey, // configure MuninNodeOptions for this builder
- opts => {
- opts.Address = options.Address;
- opts.Port = options.Port;
- opts.HostName = options.HostName;
- opts.AccessRule = options.AccessRule;
- }
+ options => options.Configure(configuredOptions)
);
builder.Services.Add(
- ServiceDescriptor.KeyedSingleton<IMuninNodeBuilder>(
+ ServiceDescriptor.KeyedSingleton<TMuninNodeBuilder>(
serviceKey: nodeBuilder.ServiceKey,
implementationFactory: (_, _) => nodeBuilder
)
@@ -70,19 +232,23 @@ public static class IMuninServiceBuilderExtensions {
// add keyed/singleton IMuninNode
builder.Services.Add(
- ServiceDescriptor.KeyedSingleton<IMuninNode>(
+ ServiceDescriptor.KeyedSingleton<TMuninNodeService, TMuninNodeImplementation>(
serviceKey: nodeBuilder.ServiceKey,
static (serviceProvider, serviceKey)
- => serviceProvider.GetRequiredKeyedService<IMuninNodeBuilder>(serviceKey).Build(serviceProvider)
+ => serviceProvider
+ .GetRequiredKeyedService<TMuninNodeBuilder>(serviceKey)
+ .Build<TMuninNodeImplementation>(serviceProvider)
)
);
// add keyless/multiple IMuninNode
+#pragma warning disable IDE0200
builder.Services.Add(
- ServiceDescriptor.Transient<IMuninNode>(
- nodeBuilder.Build
+ ServiceDescriptor.Transient<TMuninNodeService, TMuninNodeImplementation>(
+ serviceProvider => nodeBuilder.Build<TMuninNodeImplementation>(serviceProvider)
)
);
+#pragma warning restore IDE0200
return nodeBuilder;
}
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/DefaultMuninNodeBuilder.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilder.cs
similarity index 56%
rename from src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/DefaultMuninNodeBuilder.cs
rename to src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilder.cs
index 9b43d69..b7505a0 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/DefaultMuninNodeBuilder.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilder.cs
@@ -14,22 +14,39 @@ using Smdn.Net.MuninPlugin;
namespace Smdn.Net.MuninNode.DependencyInjection;
-internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
+/// <summary>
+/// Provides builder pattern for configuring and building the <c>Munin-Node</c>.
+/// </summary>
+/// <seealso cref="MuninNodeBuilderExtensions"/>
+#pragma warning disable CS0618 // TODO: remove IMuninNodeBuilder
+public class MuninNodeBuilder : IMuninNodeBuilder {
+#pragma warning restore CS0618
private readonly List<Func<IServiceProvider, IPlugin>> pluginFactories = new(capacity: 4);
private Func<IServiceProvider, IPluginProvider>? buildPluginProvider;
private Func<IServiceProvider, INodeSessionCallback>? buildSessionCallback;
private Func<IServiceProvider, IMuninNodeListenerFactory>? buildListenerFactory;
+ /// <summary>
+ /// Gets the <see cref="IServiceCollection"/> where the <c>Munin-Node</c> services are configured.
+ /// </summary>
public IServiceCollection Services { get; }
+
+ /// <summary>
+ /// Gets the <see cref="string"/> key of <c>Munin-Node</c> service.
+ /// </summary>
+ /// <remarks>
+ /// The value set as the hostname of the <c>Munin-Node</c> (see <see cref="MuninNodeOptions.HostName"/>) is used as the service key.
+ /// </remarks>
+ /// <see cref="IMuninServiceBuilderExtensions.AddNode(IMuninServiceBuilder, Action{MuninNodeOptions})"/>
public string ServiceKey { get; }
- public DefaultMuninNodeBuilder(IMuninServiceBuilder serviceBuilder, string serviceKey)
+ protected internal MuninNodeBuilder(IMuninServiceBuilder serviceBuilder, string serviceKey)
{
Services = (serviceBuilder ?? throw new ArgumentNullException(nameof(serviceBuilder))).Services;
ServiceKey = serviceKey ?? throw new ArgumentNullException(nameof(serviceKey));
}
- public void AddPluginFactory(Func<IServiceProvider, IPlugin> buildPlugin)
+ internal void AddPluginFactory(Func<IServiceProvider, IPlugin> buildPlugin)
{
if (buildPlugin is null)
throw new ArgumentNullException(nameof(buildPlugin));
@@ -37,7 +54,7 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
pluginFactories.Add(serviceProvider => buildPlugin(serviceProvider));
}
- public void SetPluginProviderFactory(
+ internal void SetPluginProviderFactory(
Func<IServiceProvider, IPluginProvider> buildPluginProvider
)
{
@@ -47,7 +64,7 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
this.buildPluginProvider = buildPluginProvider;
}
- public void SetSessionCallbackFactory(
+ internal void SetSessionCallbackFactory(
Func<IServiceProvider, INodeSessionCallback> buildSessionCallback
)
{
@@ -57,7 +74,7 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
this.buildSessionCallback = buildSessionCallback;
}
- public void SetListenerFactory(
+ internal void SetListenerFactory(
Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory
)
{
@@ -67,13 +84,19 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
this.buildListenerFactory = buildListenerFactory;
}
+ /// <summary>
+ /// Builds the <c>Munin-Node</c> with current configurations.
+ /// </summary>
+ /// <param name="serviceProvider">
+ /// An <see cref="IServiceProvider"/> that provides the services to be used by the <see cref="IMuninNode"/> being built.
+ /// </param>
+ /// <returns>An initialized <see cref="IMuninNode"/>.</returns>
public IMuninNode Build(IServiceProvider serviceProvider)
{
if (serviceProvider is null)
throw new ArgumentNullException(nameof(serviceProvider));
- return new DefaultMuninNode(
- options: serviceProvider.GetRequiredService<IOptionsMonitor<MuninNodeOptions>>().Get(name: ServiceKey),
+ return Build(
pluginProvider: buildPluginProvider is null
? new PluginProvider(
plugins: pluginFactories.Select(factory => factory(serviceProvider)).ToList(),
@@ -81,7 +104,7 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
)
: buildPluginProvider.Invoke(serviceProvider),
listenerFactory: buildListenerFactory?.Invoke(serviceProvider),
- logger: serviceProvider.GetService<ILoggerFactory>()?.CreateLogger<DefaultMuninNode>()
+ serviceProvider: serviceProvider
);
}
@@ -98,4 +121,32 @@ internal sealed class DefaultMuninNodeBuilder : IMuninNodeBuilder {
SessionCallback = sessionCallback;
}
}
+
+ protected virtual IMuninNode Build(
+ IPluginProvider pluginProvider,
+ IMuninNodeListenerFactory? listenerFactory,
+ IServiceProvider serviceProvider
+ )
+ {
+ if (serviceProvider is null)
+ throw new ArgumentNullException(nameof(serviceProvider));
+
+ return new DefaultMuninNode(
+ options: GetConfiguredOptions<MuninNodeOptions>(serviceProvider),
+ pluginProvider: pluginProvider,
+ listenerFactory: listenerFactory,
+ logger: serviceProvider.GetService<ILoggerFactory>()?.CreateLogger<DefaultMuninNode>()
+ );
+ }
+
+ protected TMuninNodeOptions GetConfiguredOptions<TMuninNodeOptions>(IServiceProvider serviceProvider)
+ where TMuninNodeOptions : MuninNodeOptions
+ {
+ if (serviceProvider is null)
+ throw new ArgumentNullException(nameof(serviceProvider));
+
+ return serviceProvider
+ .GetRequiredService<IOptionsMonitor<TMuninNodeOptions>>()
+ .Get(name: ServiceKey);
+ }
}
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilderExtensions.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilderExtensions.cs
new file mode 100644
index 0000000..f500ae1
--- /dev/null
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.DependencyInjection/MuninNodeBuilderExtensions.cs
@@ -0,0 +1,258 @@
+// SPDX-FileCopyrightText: 2025 smdn <smdn@smdn.jp>
+// SPDX-License-Identifier: MIT
+
+using System;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Smdn.Net.MuninNode.Transport;
+using Smdn.Net.MuninPlugin;
+
+namespace Smdn.Net.MuninNode.DependencyInjection;
+
+public static class MuninNodeBuilderExtensions {
+#pragma warning disable CS0419
+ /// <remarks>
+ /// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
+ /// </remarks>
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ IPlugin plugin
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (plugin is null)
+ throw new ArgumentNullException(nameof(plugin));
+
+ return AddPlugin(
+ builder: builder,
+ buildPlugin: _ => plugin
+ );
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
+ /// </remarks>
+ public static TMuninNodeBuilder AddPlugin<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<IServiceProvider, IPlugin> buildPlugin
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (buildPlugin is null)
+ throw new ArgumentNullException(nameof(buildPlugin));
+
+ builder.AddPluginFactory(buildPlugin);
+
+ return builder;
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// Calling this method will override the configurations made by
+ /// <see cref="AddPlugin"/> and <see cref="UseSessionCallback"/>.
+ /// </remarks>
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ IPluginProvider pluginProvider
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (pluginProvider is null)
+ throw new ArgumentNullException(nameof(pluginProvider));
+
+ return UsePluginProvider(
+ builder: builder,
+ buildPluginProvider: _ => pluginProvider
+ );
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// Calling this method will override the configurations made by
+ /// <see cref="AddPlugin"/> and <see cref="UseSessionCallback"/>.
+ /// </remarks>
+ public static TMuninNodeBuilder UsePluginProvider<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<IServiceProvider, IPluginProvider> buildPluginProvider
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (buildPluginProvider is null)
+ throw new ArgumentNullException(nameof(buildPluginProvider));
+
+ builder.SetPluginProviderFactory(buildPluginProvider);
+
+ return builder;
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
+ /// </remarks>
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ INodeSessionCallback sessionCallback
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (sessionCallback is null)
+ throw new ArgumentNullException(nameof(sessionCallback));
+
+ return UseSessionCallback(
+ builder: builder,
+ buildSessionCallback: _ => sessionCallback
+ );
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
+ /// </remarks>
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc,
+ Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ => UseSessionCallback(
+ builder: builder,
+ buildSessionCallback: _ => new SessionCallbackFuncWrapper(
+ reportSessionStartedAsyncFunc,
+ reportSessionClosedAsyncFunc
+ )
+ );
+
+ private sealed class SessionCallbackFuncWrapper(
+ Func<string, CancellationToken, ValueTask>? reportSessionStartedAsyncFunc,
+ Func<string, CancellationToken, ValueTask>? reportSessionClosedAsyncFunc
+ ) : INodeSessionCallback {
+ public ValueTask ReportSessionStartedAsync(string sessionId, CancellationToken cancellationToken)
+ => reportSessionStartedAsyncFunc is null
+ ? default
+ : reportSessionStartedAsyncFunc(sessionId, cancellationToken);
+
+ public ValueTask ReportSessionClosedAsync(string sessionId, CancellationToken cancellationToken)
+ => reportSessionClosedAsyncFunc is null
+ ? default
+ : reportSessionClosedAsyncFunc(sessionId, cancellationToken);
+ }
+
+#pragma warning disable CS0419
+ /// <remarks>
+ /// If <see cref="UsePluginProvider"/> is called, the configurations made by this method will be overridden.
+ /// </remarks>
+ public static TMuninNodeBuilder UseSessionCallback<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<IServiceProvider, INodeSessionCallback> buildSessionCallback
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+#pragma warning restore CS0419
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (buildSessionCallback is null)
+ throw new ArgumentNullException(nameof(buildSessionCallback));
+
+ builder.SetSessionCallbackFactory(buildSessionCallback);
+
+ return builder;
+ }
+
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ IMuninNodeListenerFactory listenerFactory
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (listenerFactory is null)
+ throw new ArgumentNullException(nameof(listenerFactory));
+
+ return UseListenerFactory(
+ builder: builder,
+ buildListenerFactory: _ => listenerFactory
+ );
+ }
+
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (createListenerAsyncFunc is null)
+ throw new ArgumentNullException(nameof(createListenerAsyncFunc));
+
+ return UseListenerFactory(
+ builder: builder,
+ buildListenerFactory: serviceProvider => new CreateListenerAsyncFuncWrapper(
+ serviceProvider,
+ createListenerAsyncFunc
+ )
+ );
+ }
+
+ private sealed class CreateListenerAsyncFuncWrapper(
+ IServiceProvider serviceProvider,
+ Func<IServiceProvider, EndPoint, IMuninNode, CancellationToken, ValueTask<IMuninNodeListener>> createListenerAsyncFunc
+ ) : IMuninNodeListenerFactory {
+ public ValueTask<IMuninNodeListener> CreateAsync(EndPoint endPoint, IMuninNode node, CancellationToken cancellationToken)
+ => createListenerAsyncFunc(serviceProvider, endPoint, node, cancellationToken);
+ }
+
+ public static TMuninNodeBuilder UseListenerFactory<TMuninNodeBuilder>(
+ this TMuninNodeBuilder builder,
+ Func<IServiceProvider, IMuninNodeListenerFactory> buildListenerFactory
+ )
+ where TMuninNodeBuilder : MuninNodeBuilder
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (buildListenerFactory is null)
+ throw new ArgumentNullException(nameof(buildListenerFactory));
+
+ builder.SetListenerFactory(buildListenerFactory);
+
+ return builder;
+ }
+
+ public static TMuninNode Build<TMuninNode>(
+ this MuninNodeBuilder builder,
+ IServiceProvider serviceProvider
+ ) where TMuninNode : IMuninNode
+ {
+ if (builder is null)
+ throw new ArgumentNullException(nameof(builder));
+ if (serviceProvider is null)
+ throw new ArgumentNullException(nameof(serviceProvider));
+
+ var n = builder.Build(serviceProvider);
+
+ if (n is not TMuninNode node)
+ throw new InvalidOperationException($"The type '{n.GetType()}' of the constructed instance did not match the requested type '{typeof(TMuninNode)}'.");
+
+ return node;
+ }
+}
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.csproj b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.csproj
index 6dd4084..dc0365e 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.csproj
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode.csproj
@@ -5,7 +5,7 @@ SPDX-License-Identifier: MIT
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net8.0</TargetFrameworks>
- <VersionPrefix>2.4.0</VersionPrefix>
+ <VersionPrefix>2.5.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<PackageValidationBaselineVersion>2.0.0</PackageValidationBaselineVersion>
<RootNamespace/> <!-- empty the root namespace so that the namespace is determined only by the directory name, for code style rule IDE0130 -->
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/MuninNodeOptions.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/MuninNodeOptions.cs
index 2b4a062..3a77f2b 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/MuninNodeOptions.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/MuninNodeOptions.cs
@@ -14,7 +14,7 @@ namespace Smdn.Net.MuninNode;
/// Options to configure the <c>Munin-Node</c>.
/// </summary>
/// <see cref="DependencyInjection.IMuninServiceBuilderExtensions.AddNode(DependencyInjection.IMuninServiceBuilder, Action{MuninNodeOptions})"/>
-public sealed class MuninNodeOptions {
+public class MuninNodeOptions {
private static IPAddress LoopbackAddress => Socket.OSSupportsIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback;
private static IPAddress AnyAddress => Socket.OSSupportsIPv6 ? IPAddress.IPv6Any : IPAddress.Any;
@@ -124,6 +124,17 @@ public sealed class MuninNodeOptions {
=> (MuninNodeOptions)MemberwiseClone();
#endif
+ protected internal virtual void Configure(MuninNodeOptions baseOptions)
+ {
+ if (baseOptions is null)
+ throw new ArgumentNullException(nameof(baseOptions));
+
+ Address = baseOptions.Address;
+ Port = baseOptions.Port;
+ HostName = baseOptions.HostName;
+ AccessRule = baseOptions.AccessRule;
+ }
+
/// <summary>
/// Set the value of the <see cref="Address"/> property to use the address of
/// <see cref="IPAddress.Any"/> or <see cref="IPAddress.IPv6Any"/>.
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/NodeBase.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/NodeBase.cs
index d8dd80c..57cc104 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/NodeBase.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninNode/NodeBase.cs
@@ -228,6 +228,10 @@ public abstract partial class NodeBase : IMuninNode, IMuninNodeProfile, IDisposa
if (Logger is not null)
LogStartingNode(Logger, null);
+ await StartingAsync(cancellationToken).ConfigureAwait(false);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
listener = await listenerFactory.CreateAsync(
endPoint: GetLocalEndPointToBind(),
node: this,
@@ -246,13 +250,47 @@ public abstract partial class NodeBase : IMuninNode, IMuninNodeProfile, IDisposa
cancellationToken: cancellationToken
).ConfigureAwait(false);
+ sessionCountdownEvent.Reset();
+
+ await StartedAsync(cancellationToken).ConfigureAwait(false);
+
if (Logger is not null)
LogStartedNode(Logger, HostName, listener.EndPoint, null);
-
- sessionCountdownEvent.Reset();
}
}
+ /// <summary>
+ /// Provides an extension point for starting the <c>Munin-Node</c> instance.
+ /// If overridden in a derived class, it is invoked before the <c>Munin-Node</c> is started
+ /// by a call to the <see cref="StartAsync"/> method.
+ /// </summary>
+ /// <param name="cancellationToken">
+ /// The <see cref="CancellationToken"/> to monitor for cancellation requests.
+ /// </param>
+ /// <returns>
+ /// The <see cref="ValueTask"/> that represents the asynchronous operation.
+ /// </returns>
+ /// <seealso cref="StartAsync"/>
+ /// <seealso cref="StartedAsync"/>
+ protected virtual ValueTask StartingAsync(CancellationToken cancellationToken)
+ => default; // nothing to do in this class
+
+ /// <summary>
+ /// Provides an extension point for starting the <c>Munin-Node</c> instance.
+ /// If overridden in a derived class, it is invoked after the <c>Munin-Node</c> is started
+ /// by a call to the <see cref="StartAsync"/> method.
+ /// </summary>
+ /// <param name="cancellationToken">
+ /// The <see cref="CancellationToken"/> to monitor for cancellation requests.
+ /// </param>
+ /// <returns>
+ /// The <see cref="ValueTask"/> that represents the asynchronous operation.
+ /// </returns>
+ /// <seealso cref="StartAsync"/>
+ /// <seealso cref="StartingAsync"/>
+ protected virtual ValueTask StartedAsync(CancellationToken cancellationToken)
+ => default; // nothing to do in this class
+
/// <summary>
/// Stops accepting connections from clients at the <c>Munin-Node</c> currently running.
/// </summary>
@@ -277,9 +315,15 @@ public abstract partial class NodeBase : IMuninNode, IMuninNodeProfile, IDisposa
async ValueTask StopAsyncCore()
{
+ cancellationToken.ThrowIfCancellationRequested();
+
if (Logger is not null)
LogStoppingNode(Logger, HostName, null);
+ await StoppingAsync(cancellationToken).ConfigureAwait(false);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
// decrement by the initial value of 1 (re)set in Start()/StartAsync()
sessionCountdownEvent.Signal();
@@ -307,11 +351,45 @@ public abstract partial class NodeBase : IMuninNode, IMuninNodeProfile, IDisposa
protocolHandler = null;
}
+ await StoppedAsync(cancellationToken).ConfigureAwait(false);
+
if (Logger is not null)
LogStoppedNode(Logger, HostName, null);
}
}
+ /// <summary>
+ /// Provides an extension point for stopping the <c>Munin-Node</c> instance.
+ /// If overridden in a derived class, it is invoked before the <c>Munin-Node</c> is stopped
+ /// by a call to the <see cref="StopAsync"/> method.
+ /// </summary>
+ /// <param name="cancellationToken">
+ /// The <see cref="CancellationToken"/> to monitor for cancellation requests.
+ /// </param>
+ /// <returns>
+ /// The <see cref="ValueTask"/> that represents the asynchronous operation.
+ /// </returns>
+ /// <seealso cref="StopAsync"/>
+ /// <seealso cref="StoppedAsync"/>
+ protected virtual ValueTask StoppingAsync(CancellationToken cancellationToken)
+ => default; // nothing to do in this class
+
+ /// <summary>
+ /// Provides an extension point for stopping the <c>Munin-Node</c> instance.
+ /// If overridden in a derived class, it is invoked after the <c>Munin-Node</c> is stopped
+ /// by a call to the <see cref="StopAsync"/> method.
+ /// </summary>
+ /// <param name="cancellationToken">
+ /// The <see cref="CancellationToken"/> to monitor for cancellation requests.
+ /// </param>
+ /// <returns>
+ /// The <see cref="ValueTask"/> that represents the asynchronous operation.
+ /// </returns>
+ /// <seealso cref="StopAsync"/>
+ /// <seealso cref="StoppingAsync"/>
+ protected virtual ValueTask StoppedAsync(CancellationToken cancellationToken)
+ => default; // nothing to do in this class
+
/// <inheritdoc cref="IMuninNode.RunAsync(CancellationToken)"/>
/// <seealso cref="IMuninNode.RunAsync(CancellationToken)"/>
/// <seealso cref="StartAsync(CancellationToken)"/>
diff --git a/src/Smdn.Net.MuninNode/Smdn.Net.MuninPlugin/PluginGraphAttributesBuilder.cs b/src/Smdn.Net.MuninNode/Smdn.Net.MuninPlugin/PluginGraphAttributesBuilder.cs
index fc69ec9..deaf417 100644
--- a/src/Smdn.Net.MuninNode/Smdn.Net.MuninPlugin/PluginGraphAttributesBuilder.cs
+++ b/src/Smdn.Net.MuninNode/Smdn.Net.MuninPlugin/PluginGraphAttributesBuilder.cs
@@ -2,6 +2,9 @@
// SPDX-License-Identifier: MIT
using System;
using System.Collections.Generic;
+#if SYSTEM_DIAGNOSTICS_CODEANALYSIS_MEMBERNOTNULLATTRIBUTE
+using System.Diagnostics.CodeAnalysis;
+#endif
using System.Text.RegularExpressions;
namespace Smdn.Net.MuninPlugin;
@@ -42,8 +45,7 @@ public partial class PluginGraphAttributesBuilder {
}
}
- private readonly string title;
-
+ private string title;
private bool? showGraph;
private string? category;
private int? height;
@@ -106,14 +108,14 @@ public partial class PluginGraphAttributesBuilder {
/// <paramref name="title"/> contains invalid characters.
/// </exception>
/// <seealso href="https://guide.munin-monitoring.org/en/latest/reference/plugin.html#graph-title">Plugin reference - Global attributes - graph_title</seealso>
+#if !SYSTEM_DIAGNOSTICS_CODEANALYSIS_MEMBERNOTNULLATTRIBUTE
+#pragma warning disable CS8618
+#endif
public PluginGraphAttributesBuilder(string title)
{
- ArgumentExceptionShim.ThrowIfNullOrWhiteSpace(title, nameof(title));
-
- ThrowIfNotMatch(RegexTitle, title, nameof(title), "graph_title");
-
- this.title = title;
+ WithTitle(title);
}
+#pragma warning restore CS8618
/// <summary>Sets a value for the <c>graph</c> to <c>yes</c>.</summary>
/// <seealso href="https://guide.munin-monitoring.org/en/latest/reference/plugin.html#graph">Plugin reference - Global attributes - graph</seealso>
@@ -231,6 +233,27 @@ public partial class PluginGraphAttributesBuilder {
return this;
}
+ /// <summary>Overwrites a value for the <c>graph_title</c>.</summary>
+ /// <seealso href="https://guide.munin-monitoring.org/en/latest/reference/plugin.html#graph-title">Plugin reference - Global attributes - graph_title</seealso>
+ /// <exception cref="ArgumentNullException"><paramref name="title"/> is <see langword="null"/>.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="title"/> is empty, or
+ /// <paramref name="title"/> contains invalid characters.
+ /// </exception>
+#if SYSTEM_DIAGNOSTICS_CODEANALYSIS_MEMBERNOTNULLATTRIBUTE
+ [MemberNotNull(nameof(title))]
+#endif
+ public PluginGraphAttributesBuilder WithTitle(string title)
+ {
+ ArgumentExceptionShim.ThrowIfNullOrWhiteSpace(title, nameof(title));
+
+ ThrowIfNotMatch(RegexTitle, title, nameof(title), "graph_title");
+
+ this.title = title;
+
+ return this;
+ }
+
/// <summary>Sets a value for the <c>graph_total</c>.</summary>
/// <seealso href="https://guide.munin-monitoring.org/en/latest/reference/plugin.html#graph-total">Plugin reference - Global attributes - graph_total</seealso>
/// <exception cref="ArgumentNullException"><paramref name="labelForTotal"/> is <see langword="null"/>.</exception>
Notes
What's Changed
Notable changes
Full Changelog: releases/Smdn.Net.MuninNode-2.4.0...releases/Smdn.Net.MuninNode-2.5.0