Skip to content

Commit

Permalink
Merge pull request #245 from microsoft/209/webapi-library-integration
Browse files Browse the repository at this point in the history
WebAPI and CA library integration
  • Loading branch information
vaughanknight authored Feb 6, 2023
2 parents 95b1fe8 + 54ffe07 commit 39d1394
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 120 deletions.
2 changes: 1 addition & 1 deletion src/CarbonAware.WebApi/src/CarbonAware.WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<ItemGroup>
<ProjectReference Include="..\..\CarbonAware.Aggregators\src\CarbonAware.Aggregators.csproj" />
<ProjectReference Include="..\..\CarbonAware.LocationSources\src\CarbonAware.LocationSources.csproj" />
<ProjectReference Include="..\..\GSF.CarbonAware\src\GSF.CarbonAware.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
61 changes: 39 additions & 22 deletions src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using CarbonAware.Aggregators.Emissions;
using CarbonAware.Aggregators.Forecast;
using CarbonAware.Interfaces;
using CarbonAware.Model;
using CarbonAware.WebApi.Models;
using GSF.CarbonAware.Handlers;
using GSF.CarbonAware.Models;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Diagnostics;
Expand All @@ -15,19 +13,19 @@ public class CarbonAwareController : ControllerBase
{
private readonly ILogger<CarbonAwareController> _logger;

private readonly IForecastAggregator _forecastAggregator;
private readonly IEmissionsHandler _emissionsHandler;

private readonly IEmissionsAggregator _emissionsAggregator;
private readonly IForecastHandler _forecastHandler;

private readonly ILocationSource _locationSource;
private readonly ILocationHandler _locationSource;

private static readonly ActivitySource Activity = new ActivitySource(nameof(CarbonAwareController));

public CarbonAwareController(ILogger<CarbonAwareController> logger, IEmissionsAggregator emissionsAggregator, IForecastAggregator forecastAggregator, ILocationSource locationSouce)
public CarbonAwareController(ILogger<CarbonAwareController> logger, IEmissionsHandler emissionsHandler, IForecastHandler forecastHandler, ILocationHandler locationSouce)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_forecastAggregator = forecastAggregator ?? throw new ArgumentNullException(nameof(forecastAggregator));
_emissionsAggregator = emissionsAggregator ?? throw new ArgumentNullException(nameof(emissionsAggregator));
_forecastHandler = forecastHandler ?? throw new ArgumentNullException(nameof(forecastHandler));
_emissionsHandler = emissionsHandler ?? throw new ArgumentNullException(nameof(emissionsHandler));
_locationSource = locationSouce ?? throw new ArgumentNullException(nameof(locationSouce));
}

