Skip to content

Commit 7a62c9f

Browse files
authored
fix: bandit attributes, logs, and baseUrl in dotnet SDK relay (#85)
* 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)
1 parent 7d92105 commit 7a62c9f

File tree

9 files changed

+52
-31
lines changed

9 files changed

+52
-31
lines changed

package-testing/dotnet-sdk-relay/EppoSDKRelay/AssignmentLogger.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@
44

55
internal class AssignmentLogger : IAssignmentLogger
66
{
7+
public static AssignmentLogger Instance = new();
8+
9+
public Queue<AssignmentLogData> AssignmentLogs = new();
10+
public Queue<BanditLogEvent> BanditLogs = new();
11+
712
public void LogAssignment(AssignmentLogData assignmentLogData)
813
{
914
Console.WriteLine("Assignment Log");
1015
Console.WriteLine(assignmentLogData);
16+
AssignmentLogs.Enqueue(assignmentLogData);
1117
}
1218

1319
public void LogBanditAction(BanditLogEvent banditLogEvent)
1420
{
1521
Console.WriteLine("Bandit Action Log");
1622
Console.WriteLine(banditLogEvent);
23+
BanditLogs.Enqueue(banditLogEvent);
1724
}
1825
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/Controllers/AssignmentController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@ public ActionResult<string> Post([FromBody] AssignmentRequest data)
2929
switch (data.AssignmentType)
3030
{
3131
case "STRING":
32-
return JsonResult(eppoClient.GetStringAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultValue.ToString()!));
32+
return JsonTestResponse(eppoClient.GetStringAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultValue.ToString()!));
3333

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

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

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

4444
case "JSON":
4545
var jString = defaultValue.ToString();
4646
var defaultJson = JObject.Parse(jString);
47-
return JsonResult(eppoClient.GetJsonAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultJson));
47+
return JsonTestResponse(eppoClient.GetJsonAssignment(data.Flag, data.SubjectKey, convertedAttributes, defaultJson));
4848
}
4949

5050
return JsonError("Invalid Assignment Type " + data.AssignmentType);

package-testing/dotnet-sdk-relay/EppoSDKRelay/Controllers/BanditController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ public ActionResult<string> Post([FromBody] BanditActionRequest data)
3333
subject,
3434
actions,
3535
defaultVal);
36-
return JsonResult(result);
36+
return JsonTestResponse(result);
3737
}
3838
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/Controllers/JsonControllerBase.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,60 @@
33
using EppoSDKRelay.DTO;
44
using System.Text.Json;
55
using Newtonsoft.Json.Linq;
6+
using eppo_sdk.dto;
7+
using eppo_sdk.dto.bandit;
68

79
namespace EppoSDKRelay.controllers;
810

