Skip to content

Commit

Permalink
Merge branch 'Green-Software-Foundation:dev' into docs/docusaurus-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
danuw authored Nov 28, 2023
2 parents 48f117e + ff355f3 commit e58c157
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 40 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/verify-azure-function-with-packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ jobs:
continue-on-error: true
run: docker rm -f ${{ env.CONTAINER_RUNTIME_NAME }}

# Build and tag final image, remove dangling images only if there are any
- name: Docker Target Final
run: |
docker build --no-cache . -f ${{ env.DOCKERFILE_PATH }} -t ${{ env.CONTAINER_IMAGE_NAME }}
docker rmi -f $(docker images -f "dangling=true" -q)
docker images -qf dangling=true | xargs --no-run-if-empty docker rmi
- name: Docker Run Container
run: docker run -d --name ${{ env.CONTAINER_RUNTIME_NAME }} -p 8080:80 ${{ env.CONTAINER_IMAGE_NAME }}
Expand Down
6 changes: 3 additions & 3 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ you different data than the WebAPI for the same query). We provide a number of
different endpoints to provide the most flexibility to integrate to your
environment:

- You can run the application using the [CLI](./src/CarbonAware.CLI) and refer
- You can run the application using the [CLI](../src/CarbonAware.CLI) and refer
to more documentation [here](./carbon-aware-cli.md).

- You can build a container containing the [WebAPI](./src/CarbonAware.WebApi)
- You can build a container containing the [WebAPI](../src/CarbonAware.WebApi)
and connect via REST requests and refer to more documentation
[here](./carbon-aware-webapi.md).

