Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Merge to master #17

Merged
merged 33 commits into from
Jul 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a425532
Minor cleanup
Elfocrash May 15, 2018
b9967fd
Update README.md
Elfocrash May 15, 2018
b067690
Update README.md
Elfocrash May 21, 2018
1b1f84a
Refactoring
Elfocrash May 21, 2018
3a18a20
Merge branch 'develop' of https://github.com/Elfocrash/Cosmonaut into…
Elfocrash May 21, 2018
820e56d
Repeating myself less
Elfocrash May 22, 2018
8ad9c10
Merge branch 'develop' of https://github.com/Elfocrash/Cosmonaut into…
Elfocrash May 22, 2018
fbc5ddc
Adds a way to override the cosmos collection name
Elfocrash May 29, 2018
885a981
More exposure of constructors for testability
Elfocrash May 29, 2018
077b869
Fixes an issue where you could not change the colleciton policy, and …
Elfocrash May 31, 2018
bdb36cb
Made exception handling StatusCode based
Elfocrash Jun 5, 2018
562f601
Forgot to remove unused using statement. Sorry.
Elfocrash Jun 5, 2018
10a99a0
Adds the base for event source based logging
Elfocrash Jun 8, 2018
bb30871
More work on telemetry and added the application insights package
Elfocrash Jun 19, 2018
8894494
Some event work.
Elfocrash Jun 19, 2018
f56e1c7
Adds more specific data collection in the event source. Tests will be…
Elfocrash Jun 20, 2018
8f65a19
Adds reflection mocking for feed response
Elfocrash Jun 20, 2018
8e0092f
Fixes the final failing tests
Elfocrash Jun 20, 2018
4ec25cd
Merge pull request #16 from Elfocrash/feature/add-logging
Elfocrash Jun 20, 2018
ebc79c0
Update README.md
Elfocrash Jul 2, 2018
ec92d2f
Update README.md
Elfocrash Jul 2, 2018
81c2e89
Update README.md
Elfocrash Jul 9, 2018
5cf9e57
Adds the GetByIdAsync method
Elfocrash Jul 9, 2018
19e89b2
Updating dependencies and adding an aggregated exception handling met…
Elfocrash Jul 12, 2018
55049f1
Merge branch 'develop' of https://github.com/Elfocrash/Cosmonaut into…
Elfocrash Jul 12, 2018
6ea35b2
Update README.md
Elfocrash Jul 13, 2018
0fd9eab
Default request logging status to success because CountAsync doesn't …
Elfocrash Jul 13, 2018
4350cd4
Merge branch 'develop' of https://github.com/Elfocrash/Cosmonaut into…
Elfocrash Jul 13, 2018
7aaf302
Renamed the GetByIdAsync method to the more appropriate FindAsync
Elfocrash Jul 14, 2018
f5a18bf
Update README.md
Elfocrash Jul 15, 2018
16b31a3
Update README.md
Elfocrash Jul 15, 2018
bf92994
Test stuff
Elfocrash Jul 15, 2018
b8ade89
Merge branch 'develop' of https://github.com/Elfocrash/Cosmonaut into…
Elfocrash Jul 15, 2018
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
91 changes: 91 additions & 0 deletions Cosmonaut.ApplicationInsights/AppInsightsTelemetryModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Threading;
using Cosmonaut.Diagnostics;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;

