Skip to content

Commit

Permalink
fix: bandit attributes, logs, and baseUrl in dotnet SDK relay (#85)
Browse files Browse the repository at this point in the history
* Return assignment and bandit logs in test responses
* rename json test response method
* use latest SDK package, update Program hosts
* use Base URL instead of host/port
* handle input attributes without losing kind (numeric/categorical)
  • Loading branch information
typotter authored Dec 5, 2024
1 parent 7d92105 commit 7a62c9f
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@

internal class AssignmentLogger : IAssignmentLogger
{
public static AssignmentLogger Instance = new();

public Queue<AssignmentLogData> AssignmentLogs = new();
public Queue<BanditLogEvent> BanditLogs = new();

public void LogAssignment(AssignmentLogData assignmentLogData)
{
Console.WriteLine("Assignment Log");
Console.WriteLine(assignmentLogData);
AssignmentLogs.Enqueue(assignmentLogData);
}

public void LogBanditAction(BanditLogEvent banditLogEvent)
{
Console.WriteLine("Bandit Action Log");
Console.WriteLine(banditLogEvent);
BanditLogs.Enqueue(banditLogEvent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ public ActionResult<string> Post([FromBody] AssignmentRequest data)
switch (data.AssignmentType)
{
case "STRING":
return JsonResult(eppoClient.GetStringAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultValue.ToString()!));
return JsonTestResponse(eppoClient.GetStringAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultValue.ToString()!));

case "INTEGER":
var intResults = eppoClient.GetIntegerAssignment(data.Flag, data.SubjectKey, convertedAttributes, Convert.ToInt64(defaultValue.ToString()));
return JsonResult(intResults);
return JsonTestResponse(intResults);

case "BOOLEAN":
return JsonResult(eppoClient.GetBooleanAssignment(data.Flag, data.SubjectKey, convertedAttributes, Convert.ToBoolean(defaultValue.ToString())));
return JsonTestResponse(eppoClient.GetBooleanAssignment(data.Flag, data.SubjectKey, convertedAttributes, Convert.ToBoolean(defaultValue.ToString())));

case "NUMERIC":
return JsonResult(eppoClient.GetNumericAssignment(data.Flag, data.SubjectKey, convertedAttributes, Convert.ToDouble(defaultValue.ToString())));
return JsonTestResponse(eppoClient.GetNumericAssignment(data.Flag, data.SubjectKey, convertedAttributes, Convert.ToDouble(defaultValue.ToString())));

case "JSON":
var jString = defaultValue.ToString();
var defaultJson = JObject.Parse(jString);
return JsonResult(eppoClient.GetJsonAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultJson));
return JsonTestResponse(eppoClient.GetJsonAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultJson));
}

