Skip to content

Add Serialization & Deserialization of Sink File Properties with CLI Commands #2749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.411",
"version": "8.0.117",
"rollForward": "latestFeature"
}
}
34 changes: 34 additions & 0 deletions schemas/dab.draft.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,40 @@
},
"required": ["endpoint"]
},
"file": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable/disable file sink telemetry logging.",
"default": false
},
"path": {
"type": "string",
"description": "File path for telemetry logs.",
"default": "/logs/dab-log.txt"
},
"rolling-interval": {
"type": "string",
"description": "Rolling interval for log files.",
"default": "day",
"enum": ["hour", "day", "week"]
},
"retained-file-count-limit": {
"type": "integer",
"description": "Maximum number of retained log files.",
"default": 1,
"minimum": 1
},
"file-size-limit-bytes": {
"type": "integer",
"description": "Maximum file size in bytes before rolling.",
"default": 1048576,
"minimum": 1
}
}
},
"log-level": {
"type": "object",
"description": "Global configuration of log level, defines logging severity levels for specific classes, when 'null' it will set logging level based on 'host: mode' property",
Expand Down
215 changes: 215 additions & 0 deletions src/Cli.Tests/ConfigureOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -819,5 +819,220 @@ private void SetupFileSystemWithInitialConfig(string jsonConfig)
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(jsonConfig, out RuntimeConfig? config));
Assert.IsNotNull(config.Runtime);
}

/// <summary>
/// Tests that running "dab configure --runtime.telemetry.file.enabled" on a config with various values results
/// in runtime config update. Takes in updated value for telemetry file enabled and
/// validates whether the runtime config reflects those updated values
/// </summary>
[DataTestMethod]
[DataRow(true, DisplayName = "Enable file sink telemetry.")]
[DataRow(false, DisplayName = "Disable file sink telemetry.")]
public void TestUpdateTelemetryFileEnabled(bool updatedEnabledValue)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update file enabled flag
ConfigureOptions options = new(
runtimeTelemetryFileEnabled: updatedEnabledValue,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate the Enabled Flag is updated
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));
Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File?.Enabled);
Assert.AreEqual(updatedEnabledValue, runtimeConfig.Runtime.Telemetry.File.Enabled);
}

/// <summary>
/// Tests that running "dab configure --runtime.telemetry.file.path" on a config with various values results
/// in runtime config update. Takes in updated value for telemetry file path and
/// validates whether the runtime config reflects those updated values
/// </summary>
[DataTestMethod]
[DataRow("/logs/custom-dab.log", DisplayName = "Update file path to custom location.")]
[DataRow("/var/log/dab-application.log", DisplayName = "Update file path to var log directory.")]
[DataRow("./logs/dab.log", DisplayName = "Update file path to relative location.")]
public void TestUpdateTelemetryFilePath(string updatedPathValue)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update file path value
ConfigureOptions options = new(
runtimeTelemetryFilePath: updatedPathValue,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate the Path is updated
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));
Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File?.Path);
Assert.AreEqual(updatedPathValue, runtimeConfig.Runtime.Telemetry.File.Path);
}

/// <summary>
/// Tests that running "dab configure --runtime.telemetry.file.rolling-interval" on a config with various values results
/// in runtime config update. Takes in updated value for telemetry file rolling interval and
/// validates whether the runtime config reflects those updated values
/// </summary>
[DataTestMethod]
[DataRow(RollingInterval.Hour, DisplayName = "Update rolling interval to Hour.")]
[DataRow(RollingInterval.Day, DisplayName = "Update rolling interval to Day.")]
[DataRow(RollingInterval.Week, DisplayName = "Update rolling interval to Week.")]
public void TestUpdateTelemetryFileRollingInterval(RollingInterval updatedRollingIntervalValue)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update rolling interval value
ConfigureOptions options = new(
runtimeTelemetryFileRollingInterval: updatedRollingIntervalValue,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate the Rolling Interval is updated
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));
Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File?.RollingInterval);
Assert.AreEqual(updatedRollingIntervalValue, runtimeConfig.Runtime.Telemetry.File.RollingInterval);
}