namespace Cosmonaut.ApplicationInsights
{
public sealed class AppInsightsTelemetryModule : EventListener, ITelemetryModule
{
private static readonly Lazy<ITelemetryModule> SingleInstance =
new Lazy<ITelemetryModule>(() => new AppInsightsTelemetryModule(), LazyThreadSafetyMode.ExecutionAndPublication);

private TelemetryClient _telemetryClient;
private bool _initialised;

private AppInsightsTelemetryModule()
{
}

public static ITelemetryModule Instance => SingleInstance.Value;

public void Initialize(TelemetryConfiguration configuration)
{
if (_initialised)
{
return;
}

_telemetryClient =
new TelemetryClient(configuration) {InstrumentationKey = configuration.InstrumentationKey};
_initialised = true;
}

protected override void OnEventSourceCreated(EventSource eventSource)
{
base.OnEventSourceCreated(eventSource);

if (eventSource.IsDependencyTrackingEventSource())
{
EnableEvents(eventSource, EventLevel.Informational);
}
}

protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
if (!_initialised || !eventData.EventSource.IsDependencyTrackingEventSource())
{
return;
}

var dependencyTelemetry = CreateDependency(eventData);
_telemetryClient.TrackDependency(dependencyTelemetry);
}

private static DependencyTelemetry CreateDependency(EventWrittenEventArgs eventData)
{
var dependency = AsDependency(eventData);

var dependencyTelemetry = new DependencyTelemetry(
dependency.DependencyTypeName,
dependency.Target,
dependency.DependencyName,
dependency.Data,
dependency.StartTime,
dependency.Duration,
dependency.ResultCode,
dependency.Success);

foreach (var propertyPair in dependency.Properties ?? new Dictionary<string, object>())
{
dependencyTelemetry.Context.Properties[propertyPair.Key] = propertyPair.Value.ToString();
}

return dependencyTelemetry;
}

public static CosmosEventMetadata AsDependency(EventWrittenEventArgs eventData)
{
return CosmosEventDataConverter.ExtractData(eventData).AsDependency();
}

public static CosmosEventMetadata AsDependency(IDictionary<string, object> eventData)
{
return CosmosEventDataConverter.ConvertToDependencyFromEventData(eventData);
}
}
}
22 changes: 22 additions & 0 deletions Cosmonaut.ApplicationInsights/Cosmonaut.ApplicationInsights.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Authors>Nick Chapsas</Authors>
<Description>ApplicationInsights support for Cosmonaut</Description>
<Copyright>Copyright 2018 - Nick Chapsas</Copyright>
<PackageLicenseUrl>https://github.com/Elfocrash/Cosmonaut/blob/develop/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/Elfocrash/Cosmonaut</PackageProjectUrl>
<PackageTags>cosmosdb azure cosmos entitystore entity db orm</PackageTags>
<RepositoryUrl>https://github.com/Elfocrash/Cosmonaut</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.6.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Cosmonaut\Cosmonaut.csproj" />
</ItemGroup>

</Project>
13 changes: 3 additions & 10 deletions Cosmonaut.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,8 @@ static async Task Main(string[] args)
{
var connectionPolicy = new ConnectionPolicy
{
ConnectionProtocol = Protocol.Tcp,
ConnectionMode = ConnectionMode.Direct,
RetryOptions = new RetryOptions
{
MaxRetryAttemptsOnThrottledRequests = 2,
MaxRetryWaitTimeInSeconds = 3
}
ConnectionProtocol = Protocol.Https,
ConnectionMode = ConnectionMode.Gateway
};

var cosmosSettings = new CosmosStoreSettings("localtest",
Expand Down Expand Up @@ -74,8 +69,6 @@ static async Task Main(string[] args)
watch.Restart();
//await Task.Delay(3000);

var testResult = await carStore.Query(new FeedOptions{EnableScanInQuery = true}).SingleOrDefaultAsync(x => x.ModelName.StartsWith("Car 1"));

var addedRetrieved = booksStore.Query().ToListAsync().Result;
System.Console.WriteLine($"Retrieved 50 documents in {watch.ElapsedMilliseconds}ms");
watch.Restart();
Expand All @@ -84,7 +77,7 @@ static async Task Main(string[] args)
addedre.AnotherRandomProp += " Nick";
}

var updated = booksStore.UpdateRangeAsync(addedRetrieved).Result;
var updated = booksStore.UpsertRangeAsync(addedRetrieved).Result;
System.Console.WriteLine($"Updated 50 documents in {watch.ElapsedMilliseconds}ms");
watch.Restart();

Expand Down
2 changes: 1 addition & 1 deletion Cosmonaut.Tests/CollectionCreatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task EnsureCreatedCreatesCollectionIfMissing()
var creator = new CosmosCollectionCreator(_mockDocumentClient.Object);

// Act
var result = await creator.EnsureCreatedAsync<Dummy>(new Database {Id = "databaseName"}, 500);
var result = await creator.EnsureCreatedAsync<Dummy>(UriFactory.CreateDatabaseUri("databaseName").ToString(), collection.Id, 500);

// Assert
result.Should().BeTrue();
Expand Down
28 changes: 16 additions & 12 deletions Cosmonaut.Tests/CosmosAddTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,22 @@ public async Task AddValidObjectSuccess()
Id = id,
Name = "Nick"
};
var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<string>(),
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<Uri>(),
It.IsAny<object>(), It.IsAny<RequestOptions>(), false))
.ReturnsAsync(resourceResponse);