Expand All @@ -43,7 +41,7 @@ public CarbonAwareController(ILogger<CarbonAwareController> logger, IEmissionsAg
[HttpGet("bylocations/best")]
public async Task<IActionResult> GetBestEmissionsDataForLocationsByTime([FromQuery] EmissionsDataForLocationsParametersDTO parameters)
{
var response = await _emissionsAggregator.GetBestEmissionsDataAsync(parameters);
var response = await _emissionsHandler.GetBestEmissionsDataAsync(parameters.MultipleLocations!, parameters.Start, parameters.End);
return response.Any() ? Ok(response) : NoContent();
}

Expand All @@ -59,29 +57,32 @@ public async Task<IActionResult> GetBestEmissionsDataForLocationsByTime([FromQue
[HttpGet("bylocations")]
public async Task<IActionResult> GetEmissionsDataForLocationsByTime([FromQuery] EmissionsDataForLocationsParametersDTO parameters)
{
var response = await _emissionsAggregator.GetEmissionsDataAsync(parameters);
var response = await _emissionsHandler.GetEmissionsDataAsync(parameters.MultipleLocations!, parameters.Start, parameters.End);
return response.Any() ? Ok(response) : NoContent();
}

/// <summary>
/// Calculate the best emission data by location for a specified time period.
/// </summary>
/// <param name="location"> String named location.</param>
/// <param name="time"> [Optional] Start time for the data query.</param>
/// <param name="toTime"> [Optional] End time for the data query.</param>
/// <param name="startTime"> [Optional] Start time for the data query.</param>
/// <param name="endTime"> [Optional] End time for the data query.</param>
/// <returns>Array of EmissionsData objects that contains the location, time and the rating in g/kWh</returns>
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<EmissionsData>))]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationProblemDetails))]
[HttpGet("bylocation")]
public async Task<IActionResult> GetEmissionsDataForLocationByTime([FromQuery, SwaggerParameter(Required = true)] string location, DateTimeOffset? time = null, DateTimeOffset? toTime = null)
public async Task<IActionResult> GetEmissionsDataForLocationByTime(
[FromQuery, SwaggerParameter(Required = true)] string location,
DateTimeOffset? startTime = null,
DateTimeOffset? endTime = null)
{
var parameters = new EmissionsDataForLocationsParametersDTO
{
MultipleLocations = new string[]{ location },
Start = time,
End = toTime
Start = startTime,
End = endTime
};
return await GetEmissionsDataForLocationsByTime(parameters);
}
Expand Down Expand Up @@ -114,7 +115,7 @@ public async Task<IActionResult> GetEmissionsDataForLocationByTime([FromQuery, S
[HttpGet("forecasts/current")]
public async Task<IActionResult> GetCurrentForecastData([FromQuery] EmissionsForecastCurrentParametersDTO parameters)
{
var forecasts = await _forecastAggregator.GetCurrentForecastDataAsync(parameters);
var forecasts = await _forecastHandler.GetCurrentForecastAsync(parameters.MultipleLocations!, parameters.Start, parameters.End, parameters.Duration);
var results = forecasts.Select(f => EmissionsForecastDTO.FromEmissionsForecast(f));
return Ok(results);
}
Expand Down Expand Up @@ -147,7 +148,13 @@ public async Task<IActionResult> BatchForecastDataAsync([FromBody] IEnumerable<E
var result = new List<EmissionsForecastDTO>();
foreach ( var forecastParameters in requestedForecasts)
{
var forecast = await _forecastAggregator.GetForecastDataAsync(forecastParameters);
var forecast = await _forecastHandler.GetForecastByDateAsync(
forecastParameters.SingleLocation!,
forecastParameters.Start,
forecastParameters.End,
forecastParameters.Requested,
forecastParameters.Duration
);
result.Add(EmissionsForecastDTO.FromEmissionsForecast(forecast));
};

Expand All @@ -172,7 +179,12 @@ public async Task<IActionResult> BatchForecastDataAsync([FromBody] IEnumerable<E
[HttpGet("average-carbon-intensity")]
public async Task<IActionResult> GetAverageCarbonIntensity([FromQuery] CarbonIntensityParametersDTO parameters)
{
var result = await this._emissionsAggregator.CalculateAverageCarbonIntensityAsync(parameters);
var result = await this._emissionsHandler.GetAverageCarbonIntensityAsync(
parameters.SingleLocation!,
(DateTimeOffset)parameters.Start!,
(DateTimeOffset)parameters.End!
);

var carbonIntensity = new CarbonIntensityDTO
{
Location = parameters.SingleLocation,
Expand Down Expand Up @@ -205,9 +217,14 @@ public async Task<IActionResult> GetAverageCarbonIntensity([FromQuery] CarbonInt
public async Task<IActionResult> GetAverageCarbonIntensityBatch([FromBody] IEnumerable<CarbonIntensityBatchParametersDTO> requestedCarbonIntensities)
{
var result = new List<CarbonIntensityDTO>();
foreach ( var carbonIntensityBatchDTO in requestedCarbonIntensities)
foreach (var carbonIntensityBatchDTO in requestedCarbonIntensities)
{
var carbonIntensityValue = await this._emissionsAggregator.CalculateAverageCarbonIntensityAsync(carbonIntensityBatchDTO);
var carbonIntensityValue = await this._emissionsHandler.GetAverageCarbonIntensityAsync(
carbonIntensityBatchDTO.SingleLocation!,
(DateTimeOffset)carbonIntensityBatchDTO.Start!,
(DateTimeOffset)carbonIntensityBatchDTO.End!
);

var carbonIntensityDTO = new CarbonIntensityDTO()
{
Location = carbonIntensityBatchDTO.SingleLocation,
Expand Down
10 changes: 5 additions & 5 deletions src/CarbonAware.WebApi/src/Controllers/LocationsController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using CarbonAware.Interfaces;
using CarbonAware.Model;
using GSF.CarbonAware.Handlers;
using GSF.CarbonAware.Models;
using Microsoft.AspNetCore.Mvc;

namespace CarbonAware.WebApi.Controllers;
Expand All @@ -10,10 +10,10 @@ public class LocationsController : ControllerBase
{
private readonly ILogger<CarbonAwareController> _logger;

private readonly ILocationSource _locationSource;
private readonly ILocationHandler _locationSource;


public LocationsController(ILogger<CarbonAwareController> logger, ILocationSource locationSouce)
public LocationsController(ILogger<CarbonAwareController> logger, ILocationHandler locationSouce)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_locationSource = locationSouce ?? throw new ArgumentNullException(nameof(locationSouce));
Expand All @@ -29,7 +29,7 @@ public LocationsController(ILogger<CarbonAwareController> logger, ILocationSourc
[HttpGet()]
public async Task<IActionResult> GetAllLocations()
{
var response = await _locationSource.GetGeopositionLocationsAsync();
var response = await _locationSource.GetLocationsAsync();
return response.Any() ? Ok(response) : NoContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class HttpResponseExceptionFilter : IExceptionFilter
{
{ "ArgumentException", (int)HttpStatusCode.BadRequest },
{ "NotImplementedException", (int)HttpStatusCode.NotImplemented },
{ "InvalidOperationException", (int)HttpStatusCode.BadRequest },
};

public HttpResponseExceptionFilter(ILogger<HttpResponseExceptionFilter> logger, IOptionsMonitor<CarbonAwareVariablesConfiguration> options)
Expand Down
4 changes: 2 additions & 2 deletions src/CarbonAware.WebApi/src/Models/EmissionsDataDTO.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace CarbonAware.WebApi.Models;

using CarbonAware.Model;
using GSF.CarbonAware.Models;
using System.Text.Json.Serialization;

[Serializable]
Expand Down Expand Up @@ -30,7 +30,7 @@ public record EmissionsDataDTO
}
return new EmissionsDataDTO
{
Location = emissionsData.Location,
Location = emissionsData.Location!,
Timestamp = emissionsData.Time,
Duration = (int)emissionsData.Duration.TotalMinutes,
Value = emissionsData.Rating
Expand Down
12 changes: 4 additions & 8 deletions src/CarbonAware.WebApi/src/Models/EmissionsForecastDTO.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace CarbonAware.WebApi.Models;

using CarbonAware.Model;
using GSF.CarbonAware.Models;
using System.Text.Json.Serialization;

[Serializable]
Expand Down Expand Up @@ -100,14 +100,10 @@ public static EmissionsForecastDTO FromEmissionsForecast(EmissionsForecast emiss
{
return new EmissionsForecastDTO
{
RequestedAt = emissionsForecast.RequestedAt,
GeneratedAt = emissionsForecast.GeneratedAt,
Location = emissionsForecast.Location.Name!,
DataStartAt = emissionsForecast.DataStartAt,
DataEndAt = emissionsForecast.DataEndAt,
WindowSize = (int)emissionsForecast.WindowSize.TotalMinutes,
OptimalDataPoints = emissionsForecast.OptimalDataPoints.Select(d => EmissionsDataDTO.FromEmissionsData(d))!,
ForecastData = emissionsForecast.ForecastData.Select(d => EmissionsDataDTO.FromEmissionsData(d))!,
RequestedAt = emissionsForecast.RequestedAt
ForecastData = emissionsForecast.EmissionsDataPoints.Select(d => EmissionsDataDTO.FromEmissionsData(d))!,
OptimalDataPoints = emissionsForecast.OptimalDataPoints.Select(d => EmissionsDataDTO.FromEmissionsData(d))!
};
}
}
20 changes: 15 additions & 5 deletions src/CarbonAware.WebApi/src/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using CarbonAware;
using CarbonAware.Aggregators.Configuration;
using CarbonAware.WebApi.Configuration;
using CarbonAware.WebApi.Filters;
using GSF.CarbonAware.Configuration;
using GSF.CarbonAware.Exceptions;
using Microsoft.OpenApi.Models;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
Expand Down Expand Up @@ -48,8 +49,17 @@

builder.Services.Configure<CarbonAwareVariablesConfiguration>(builder.Configuration.GetSection(CarbonAwareVariablesConfiguration.Key));

string? errorMessage;
bool successfulEmissionServices = builder.Services.TryAddCarbonAwareEmissionServices(builder.Configuration, out errorMessage);
bool successfulServices = true;
string? errorMessage = null;
try
{
builder.Services.AddEmissionsServices(builder.Configuration);
builder.Services.AddForecastServices(builder.Configuration);
} catch(CarbonAwareException e)
{
successfulServices = false;
errorMessage = e.Message;
}

CarbonAwareVariablesConfiguration config = new();

Expand All @@ -64,8 +74,8 @@
});

var app = builder.Build();

if(!successfulEmissionServices)
if (!successfulServices)
{
var _logger = app.Services.GetService<ILogger<Program>>();
_logger?.LogError(errorMessage);
Expand Down
10 changes: 10 additions & 0 deletions src/CarbonAware.WebApi/src/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
{
"DataSources": {
"EmissionsDataSource": "test-json",
"ForecastDataSource": "", // We don't currently publish a sample test data source for forecasts.
"Configurations": {
"test-json": {
"Type": "JSON",
"DataFileLocation": "test-data-azure-emissions.json"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,6 @@ public async Task EmissionsForecastsBatch_SupportedDataSources_ReturnsOk(string
Assert.That(forecasts!.Count, Is.EqualTo(inputData.Count()));
foreach (var forecast in forecasts!)
{
Assert.That(forecast.Location, Is.EqualTo(location));
Assert.That(forecast.DataStartAt, Is.EqualTo(expectedDataStartAt));
Assert.That(forecast.DataEndAt, Is.EqualTo(expectedDataEndAt));
Assert.That(forecast.RequestedAt, Is.EqualTo(expectedRequestedAt));
Assert.That(forecast.GeneratedAt, Is.Not.Null);
Assert.That(forecast.OptimalDataPoints, Is.Not.Null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<ItemGroup>
<ProjectReference Include="..\..\src\CarbonAware.WebApi.csproj" />
<ProjectReference Include="..\..\..\GSF.CarbonAware\src\GSF.CarbonAware.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 39d1394

Please sign in to comment.