9-
public class JsonControllerBase : ControllerBase {
11+
public class JsonControllerBase : ControllerBase
12+
{
1013

1114
protected static readonly JsonSerializerOptions SerializeOptions = new()
1215
{
1316
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
1417
WriteIndented = true
1518
};
1619

17-
protected static ActionResult<string> JsonResult(object result)
20+
protected static ActionResult<string> JsonTestResponse(object result)
1821
{
1922
// System.Text.Json does not play nicely with Newtonsoft types
2023
// Since "Objects" implement IEnumerable, System.Text will try to encode
2124
// the json object as an array. :(
22-
if (result is JObject) {
25+
if (result is JObject)
26+
{
2327
result = ((JObject)result).ToObject<Dictionary<string, object>>();
2428
}
2529

2630
var response = new TestResponse
2731
{
28-
Result = result
32+
Result = result,
33+
AssignmentLog = DequeueAllForResponse<AssignmentLogData>(AssignmentLogger.Instance.AssignmentLogs),
34+
BanditLog = DequeueAllForResponse<BanditLogEvent>(AssignmentLogger.Instance.BanditLogs),
2935
};
3036
return JsonSerializer.Serialize(response, SerializeOptions);
3137
}
32-
38+
3339
protected static ActionResult<string> JsonError(String error)
3440
{
3541
return JsonSerializer.Serialize(new TestResponse
3642
{
3743
Error = error
3844
}, SerializeOptions);
3945
}
40-
46+
47+
public static List<object> DequeueAllForResponse<T>(Queue<T> queue)
48+
{
49+
List<object> items = [];
50+
51+
while (queue.Count > 0)
52+
{
53+
var item = queue.Dequeue();
54+
if (item != null)
55+
{
56+
items.Add(item);
57+
}
58+
}
59+
60+
return items;
61+
}
4162
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/DTO/AttributeSet.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@ namespace EppoSDKRelay.DTO;
44

55
public class AttributeSet
66
{
7-
public Dictionary<string, object?> NumericAttributes { get; set; }
8-
public Dictionary<string, object?> CategoricalAttributes { get; set; }
9-
10-
public Dictionary<string, object?> AttributeDictionary
11-
{
12-
get => new Dictionary<string, object?>[] { NumericAttributes, CategoricalAttributes }.SelectMany(dict => dict)
13-
.ToDictionary(pair => pair.Key, pair => pair.Value);
14-
}
7+
public required Dictionary<string, object?> NumericAttributes { get; set; }
8+
public required Dictionary<string, object?> CategoricalAttributes { get; set; }
159

1610
public Dictionary<string, string?> CategoricalAttributesAsStrings
1711
{
@@ -23,6 +17,5 @@ public class AttributeSet
2317
public Dictionary<string, object?> NumericAttributesAsNumbers => NumericAttributes
2418
.Where(kvp =>
2519
(kvp.Value is JsonElement jsonElement) && jsonElement.ValueKind == JsonValueKind.Number)
26-
.ToDictionary(kvp => kvp.Key, static kvp => (object?)((JsonElement)kvp.Value).GetDouble());
27-
20+
.ToDictionary(kvp => kvp.Key, static kvp => kvp.Value == null ? null : (object?)((JsonElement)kvp.Value).GetDouble());
2821
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/DTO/BanditActionRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ public ContextAttributes GetSubjectContext()
2121
public IDictionary<string, ContextAttributes> GetActionContextDict()
2222
{
2323
return Actions.ToDictionary(action => action.ActionKey,
24-
action => ContextAttributes.FromDict(action.ActionKey, Values.ConvertJsonValuesToPrimitives(action.AttributeDictionary)));
24+
action => ContextAttributes.FromNullableAttributes(action.ActionKey, Values.ConvertJsonValuesToPrimitives(action.CategoricalAttributes), Values.ConvertJsonValuesToPrimitives(action.NumericAttributes)));
2525
}
2626
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/EppoSDKRelay.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Eppo.Sdk" Version="3.4.0" />
10+
<PackageReference Include="Eppo.Sdk" Version="3.5.1" />
1111
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
1212
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" />
1313
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />

package-testing/dotnet-sdk-relay/EppoSDKRelay/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
1414
{
1515
builder.UseStartup<Startup>();
1616
builder.UseUrls("http://" + host + ":" + port);
17+
18+
// Listen on the docker hostname as well
19+
builder.UseUrls("http://host.docker.internal:" + port);
1720
});
1821
}

package-testing/dotnet-sdk-relay/EppoSDKRelay/Startup.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,17 @@ namespace EppoSDKRelay;
55

66
public class Startup
77
{
8-
static readonly String apiHost = Environment.GetEnvironmentVariable("EPPO_API_HOST") ?? "localhost";
9-
static readonly String apiPort = Environment.GetEnvironmentVariable("EPPO_API_PORT") ?? "5000";
8+
static readonly String eppoBaseUrl = Environment.GetEnvironmentVariable("EPPO_BASE_URL") ?? "http://localhost:5000/api";
109
static readonly String apiToken = Environment.GetEnvironmentVariable("EPPO_API_TOKEN") ?? "NO_TOKEN";
1110

1211

1312
public static void InitEppoClient()
1413
{
15-
var url = "http://" + apiHost + ":" + apiPort;
16-
Console.WriteLine("Initializating SDK pointed at" + url);
14+
Console.WriteLine("Initializating SDK pointed at" + eppoBaseUrl);
1715

18-
var eppoClientConfig = new EppoClientConfig(apiToken, new AssignmentLogger())
16+
var eppoClientConfig = new EppoClientConfig(apiToken, AssignmentLogger.Instance)
1917
{
20-
BaseUrl = url
18+
BaseUrl = eppoBaseUrl
2119
};
2220

2321
EppoClient.Init(eppoClientConfig);
@@ -45,7 +43,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
4543
app.UseDeveloperExceptionPage();
4644

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

5148
app.UseHttpsRedirection();

0 commit comments

Comments
 (0)