var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.AddAsync(dummy);

//Assert
result.IsSuccess.Should().BeTrue();
result.Entity.Should().BeEquivalentTo(dummy);
result.ResourceResponse.Resource.Should().NotBeNull();
result.ResourceResponse.Resource.Should().BeEquivalentTo(document);
result.CosmosOperationStatus.Should().Be(CosmosOperationStatus.Success);
result.ResourceResponse.StatusCode.Should().Be(HttpStatusCode.OK);
}
Expand All @@ -65,14 +67,14 @@ public async Task AddRangeValidObjectsSuccess()
};
dummies.Add(dummy);

var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<string>(),
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<Uri>(),
It.IsAny<object>(), It.IsAny<RequestOptions>(), false))
.ReturnsAsync(resourceResponse);
}

var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.AddRangeAsync(dummies);
Expand All @@ -98,14 +100,14 @@ public async Task AddRangeParamsValidObjectsSuccess()
};
dummies.Add(dummy);

var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<string>(),
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<Uri>(),
It.IsAny<object>(), It.IsAny<RequestOptions>(), false))
.ReturnsAsync(resourceResponse);
}

var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.AddRangeAsync(dummies[0], dummies[1], dummies[2], dummies[3], dummies[4]);
Expand All @@ -124,13 +126,13 @@ public async Task AddEntityWithoutIdEmptyGeneratedId()
{
Name = "Nick"
};
var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<string>(),
_mockDocumentClient.Setup(x => x.CreateDocumentAsync(It.IsAny<Uri>(),
It.IsAny<object>(), It.IsAny<RequestOptions>(), false))
.ReturnsAsync(resourceResponse);

var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.AddAsync(dummy);
Expand All @@ -140,6 +142,8 @@ public async Task AddEntityWithoutIdEmptyGeneratedId()
isGuid.Should().BeTrue();
guid.Should().NotBeEmpty();
result.IsSuccess.Should().BeTrue();
result.ResourceResponse.Resource.Should().NotBeNull();
result.ResourceResponse.Resource.Should().BeEquivalentTo(document);
result.Entity.Should().BeEquivalentTo(dummy);
result.CosmosOperationStatus.Should().Be(CosmosOperationStatus.Success);
result.ResourceResponse.StatusCode.Should().Be(HttpStatusCode.OK);
Expand Down
20 changes: 13 additions & 7 deletions Cosmonaut.Tests/CosmosRemoveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ public async Task RemoveEntityRemoves()
Name = "Test"
};

var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.DeleteDocumentAsync(It.IsAny<Uri>(), It.IsAny<RequestOptions>()))
.ReturnsAsync(resourceResponse);
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.RemoveAsync(dummy);