/// <summary>
/// Tests that running "dab configure --runtime.telemetry.file.retained-file-count-limit" on a config with various values results
/// in runtime config update. Takes in updated value for retained file count limit and
/// validates whether the runtime config reflects those updated values
/// </summary>
[DataTestMethod]
[DataRow(1, DisplayName = "Update retained file count limit to 1.")]
[DataRow(7, DisplayName = "Update retained file count limit to 7.")]
[DataRow(30, DisplayName = "Update retained file count limit to 30.")]
public void TestUpdateTelemetryFileRetainedFileCountLimit(int updatedRetainedFileCountLimitValue)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update retained file count limit value
ConfigureOptions options = new(
runtimeTelemetryFileRetainedFileCountLimit: updatedRetainedFileCountLimitValue,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate the Retained File Count Limit is updated
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));
Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File?.RetainedFileCountLimit);
Assert.AreEqual(updatedRetainedFileCountLimitValue, runtimeConfig.Runtime.Telemetry.File.RetainedFileCountLimit);
}

/// <summary>
/// Tests that running "dab configure --runtime.telemetry.file.file-size-limit-bytes" on a config with various values results
/// in runtime config update. Takes in updated value for file size limit bytes and
/// validates whether the runtime config reflects those updated values
/// </summary>
[DataTestMethod]
[DataRow(1048576, DisplayName = "Update file size limit to 1MB.")]
[DataRow(10485760, DisplayName = "Update file size limit to 10MB.")]
[DataRow(104857600, DisplayName = "Update file size limit to 100MB.")]
public void TestUpdateTelemetryFileFileSizeLimitBytes(int updatedFileSizeLimitBytesValue)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update file size limit bytes value
ConfigureOptions options = new(
runtimeTelemetryFileFileSizeLimitBytes: updatedFileSizeLimitBytesValue,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate the File Size Limit Bytes is updated
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));
Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File?.FileSizeLimitBytes);
Assert.AreEqual(updatedFileSizeLimitBytesValue, runtimeConfig.Runtime.Telemetry.File.FileSizeLimitBytes);
}

/// <summary>
/// Tests that validation fails when invalid values are provided for retained file count limit and file size limit
/// </summary>
[DataTestMethod]
[DataRow(0, "retained-file-count-limit", DisplayName = "Fail when retained file count limit is 0.")]
[DataRow(-1, "retained-file-count-limit", DisplayName = "Fail when retained file count limit is negative.")]
[DataRow(0, "file-size-limit-bytes", DisplayName = "Fail when file size limit is 0.")]
[DataRow(-1, "file-size-limit-bytes", DisplayName = "Fail when file size limit is negative.")]
public void TestTelemetryFileConfigurationValidationFailures(int invalidValue, string optionType)
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

ConfigureOptions options;
if (optionType == "retained-file-count-limit")
{
options = new ConfigureOptions(
runtimeTelemetryFileRetainedFileCountLimit: invalidValue,
config: TEST_RUNTIME_CONFIG_FILE
);
}
else
{
options = new ConfigureOptions(
runtimeTelemetryFileFileSizeLimitBytes: invalidValue,
config: TEST_RUNTIME_CONFIG_FILE
);
}

// Act: Attempts to update with invalid value
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate that configuration fails
Assert.IsFalse(isSuccess);
}

/// <summary>
/// Tests that multiple file sink telemetry options can be configured in a single command
/// </summary>
[TestMethod]
public void TestUpdateMultipleTelemetryFileOptions()
{
// Arrange -> all the setup which includes creating options.
SetupFileSystemWithInitialConfig(INITIAL_CONFIG);

// Act: Attempts to update multiple file options at once
ConfigureOptions options = new(
runtimeTelemetryFileEnabled: true,
runtimeTelemetryFilePath: "/var/log/custom-dab.log",
runtimeTelemetryFileRollingInterval: RollingInterval.Week,
runtimeTelemetryFileRetainedFileCountLimit: 14,
runtimeTelemetryFileFileSizeLimitBytes: 52428800,
config: TEST_RUNTIME_CONFIG_FILE
);
bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);