- You can reference the [Carbon Aware C# Library](./src/GSF.CarbonAware) in your
- You can reference the [Carbon Aware C# Library](../src/GSF.CarbonAware) in your
projects and make use of its functionalities and features.

- (Future) You can install the Nuget package and make requests directly.
Expand Down
4 changes: 2 additions & 2 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Expected output:

For example, to get emissions in the `eastus` and `uksouth` region between
`2022-08-23 at 11:15am` and `2022-08-23 at 11:20am`, run:
`dotnet run -l eastus,uksouth -t 2022-08-23T11:15 --toTime 2022-08-23T11:20`
`dotnet run emissions -l eastus,uksouth -s 2022-08-23T11:15 -e 2022-08-23T11:20`

Expected output:

Expand Down Expand Up @@ -147,7 +147,7 @@ hour window on the 23rd of August in the regions: `eastus`, `westus`,
`westus3`,`uksouth`, run the command:

```bash
dotnet run -l eastus,westus,westus3,uksouth -t 2022-08-23T00:00 --toTime 2022-08-23T23:59 --best
dotnet run -l eastus,westus,westus3,uksouth -s 2022-08-23T00:00 -e 2022-08-23T23:59 --best
```

Expected output:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public async Task Emissions_StartAndEndOptions_ReturnsExpectedData()
_dataSourceMocker.SetupDataMock(start, end, location);

// Act
var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z");
var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T00:00:00Z -e 2022-09-01T00:04:00Z");

// Assert
Assert.AreEqual(0, exitCode);
Expand Down Expand Up @@ -117,7 +117,7 @@ public async Task Emissions_BestOption_ReturnsExpectedData()
_dataSourceMocker.SetupDataMock(start, end, location);

// Act
var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z -b");
var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T00:00:00Z -e 2022-09-01T00:04:00Z -b");

// Assert
Assert.AreEqual(0, exitCode);
Expand Down Expand Up @@ -157,6 +157,26 @@ public async Task Emissions_AverageOption_ReturnsExpectedData()
Assert.IsNotNull(firstResult["Duration"]);
}

[Test]
public async Task Average_Best_ReturnsExpectedError()
{
// Arrange
var start = DateTimeOffset.Parse("2022-09-01T00:00:00Z");
var end = DateTimeOffset.Parse("2022-09-01T03:00:00Z");
var location = "eastus";
_dataSourceMocker.SetupDataMock(start, end, location);

// Act
var exitCode = await InvokeCliAsync($"emissions -l {location} -s 2022-09-01T02:01:00Z -e 2022-09-01T02:04:00Z -a -best");
// Assert
Assert.AreEqual(1, exitCode);
var expectedError = "Options --average and --best cannot be used together Option '-s' expects a single argument but 2 were provided. ";
// Whitespace characters regex
var regex = @"\s+";
var output = Regex.Replace(_console.Error.ToString()!, regex, " ");

Assert.AreEqual(expectedError, output);
}
private void IgnoreTestForDataSource(string reasonMessage, params DataSourceType[] ignoredDataSources)
{
if (ignoredDataSources.Contains(_dataSource))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ public async Task EmissionsForecasts_StartAndEndOptions_ReturnsExpectedData()
var location = "eastus";
var start = DateTimeOffset.UtcNow.AddMinutes(10);
var end = start.AddHours(5);
var dataStartAt = start.ToString("yyyy-MM-ddTHH:mm:ss");
var dataEndAt = end.ToString("yyyy-MM-ddTHH:mm:ss");
var dataStartAt = start.ToString("yyyy-MM-ddTHH:mm:ssZ");
var dataEndAt = end.ToString("yyyy-MM-ddTHH:mm:ssZ");

_dataSourceMocker.SetupForecastMock();
// Act
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public async Task<EmissionsForecast> GetCurrentCarbonIntensityForecastAsync(Loca
{
ForecastedCarbonIntensityData forecast;
var geolocation = await this._locationSource.ToGeopositionLocationAsync(location);
if (geolocation.Latitude != null && geolocation.Latitude != null)
forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.Latitude.ToString() ?? "", geolocation.Longitude.ToString() ?? "");
if (geolocation.Latitude != null && geolocation.Longitude != null)
forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.LatitudeAsCultureInvariantString(), geolocation.LongitudeAsCultureInvariantString());
else
{
forecast = await this._electricityMapsClient.GetForecastedCarbonIntensityAsync (geolocation.Name ?? "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,29 @@ public async Task<IEnumerable<EmissionsData>> GetCarbonIntensityAsync(Location l
}

List<EmissionsData> EmissionsDataList = new List<EmissionsData>();
var emissionDateTime = gridEmissionData.Data.Datetime;

var emissionData = new EmissionsData()
// periodStartTime should be less than current date time because this method should not handle forecast data.
var shouldReturn = periodStartTime <= DateTimeOffset.UtcNow;
if (shouldReturn && emissionDateTime != null && periodStartTime < periodEndTime)
{
Location = location.Name ?? "",
Time = gridEmissionData.Data.Datetime ?? new DateTimeOffset(),
Rating = gridEmissionData.Data.CarbonIntensity ?? 0.0,
Duration = new TimeSpan(0, 0, 0)
};
EmissionsDataList.Add(emissionData);
// periodEndTime would be set periodStartTime in EmissionHandler if it is not specified.
// So we can assume we should return the most recent data if they equal.
// If not, we should return the data after checking it is within specified time range.
shouldReturn = periodStartTime <= emissionDateTime && emissionDateTime < periodEndTime;
}

if (shouldReturn)
{
var emissionData = new EmissionsData()
{
Location = location.Name ?? "",
Time = emissionDateTime ?? new DateTimeOffset(),
Rating = gridEmissionData.Data.CarbonIntensity ?? 0.0,
Duration = new TimeSpan(0, 0, 0)
};
EmissionsDataList.Add(emissionData);
}

return EmissionsDataList;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ public ElectricityMapsFreeDataSourceTests()
_dataSource = new ElectricityMapsFreeDataSource(_logger.Object, _ElectricityMapsFreeClient.Object, _locationSource.Object);
}

[Test]
public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound()
[TestCase(false, TestName = "GetCarbonIntensity_ReturnsResultsWhenRecordsFound without emission date time")]
[TestCase(true, TestName = "GetCarbonIntensity_ReturnsResultsWhenRecordsFound with emission date time")]
public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound(bool withEmissionDateTime)
{
var startDate = DateTimeOffset.UtcNow.AddHours(-10);
var endDate = startDate.AddHours(1);
Expand All @@ -49,6 +50,7 @@ public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound()
{
Data = new Data()
{
Datetime = withEmissionDateTime ? startDate.AddMinutes(30) : null,
CarbonIntensity = expectedCarbonIntensity,
}
};
Expand All @@ -71,8 +73,9 @@ public async Task GetCarbonIntensity_ReturnsResultsWhenRecordsFound()
this._locationSource.Verify(l => l.ToGeopositionLocationAsync(_defaultLocation));
}

[Test]
public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable()
[TestCase(false, TestName = "GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable without emission date time")]
[TestCase(true, TestName = "GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable with emission date time")]
public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable(bool withEmissionDateTime)
{
var startDate = new DateTimeOffset(2022, 4, 18, 12, 32, 42, TimeSpan.FromHours(-6));
var endDate = startDate.AddMinutes(1);
Expand All @@ -84,6 +87,7 @@ public async Task GetCarbonIntensity_UseRegionNameWhenCoordinatesNotAvailable()
{
Data = new Data()
{
Datetime = withEmissionDateTime ? startDate.AddSeconds(30) : null,
CarbonIntensity = expectedCarbonIntensity,
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ public async Task<IActionResult> GetEmissionsDataForLocationsByTime([FromQuery]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationProblemDetails))]
[HttpGet("bylocation")]
public async Task<IActionResult> GetEmissionsDataForLocationByTime(
[FromQuery, SwaggerParameter(Required = true)] string location,
DateTimeOffset? startTime = null,
DateTimeOffset? endTime = null)
[FromQuery, SwaggerParameter(Required = true)] string location,
[FromQuery(Name = "time")] DateTimeOffset? startTime = null,
[FromQuery(Name = "toTime")] DateTimeOffset? endTime = null)
{
var parameters = new EmissionsDataForLocationsParametersDTO
{
Expand Down
6 changes: 4 additions & 2 deletions src/CarbonAware.WebApi/src/Models/CarbonIntensityDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace CarbonAware.WebApi.Models;
[Serializable]
public record CarbonIntensityDTO
{
private DateTimeOffset? _startTime;
private DateTimeOffset? _endTime;
/// <summary>the location name where workflow is run </summary>
/// <example>eastus</example>
[JsonPropertyName("location")]
Expand All @@ -13,12 +15,12 @@ public record CarbonIntensityDTO
/// <summary>the time at which the workflow we are measuring carbon intensity for started </summary>
/// <example>2022-03-01T15:30:00Z</example>
[JsonPropertyName("startTime")]
public DateTimeOffset? StartTime { get; set; }
public DateTimeOffset? StartTime { get => _startTime; set => _startTime = value?.ToUniversalTime(); }

/// <summary> the time at which the workflow we are measuring carbon intensity for ended</summary>
/// <example>2022-03-01T18:30:00Z</example>
[JsonPropertyName("endTime")]
public DateTimeOffset? EndTime { get; set; }
public DateTimeOffset? EndTime { get => _endTime; set => _endTime = value?.ToUniversalTime(); }

/// <summary>Value of the marginal carbon intensity in grams per kilowatt-hour.</summary>
/// <example>345.434</example>
Expand Down
Loading

0 comments on commit e58c157

Please sign in to comment.