// Assert
result.IsSuccess.Should().BeTrue();
result.Entity.Should().BeEquivalentTo(dummy);
result.ResourceResponse.Resource.Should().NotBeNull();
result.ResourceResponse.Resource.Should().BeEquivalentTo(document);
result.CosmosOperationStatus.Should().Be(CosmosOperationStatus.Success);
result.ResourceResponse.StatusCode.Should().Be(HttpStatusCode.OK);
}
Expand All @@ -60,17 +62,19 @@ public async Task RemoveByIdRemoves()
Id = id,
Name = "Test"
};
var document = toRemove.GetCosmosDbFriendlyEntity() as Document;
var document = toRemove.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.DeleteDocumentAsync(It.IsAny<Uri>(), It.IsAny<RequestOptions>()))
.ReturnsAsync(resourceResponse);
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.RemoveByIdAsync(id);

// Assert
result.IsSuccess.Should().BeTrue();
result.ResourceResponse.Resource.Should().NotBeNull();
result.ResourceResponse.Resource.Should().BeEquivalentTo(document);
result.CosmosOperationStatus.Should().Be(CosmosOperationStatus.Success);
result.ResourceResponse.StatusCode.Should().Be(HttpStatusCode.OK);
}
Expand All @@ -88,11 +92,11 @@ public async Task RemoveEntitiesRemoves()

var dummies = new List<Dummy> {dummy};

var document = dummy.GetCosmosDbFriendlyEntity() as Document;
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
_mockDocumentClient.Setup(x => x.DeleteDocumentAsync(It.IsAny<string>(), It.IsAny<RequestOptions>()))
_mockDocumentClient.Setup(x => x.DeleteDocumentAsync(It.IsAny<Uri>(), It.IsAny<RequestOptions>()))
.ReturnsAsync(resourceResponse);
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", new CosmosDatabaseCreator(_mockDocumentClient.Object), new CosmosCollectionCreator(_mockDocumentClient.Object));
var entityStore = new CosmosStore<Dummy>(_mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.RemoveRangeAsync(dummies);
Expand All @@ -101,6 +105,8 @@ public async Task RemoveEntitiesRemoves()
result.IsSuccess.Should().BeTrue();
result.FailedEntities.Should().BeEmpty();
result.SuccessfulEntities.Should().HaveCount(1);
result.SuccessfulEntities.Single().ResourceResponse.Resource.Should().NotBeNull();
result.SuccessfulEntities.Single().ResourceResponse.Resource.Should().BeEquivalentTo(document);
}
}
}
26 changes: 26 additions & 0 deletions Cosmonaut.Tests/CosmosStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using Cosmonaut.Extensions;
using Cosmonaut.Response;
using Cosmonaut.Storage;
using FluentAssertions;
using Microsoft.Azure.Documents;
Expand Down Expand Up @@ -98,5 +99,30 @@ public void RemovePotentialDuplicateIdPropertiesRemovesNoMatterTheCase()
((string)obj.ID?.ToString()).Should().BeNull();
((string)obj.Id?.ToString()).Should().BeNull();
}

[Fact]
public async Task FindAsync_ReturnsEntity_WhenFoundInCosmosDB()
{
// Arrange
Mock<IDocumentClient> mockDocumentClient = MockHelpers.GetMockDocumentClient();
var id = Guid.NewGuid().ToString();
var dummy = new Dummy
{
Id = id,
Name = "Nick"
};
var document = dummy.ConvertObjectToDocument();
var resourceResponse = MockHelpers.CreateResourceResponse(document, HttpStatusCode.OK);
mockDocumentClient.Setup(x => x.ReadDocumentAsync(UriFactory.CreateDocumentUri("databaseName", "dummies", id), It.IsAny<RequestOptions>()))
.ReturnsAsync(resourceResponse);

var entityStore = new CosmosStore<Dummy>(mockDocumentClient.Object, "databaseName", "", "http://test.com");

// Act
var result = await entityStore.FindAsync(id);

//Assert
result.Should().BeEquivalentTo(dummy);
}
}
}
Loading