// Assert: Validate all options are updated correctly
Assert.IsTrue(isSuccess);
string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? runtimeConfig));

Assert.IsNotNull(runtimeConfig.Runtime?.Telemetry?.File);
var fileOptions = runtimeConfig.Runtime.Telemetry.File;

Assert.AreEqual(true, fileOptions.Enabled);
Assert.AreEqual("/var/log/custom-dab.log", fileOptions.Path);
Assert.AreEqual(RollingInterval.Week, fileOptions.RollingInterval);
Assert.AreEqual(14, fileOptions.RetainedFileCountLimit);
Assert.AreEqual(52428800, fileOptions.FileSizeLimitBytes);
}
}
}
26 changes: 26 additions & 0 deletions src/Cli/Commands/ConfigureOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public ConfigureOptions(
string? runtimeHostAuthenticationProvider = null,
string? runtimeHostAuthenticationJwtAudience = null,
string? runtimeHostAuthenticationJwtIssuer = null,
bool? runtimeTelemetryFileEnabled = null,
string? runtimeTelemetryFilePath = null,
RollingInterval? runtimeTelemetryFileRollingInterval = null,
int? runtimeTelemetryFileRetainedFileCountLimit = null,
int? runtimeTelemetryFileFileSizeLimitBytes = null,
string? config = null)
: base(config)
{
Expand Down Expand Up @@ -72,6 +77,12 @@ public ConfigureOptions(
RuntimeHostAuthenticationProvider = runtimeHostAuthenticationProvider;
RuntimeHostAuthenticationJwtAudience = runtimeHostAuthenticationJwtAudience;
RuntimeHostAuthenticationJwtIssuer = runtimeHostAuthenticationJwtIssuer;
// File Sink Telemetry
RuntimeTelemetryFileEnabled = runtimeTelemetryFileEnabled;
RuntimeTelemetryFilePath = runtimeTelemetryFilePath;
RuntimeTelemetryFileRollingInterval = runtimeTelemetryFileRollingInterval;
RuntimeTelemetryFileRetainedFileCountLimit = runtimeTelemetryFileRetainedFileCountLimit;
RuntimeTelemetryFileFileSizeLimitBytes = runtimeTelemetryFileFileSizeLimitBytes;
}

[Option("data-source.database-type", Required = false, HelpText = "Database type. Allowed values: MSSQL, PostgreSQL, CosmosDB_NoSQL, MySQL.")]
Expand Down Expand Up @@ -140,6 +151,21 @@ public ConfigureOptions(
[Option("runtime.host.authentication.jwt.issuer", Required = false, HelpText = "Configure the entity that issued the Jwt Token.")]
public string? RuntimeHostAuthenticationJwtIssuer { get; }

[Option("runtime.telemetry.file.enabled", Required = false, HelpText = "Enable/disable file sink telemetry logging. Default: false (boolean).")]
public bool? RuntimeTelemetryFileEnabled { get; }

[Option("runtime.telemetry.file.path", Required = false, HelpText = "File path for telemetry logs. Default: '/logs/dab-log.txt' (string).")]
public string? RuntimeTelemetryFilePath { get; }

[Option("runtime.telemetry.file.rolling-interval", Required = false, HelpText = "Rolling interval for log files. Default: Day. Allowed values: Hour, Day, Week.")]
public RollingInterval? RuntimeTelemetryFileRollingInterval { get; }

[Option("runtime.telemetry.file.retained-file-count-limit", Required = false, HelpText = "Maximum number of retained log files. Default: 1 (integer, minimum: 1).")]
public int? RuntimeTelemetryFileRetainedFileCountLimit { get; }

[Option("runtime.telemetry.file.file-size-limit-bytes", Required = false, HelpText = "Maximum file size in bytes before rolling. Default: 1048576 (integer, minimum: 1).")]
public int? RuntimeTelemetryFileFileSizeLimitBytes { get; }

public int Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem)
{
logger.LogInformation("{productName} {version}", PRODUCT_NAME, ProductInfo.GetProductVersion());
Expand Down
Loading
Loading