return JsonError("Invalid Assignment Type " + data.AssignmentType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public ActionResult<string> Post([FromBody] BanditActionRequest data)
subject,
actions,
defaultVal);
return JsonResult(result);
return JsonTestResponse(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,60 @@
using EppoSDKRelay.DTO;
using System.Text.Json;
using Newtonsoft.Json.Linq;
using eppo_sdk.dto;
using eppo_sdk.dto.bandit;

namespace EppoSDKRelay.controllers;

public class JsonControllerBase : ControllerBase {
public class JsonControllerBase : ControllerBase
{

protected static readonly JsonSerializerOptions SerializeOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};

protected static ActionResult<string> JsonResult(object result)
protected static ActionResult<string> JsonTestResponse(object result)
{
// System.Text.Json does not play nicely with Newtonsoft types
// Since "Objects" implement IEnumerable, System.Text will try to encode
// the json object as an array. :(
if (result is JObject) {
if (result is JObject)
{
result = ((JObject)result).ToObject<Dictionary<string, object>>();
}

var response = new TestResponse
{
Result = result
Result = result,
AssignmentLog = DequeueAllForResponse<AssignmentLogData>(AssignmentLogger.Instance.AssignmentLogs),
BanditLog = DequeueAllForResponse<BanditLogEvent>(AssignmentLogger.Instance.BanditLogs),
};
return JsonSerializer.Serialize(response, SerializeOptions);
}

protected static ActionResult<string> JsonError(String error)
{
return JsonSerializer.Serialize(new TestResponse
{
Error = error
}, SerializeOptions);
}


public static List<object> DequeueAllForResponse<T>(Queue<T> queue)
{
List<object> items = [];

while (queue.Count > 0)
{
var item = queue.Dequeue();
if (item != null)
{
items.Add(item);
}
}

return items;
}
}
13 changes: 3 additions & 10 deletions package-testing/dotnet-sdk-relay/EppoSDKRelay/DTO/AttributeSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@ namespace EppoSDKRelay.DTO;

public class AttributeSet
{
public Dictionary<string, object?> NumericAttributes { get; set; }
public Dictionary<string, object?> CategoricalAttributes { get; set; }

public Dictionary<string, object?> AttributeDictionary
{
get => new Dictionary<string, object?>[] { NumericAttributes, CategoricalAttributes }.SelectMany(dict => dict)
.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public required Dictionary<string, object?> NumericAttributes { get; set; }
public required Dictionary<string, object?> CategoricalAttributes { get; set; }

public Dictionary<string, string?> CategoricalAttributesAsStrings
{
Expand All @@ -23,6 +17,5 @@ public class AttributeSet
public Dictionary<string, object?> NumericAttributesAsNumbers => NumericAttributes
.Where(kvp =>
(kvp.Value is JsonElement jsonElement) && jsonElement.ValueKind == JsonValueKind.Number)
.ToDictionary(kvp => kvp.Key, static kvp => (object?)((JsonElement)kvp.Value).GetDouble());

.ToDictionary(kvp => kvp.Key, static kvp => kvp.Value == null ? null : (object?)((JsonElement)kvp.Value).GetDouble());
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public ContextAttributes GetSubjectContext()
public IDictionary<string, ContextAttributes> GetActionContextDict()
{
return Actions.ToDictionary(action => action.ActionKey,
action => ContextAttributes.FromDict(action.ActionKey, Values.ConvertJsonValuesToPrimitives(action.AttributeDictionary)));
action => ContextAttributes.FromNullableAttributes(action.ActionKey, Values.ConvertJsonValuesToPrimitives(action.CategoricalAttributes), Values.ConvertJsonValuesToPrimitives(action.NumericAttributes)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Eppo.Sdk" Version="3.4.0" />
<PackageReference Include="Eppo.Sdk" Version="3.5.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
Expand Down
3 changes: 3 additions & 0 deletions package-testing/dotnet-sdk-relay/EppoSDKRelay/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
{
builder.UseStartup<Startup>();
builder.UseUrls("http://" + host + ":" + port);

// Listen on the docker hostname as well
builder.UseUrls("http://host.docker.internal:" + port);
});
}
11 changes: 4 additions & 7 deletions package-testing/dotnet-sdk-relay/EppoSDKRelay/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ namespace EppoSDKRelay;

public class Startup
{
static readonly String apiHost = Environment.GetEnvironmentVariable("EPPO_API_HOST") ?? "localhost";
static readonly String apiPort = Environment.GetEnvironmentVariable("EPPO_API_PORT") ?? "5000";
static readonly String eppoBaseUrl = Environment.GetEnvironmentVariable("EPPO_BASE_URL") ?? "http://localhost:5000/api";
static readonly String apiToken = Environment.GetEnvironmentVariable("EPPO_API_TOKEN") ?? "NO_TOKEN";


public static void InitEppoClient()
{
var url = "http://" + apiHost + ":" + apiPort;
Console.WriteLine("Initializating SDK pointed at" + url);
Console.WriteLine("Initializating SDK pointed at" + eppoBaseUrl);

var eppoClientConfig = new EppoClientConfig(apiToken, new AssignmentLogger())
var eppoClientConfig = new EppoClientConfig(apiToken, AssignmentLogger.Instance)
{
BaseUrl = url
BaseUrl = eppoBaseUrl
};

EppoClient.Init(eppoClientConfig);
Expand Down Expand Up @@ -45,7 +43,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage();

app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My REST Server v1"));
}

app.UseHttpsRedirection();
Expand Down

0 comments on commit 7a62c9f

Please sign in to comment.