Logging changes to use ILogger (#453)

* logging changes to use ILogger

Co-authored-by: Ryan Nowak <nowakra@gmail.com>
This commit is contained in:
vinayada1 2020-10-30 13:09:32 -07:00 committed by GitHub
parent aa682eb462
commit 0ccddf73ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 191 additions and 232 deletions

View File

@ -4,7 +4,6 @@
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<!--
This is a workaround for https://github.com/dotnet/sdk/issues/14019
The extra reference is harmless but is needed due to a bug in the 5.0 RC dotnet SDK.

View File

@ -9,7 +9,9 @@ namespace Dapr.Actors.AspNetCore
using Dapr.Actors.Runtime;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
/// <summary>
/// Class containing DaprActor related extension methods for Microsoft.AspNetCore.Hosting.IWebHostBuilder.
@ -22,27 +24,29 @@ namespace Dapr.Actors.AspNetCore
/// Configures the service to use the routes needed by Dapr Actor runtime.
/// </summary>
/// <param name="hostBuilder">The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.</param>
/// <param name="configureActorRuntime">Adds a delegate to configure Actor runtime..</param>
/// <param name="configure">A delegate used to register actors and configure the actor runtime.</param>
/// <returns>The Microsoft.AspNetCore.Hosting.IWebHostBuilder.</returns>
public static IWebHostBuilder UseActors(this IWebHostBuilder hostBuilder, Action<ActorRuntime> configureActorRuntime)
public static IWebHostBuilder UseActors(this IWebHostBuilder hostBuilder, Action<ActorRuntimeOptions> configure)
{
if (hostBuilder == null)
{
throw new ArgumentNullException("hostBuilder");
}
hostBuilder.ConfigureServices(services =>
{
if (configure != null)
{
services.Configure<ActorRuntimeOptions>(configure);
}
});
// Check if 'UseActors' has already been called.
if (hostBuilder.GetSetting(SettingName) != null && hostBuilder.GetSetting(SettingName).Equals(true.ToString(), StringComparison.Ordinal))
{
return hostBuilder;
}
var runtime = new ActorRuntime();
if (configureActorRuntime != null)
{
configureActorRuntime.Invoke(runtime);
}
// Set flag to prevent double service configuration
hostBuilder.UseSetting(SettingName, true.ToString());
@ -53,7 +57,10 @@ namespace Dapr.Actors.AspNetCore
services.AddHealthChecks();
services.AddSingleton<IStartupFilter>(new DaprActorSetupFilter());
services.AddSingleton<ActorRuntime>(runtime);
services.AddSingleton<ActorRuntime>(s =>
{
return new ActorRuntime(s.GetRequiredService<IOptions<ActorRuntimeOptions>>().Value, s.GetRequiredService<ILoggerFactory>());
});
});
return hostBuilder;

View File

@ -1,123 +0,0 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
namespace Dapr.Actors
{
using System;
using System.Globalization;
internal sealed class ActorTrace
{
internal static readonly ActorTrace Instance = new ActorTrace();
private readonly ITraceWriter traceWriter;
/// <summary>
/// Prevents a default instance of the <see cref="ActorTrace" /> class from being created.
/// </summary>
private ActorTrace()
{
// TODO: Replace with actual TraceWriter (or integrate with distributed tracing).
// Use ConsoleTraceWriter during development & test.
this.traceWriter = new ConsoleTraceWriter();
}
/// <summary>
/// Interface for traces.
/// </summary>
private interface ITraceWriter
{
/// <summary>
/// Writes info trace.
/// </summary>
/// <param name="infoText">Text to trace.</param>
void WriteInfo(string infoText);
/// <summary>
/// Writes warning trace.
/// </summary>
/// <param name="warningText">Text to trace.</param>
void WriteWarning(string warningText);
/// <summary>
/// Writes Error trace.
/// </summary>
/// <param name="errorText">Text to trace.</param>
void WriteError(string errorText);
}
internal void WriteInfo(string type, string format, params object[] args)
{
this.WriteInfoWithId(type, string.Empty, format, args);
}
internal void WriteInfoWithId(string type, string id, string format, params object[] args)
{
if (args == null || args.Length == 0)
{
this.traceWriter.WriteInfo($"{type}: {id} {format}");
}
else
{
this.traceWriter.WriteInfo($"{type}: {id} {string.Format(CultureInfo.InvariantCulture, format, args)}");
}
}
internal void WriteWarning(string type, string format, params object[] args)
{
this.WriteWarningWithId(type, string.Empty, format, args);
}
internal void WriteWarningWithId(string type, string id, string format, params object[] args)
{
if (args == null || args.Length == 0)
{
this.traceWriter.WriteWarning($"{type}: {id} {format}");
}
else
{
this.traceWriter.WriteWarning($"{type}: {id} {string.Format(CultureInfo.InvariantCulture, format, args)}");
}
}
internal void WriteError(string type, string format, params object[] args)
{
this.WriteErrorWithId(type, string.Empty, format, args);
}
internal void WriteErrorWithId(string type, string id, string format, params object[] args)
{
if (args == null || args.Length == 0)
{
this.traceWriter.WriteError($"{type}: {id} {format}");
}
else
{
this.traceWriter.WriteError($"{type}: {id} {string.Format(CultureInfo.InvariantCulture, format, args)}");
}
}
private class ConsoleTraceWriter : ITraceWriter
{
public void WriteError(string errorText)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"ERROR: {errorText}");
Console.ResetColor();
}
public void WriteInfo(string infoText)
{
Console.WriteLine(infoText);
}
public void WriteWarning(string warningText)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"WARNING: {warningText}");
Console.ResetColor();
}
}
}
}

View File

@ -16,6 +16,7 @@ namespace Dapr.Actors.Communication
using System.Xml;
using Dapr.Actors;
using Dapr.Actors.Resources;
using Microsoft.Extensions.Logging;
/// <summary>
/// Fault type used by Service Remoting to transfer the exception details from the service to the client.
@ -52,25 +53,21 @@ namespace Dapr.Actors.Communication
/// </summary>
/// <param name="exception">Exception.</param>
/// <returns>Serialized bytes.</returns>
public static byte[] FromException(Exception exception)
public static (byte[], string) FromException(Exception exception)
{
try
{
using var stream = new MemoryStream();
binaryFormatter.Serialize(stream, exception);
stream.Flush();
return stream.ToArray();
return (stream.ToArray(), string.Empty);
}
catch (Exception e)
{
// failed to serialize the exception, include the information about the exception in the data
// Add trace diagnostics
ActorTrace.Instance.WriteWarning(
"RemoteException",
"Serialization failed for Exception Type {0} : Reason {1}",
exception.GetType().FullName,
e);
return FromExceptionString(exception);
var errorMessage = $"RemoteException, Serialization failed for Exception Type {exception.GetType().FullName} : Reason {e}";
return (FromExceptionString(exception), errorMessage);
}
}
@ -103,7 +100,7 @@ namespace Dapr.Actors.Communication
return false;
}
internal static bool TryDeserializeExceptionData(Stream data, out ServiceExceptionData result)
internal static bool TryDeserializeExceptionData(Stream data, out ServiceExceptionData result, ILogger logger = null)
{
try
{
@ -114,7 +111,7 @@ namespace Dapr.Actors.Communication
catch (Exception e)
{
// swallowing the exception
ActorTrace.Instance.WriteWarning(
logger?.LogWarning(
"RemoteException",
" ServiceExceptionData DeSerialization failed : Reason {0}",
e);
@ -161,7 +158,7 @@ namespace Dapr.Actors.Communication
}
}
private static bool TryDeserializeServiceException(Stream data, out Exception result)
private static bool TryDeserializeServiceException(Stream data, out Exception result, ILogger logger = null)
{
try
{
@ -175,7 +172,7 @@ namespace Dapr.Actors.Communication
catch (Exception e)
{
// swallowing the exception
ActorTrace.Instance.WriteWarning("RemoteException", "DeSerialization failed : Reason {0}", e);
logger?.LogWarning("RemoteException", "DeSerialization failed : Reason {0}", e);
}
result = null;

View File

@ -8,5 +8,8 @@
<Description>This package contains the reference assemblies for developing Actor services using Dapr.</Description>
<PackageTags>$(PackageTags);Actors</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.0" />
</ItemGroup>
</Project>

View File

@ -19,6 +19,7 @@ namespace Dapr.Actors
using System.Threading.Tasks;
using Dapr.Actors.Communication;
using Dapr.Actors.Resources;
using Microsoft.Extensions.Logging;
/// <summary>
/// Class to interact with Dapr runtime over http.
@ -26,7 +27,6 @@ namespace Dapr.Actors
internal class DaprHttpInteractor : IDaprInteractor
{
private const string DaprEndpoint = Constants.DaprDefaultEndpoint;
private const string TraceType = "DaprHttpInteractor";
private readonly string daprPort;
private readonly HttpClientHandler innerHandler;
private readonly IReadOnlyList<DelegatingHandler> delegateHandlers;
@ -420,31 +420,19 @@ namespace Dapr.Actors
CancellationToken cancellationToken)
{
HttpResponseMessage response;
try
{
// Get the request using the Func as same request cannot be resent when retries are implemented.
var request = requestFunc.Invoke();
// add token for dapr api token based authentication
var daprApiToken = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
if (daprApiToken != null)
{
request.Headers.Add("dapr-api-token", daprApiToken);
}
// Get the request using the Func as same request cannot be resent when retries are implemented.
var request = requestFunc.Invoke();
response = await this.httpClient.SendAsync(request, cancellationToken);
}
catch (AuthenticationException ex)
// add token for dapr api token based authentication
var daprApiToken = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
if (daprApiToken != null)
{
ActorTrace.Instance.WriteError(TraceType, ex.ToString());
throw;
}
catch (HttpRequestException ex)
{
ActorTrace.Instance.WriteError(TraceType, ex.ToString());
throw;
request.Headers.Add("dapr-api-token", daprApiToken);
}
response = await this.httpClient.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
// RefreshSecurity Settings and try again,

View File

@ -8,6 +8,7 @@ namespace Dapr.Actors.Runtime
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
/// <summary>
/// Represents the base class for actors.
@ -19,10 +20,14 @@ namespace Dapr.Actors.Runtime
/// </remarks>
public abstract class Actor
{
private const string TraceType = "Actor";
private readonly string traceId;
private readonly string actorTypeName;
/// <summary>
/// The logger
/// </summary>
protected ILogger logger { get; }
/// <summary>
/// Contains timers to be invoked.
/// </summary>
@ -42,6 +47,7 @@ namespace Dapr.Actors.Runtime
this.ActorService = actorService;
this.StateManager = actorStateManager ?? new ActorStateManager(this);
this.actorTypeName = this.ActorService.ActorTypeInfo.ActorTypeName;
this.logger = actorService.LoggerFactory.CreateLogger(this.GetType());
}
/// <summary>
@ -56,8 +62,6 @@ namespace Dapr.Actors.Runtime
/// <value>The <see cref="ActorService"/> for the actor.</value>
public ActorService ActorService { get; }
internal ActorTrace TraceSource => ActorTrace.Instance;
internal bool IsDirty { get; private set; }
/// <summary>
@ -69,7 +73,8 @@ namespace Dapr.Actors.Runtime
{
await this.ResetStateAsync();
await this.OnActivateAsync();
this.TraceSource.WriteInfoWithId(TraceType, this.traceId, "Activated");
this.logger.LogDebug("Activated");
// Save any state modifications done in user overridden Activate method.
await this.SaveStateAsync();
@ -77,10 +82,10 @@ namespace Dapr.Actors.Runtime
internal async Task OnDeactivateInternalAsync()
{
this.TraceSource.WriteInfoWithId(TraceType, this.traceId, "Deactivating ...");
this.logger.LogDebug("Deactivating ...");
await this.ResetStateAsync();
await this.OnDeactivateAsync();
this.TraceSource.WriteInfoWithId(TraceType, this.traceId, "Deactivated");
this.logger.LogDebug("Deactivated");
}
internal Task OnPreActorMethodAsyncInternal(ActorMethodContext actorMethodContext)

View File

@ -14,13 +14,13 @@ namespace Dapr.Actors.Runtime
using System.Threading.Tasks;
using Dapr.Actors;
using Dapr.Actors.Communication;
using Microsoft.Extensions.Logging;
/// <summary>
/// Manages Actors of a specific actor type.
/// </summary>
internal sealed class ActorManager : IActorManager
{
private const string TraceType = "ActorManager";
private const string ReceiveReminderMethodName = "ReceiveReminderAsync";
private const string TimerMethodName = "FireTimerAsync";
private readonly ActorService actorService;
@ -36,7 +36,9 @@ namespace Dapr.Actors.Runtime
// method info map used by non-remoting calls.
private readonly ActorMethodInfoMap actorMethodInfoMap;
internal ActorManager(ActorService actorService)
private readonly ILogger logger;
internal ActorManager(ActorService actorService, ILoggerFactory loggerFactory)
{
this.actorService = actorService;
@ -50,6 +52,8 @@ namespace Dapr.Actors.Runtime
this.timerMethodContext = ActorMethodContext.CreateForReminder(TimerMethodName);
this.serializersManager = IntializeSerializationManager(null);
this.messageBodyFactory = new WrappedRequestMessageFactory();
this.logger = loggerFactory?.CreateLogger(this.GetType());
}
internal ActorTypeInformation ActorTypeInfo => this.actorService.ActorTypeInfo;
@ -129,7 +133,6 @@ namespace Dapr.Actors.Runtime
else
{
var errorMsg = $"Method {string.Concat(methodInfo.DeclaringType.Name, ".", methodInfo.Name)} has more than one parameter and can't be invoked through http";
ActorTrace.Instance.WriteError(TraceType, errorMsg);
throw new ArgumentException(errorMsg);
}
@ -234,7 +237,6 @@ namespace Dapr.Actors.Runtime
if (!this.activeActors.TryGetValue(actorId, out var actor))
{
var errorMsg = $"Actor {actorId} is not yet activated.";
ActorTrace.Instance.WriteError(TraceType, errorMsg);
throw new InvalidOperationException(errorMsg);
}
@ -248,10 +250,9 @@ namespace Dapr.Actors.Runtime
// PostActivate will save the state, its not invoked when actorFunc invocation throws.
await actor.OnPostActorMethodAsyncInternal(actorMethodContext);
}
catch (Exception ex)
catch (Exception)
{
await actor.OnInvokeFailedAsync();
ActorTrace.Instance.WriteError(TraceType, $"Got exception from actor method invocation: {ex}");
throw;
}
@ -277,7 +278,11 @@ namespace Dapr.Actors.Runtime
var responseHeaderBytes = this.serializersManager.GetHeaderSerializer().SerializeResponseHeader(responseHeader);
var serializedHeader = Encoding.UTF8.GetString(responseHeaderBytes, 0, responseHeaderBytes.Length);
var responseMsgBody = RemoteException.FromException(ex);
(var responseMsgBody, var errorMsg) = RemoteException.FromException(ex);
if(errorMsg != null)
{
this.logger.LogWarning(ex, errorMsg);
}
return new Tuple<string, byte[]>(serializedHeader, responseMsgBody);
}

View File

@ -12,22 +12,33 @@ namespace Dapr.Actors.Runtime
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
/// <summary>
/// Contains methods to register actor types. Registering the types allows the runtime to create instances of the actor.
/// </summary>
public sealed class ActorRuntime
{
private const string TraceType = "ActorRuntime";
// Map of ActorType --> ActorManager.
private readonly Dictionary<string, ActorManager> actorManagers = new Dictionary<string, ActorManager>();
private ActorSettings actorSettings;
internal ActorRuntime()
private readonly ILogger logger;
internal ActorRuntime(ActorRuntimeOptions options, ILoggerFactory loggerFactory)
{
this.actorSettings = new ActorSettings();
this.logger = loggerFactory.CreateLogger(this.GetType());
// Create ActorManagers, override existing entry if registered again.
foreach(var actorServiceFunc in options.actorServicesFunc)
{
var actorServiceFactory = actorServiceFunc.Value ?? ((type) => new ActorService(type, loggerFactory));
var actorService = actorServiceFactory.Invoke(actorServiceFunc.Key);
this.actorManagers[actorServiceFunc.Key.ActorTypeName] = new ActorManager(actorService, loggerFactory);
}
}
/// <summary>
@ -37,29 +48,6 @@ namespace Dapr.Actors.Runtime
internal static IDaprInteractor DaprInteractor => new DaprHttpInteractor();
/// <summary>
/// Registers an actor with the runtime.
/// </summary>
/// <typeparam name="TActor">Type of actor.</typeparam>
/// <param name="actorServiceFactory">An optional delegate to create actor service. This can be used for dependency injection into actors.</param>
public void RegisterActor<TActor>(Func<ActorTypeInformation, ActorService> actorServiceFactory = null)
where TActor : Actor
{
var actorTypeInfo = ActorTypeInformation.Get(typeof(TActor));
ActorService actorService;
if (actorServiceFactory != null)
{
actorService = actorServiceFactory.Invoke(actorTypeInfo);
}
else
{
actorService = new ActorService(actorTypeInfo);
}
// Create ActorManagers, override existing entry if registered again.
this.actorManagers[actorTypeInfo.ActorTypeName] = new ActorManager(actorService);
}
/// <summary>
/// Allows configuration of this app's actor configuration.
@ -118,7 +106,10 @@ namespace Dapr.Actors.Runtime
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
internal async Task DeactivateAsync(string actorTypeName, string actorId)
{
await GetActorManager(actorTypeName).DeactivateActor(new ActorId(actorId));
using(this.logger.BeginScope("ActorType: {ActorType}, ActorId: {ActorId}", actorTypeName, actorId))
{
await GetActorManager(actorTypeName).DeactivateActor(new ActorId(actorId));
}
}
/// <summary>
@ -133,7 +124,10 @@ namespace Dapr.Actors.Runtime
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
internal Task<Tuple<string, byte[]>> DispatchWithRemotingAsync(string actorTypeName, string actorId, string actorMethodName, string daprActorheader, Stream data, CancellationToken cancellationToken = default)
{
return GetActorManager(actorTypeName).DispatchWithRemotingAsync(new ActorId(actorId), actorMethodName, daprActorheader, data, cancellationToken);
using(this.logger.BeginScope("ActorType: {ActorType}, ActorId: {ActorId}, MethodName: {Reminder}", actorTypeName, actorId, actorMethodName))
{
return GetActorManager(actorTypeName).DispatchWithRemotingAsync(new ActorId(actorId), actorMethodName, daprActorheader, data, cancellationToken);
}
}
/// <summary>
@ -162,7 +156,10 @@ namespace Dapr.Actors.Runtime
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
internal Task FireReminderAsync(string actorTypeName, string actorId, string reminderName, Stream requestBodyStream, CancellationToken cancellationToken = default)
{
return GetActorManager(actorTypeName).FireReminderAsync(new ActorId(actorId), reminderName, requestBodyStream, cancellationToken);
using(this.logger.BeginScope("ActorType: {ActorType}, ActorId: {ActorId}, ReminderName: {Reminder}", actorTypeName, actorId, reminderName))
{
return GetActorManager(actorTypeName).FireReminderAsync(new ActorId(actorId), reminderName, requestBodyStream, cancellationToken);
}
}
/// <summary>
@ -175,7 +172,10 @@ namespace Dapr.Actors.Runtime
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
internal Task FireTimerAsync(string actorTypeName, string actorId, string timerName, CancellationToken cancellationToken = default)
{
return GetActorManager(actorTypeName).FireTimerAsync(new ActorId(actorId), timerName, cancellationToken);
using(this.logger.BeginScope("ActorType: {ActorType}, ActorId: {ActorId}, TimerName: {Timer}", actorTypeName, actorId, timerName))
{
return GetActorManager(actorTypeName).FireTimerAsync(new ActorId(actorId), timerName, cancellationToken);
}
}
private ActorManager GetActorManager(string actorTypeName)
@ -183,7 +183,6 @@ namespace Dapr.Actors.Runtime
if (!this.actorManagers.TryGetValue(actorTypeName, out var actorManager))
{
var errorMsg = $"Actor type {actorTypeName} is not registered with Actor runtime.";
ActorTrace.Instance.WriteError(TraceType, errorMsg);
throw new InvalidOperationException(errorMsg);
}

View File

@ -0,0 +1,31 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
namespace Dapr.Actors.Runtime
{
using System;
using System.Collections.Generic;
/// <summary>
/// Represents the Dapr runtime options
/// </summary>
public class ActorRuntimeOptions
{
// Map of ActorType --> ActorService factory.
internal readonly Dictionary<ActorTypeInformation, Func<ActorTypeInformation, ActorService>> actorServicesFunc = new Dictionary<ActorTypeInformation, Func<ActorTypeInformation, ActorService>>();
/// <summary>
/// Registers an actor with the runtime.
/// </summary>
/// <typeparam name="TActor">Type of actor.</typeparam>
/// <param name="actorServiceFactory">An optional delegate to create actor service. This can be used for dependency injection into actors.</param>
public void RegisterActor<TActor>(Func<ActorTypeInformation, ActorService> actorServiceFactory = null)
where TActor : Actor
{
var actorTypeInfo = ActorTypeInformation.Get(typeof(TActor));
this.actorServicesFunc.Add(actorTypeInfo, actorServiceFactory);
}
}
}

View File

@ -6,6 +6,7 @@
namespace Dapr.Actors.Runtime
{
using System;
using Microsoft.Extensions.Logging;
/// <summary>
/// Represents a host for an actor type within the actor runtime.
@ -18,14 +19,17 @@ namespace Dapr.Actors.Runtime
/// Initializes a new instance of the <see cref="ActorService"/> class.
/// </summary>
/// <param name="actorTypeInfo">The type information of the Actor.</param>
/// <param name="loggerFactory">The logger factory.</param>
/// <param name="actorFactory">The factory method to create Actor objects.</param>
public ActorService(
ActorTypeInformation actorTypeInfo,
ILoggerFactory loggerFactory,
Func<ActorService, ActorId, Actor> actorFactory = null)
{
this.ActorTypeInfo = actorTypeInfo;
this.actorFactory = actorFactory ?? this.DefaultActorFactory;
this.StateProvider = new DaprStateProvider();
this.LoggerFactory = loggerFactory;
}
/// <summary>
@ -35,6 +39,11 @@ namespace Dapr.Actors.Runtime
internal DaprStateProvider StateProvider { get; }
/// <summary>
/// Gets the LoggerFactory for actor service
/// </summary>
public ILoggerFactory LoggerFactory { get; private set; }
internal Actor CreateActor(ActorId actorId)
{
return this.actorFactory.Invoke(this, actorId);

View File

@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Builder
{
if (logger != null)
{
logger.LogWarning("Topic subscription doesn't support route with parameters. Subscription for topic {name} is removed.", entry.Name);
logger.LogError("Topic subscription doesn't support route with parameters. Subscription for topic {name} is removed.", entry.Name);
}
continue;

View File

@ -29,7 +29,7 @@ namespace Dapr.Actors.Test
var message = "Remote Actor Exception";
// Create Serialized Exception
var serializedException = RemoteException.FromException(new InvalidOperationException());
(var serializedException, _) = RemoteException.FromException(new InvalidOperationException());
// De Serialize Exception
var isDeserialzied = RemoteException.ToException(

View File

@ -9,6 +9,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.9.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit" Version="2.4.1" />

View File

@ -0,0 +1,42 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
namespace Dapr.Actors.Test.Runtime
{
using System;
using System.Threading;
using Dapr.Actors.Runtime;
using FluentAssertions;
using Moq;
using Xunit;
using Microsoft.Extensions.Logging;
using System.Linq;
public sealed class ActorRuntimeOptionsTests
{
[Fact]
public void TestRegisterActor_SavesActorServiceFactory()
{
var actorType = typeof(TestActor);
var actorTypeInformation = ActorTypeInformation.Get(actorType);
var actorService = new ActorService(actorTypeInformation, new LoggerFactory());
Func<ActorTypeInformation, ActorService> actorServiceFactory = (actorTypeInfo) => NewActorServiceFactory(actorTypeInfo);
Func<ActorService, ActorId, TestActor> actorFactory = (service, id) =>
new TestActor(service, id, null);
var actorRuntimeOptions = new ActorRuntimeOptions();
actorRuntimeOptions.RegisterActor<TestActor>(actorServiceFactory);
Assert.True(actorRuntimeOptions.actorServicesFunc.Count.Equals(1));
var key = actorRuntimeOptions.actorServicesFunc.Keys.First();
Assert.True(key.ActorTypeName.Equals(ActorTypeInformation.Get(actorType).ActorTypeName));
}
private ActorService NewActorServiceFactory(ActorTypeInformation actorTypeInfo)
{
return new ActorService(actorTypeInfo, null, null);
}
}
}

View File

@ -14,10 +14,13 @@ namespace Dapr.Actors.Test
using Dapr.Actors;
using Dapr.Actors.Runtime;
using Xunit;
using Microsoft.Extensions.Logging;
public sealed class ActorRuntimeTests
{
private const string RenamedActorTypeName = "MyRenamedActor";
private ActorRuntimeOptions options = new ActorRuntimeOptions();
private ILoggerFactory loggerFactory = new LoggerFactory();
private interface ITestActor : IActor
{
@ -27,11 +30,9 @@ namespace Dapr.Actors.Test
public void TestInferredActorType()
{
var actorType = typeof(TestActor);
var actorRuntime = new ActorRuntime();
Assert.Empty(actorRuntime.RegisteredActorTypes);
actorRuntime.RegisterActor<TestActor>();
options.RegisterActor<TestActor>();
var actorRuntime = new ActorRuntime(options, loggerFactory);
Assert.Contains(actorType.Name, actorRuntime.RegisteredActorTypes, StringComparer.InvariantCulture);
}
@ -40,14 +41,10 @@ namespace Dapr.Actors.Test
public void TestExplicitActorType()
{
var actorType = typeof(RenamedActor);
var actorRuntime = new ActorRuntime();
options.RegisterActor<RenamedActor>();
var actorRuntime = new ActorRuntime(options, loggerFactory);
Assert.NotEqual(RenamedActorTypeName, actorType.Name);
Assert.Empty(actorRuntime.RegisteredActorTypes);
actorRuntime.RegisterActor<RenamedActor>();
Assert.Contains(RenamedActorTypeName, actorRuntime.RegisteredActorTypes, StringComparer.InvariantCulture);
}
@ -57,8 +54,8 @@ namespace Dapr.Actors.Test
{
var actorType = typeof(MyActor);
var runtime = new ActorRuntime();
runtime.RegisterActor<MyActor>();
options.RegisterActor<MyActor>();
var runtime = new ActorRuntime(options, loggerFactory);
var output = new MemoryStream();
await runtime.DispatchWithoutRemotingAsync("MyActor", "abc", "MyMethod", new MemoryStream(), output);
@ -73,9 +70,8 @@ namespace Dapr.Actors.Test
public void TestActorSettings()
{
var actorType = typeof(TestActor);
var actorRuntime = new ActorRuntime();
Assert.Empty(actorRuntime.RegisteredActorTypes);
options.RegisterActor<TestActor>();
var actorRuntime = new ActorRuntime(options, loggerFactory);
actorRuntime.ConfigureActorSettings(a =>
{
@ -85,8 +81,6 @@ namespace Dapr.Actors.Test
a.DrainRebalancedActors = true;
});
actorRuntime.RegisterActor<TestActor>();
Assert.Contains(actorType.Name, actorRuntime.RegisteredActorTypes, StringComparer.InvariantCulture);
ArrayBufferWriter<byte> writer = new ArrayBufferWriter<byte>();

View File

@ -11,6 +11,7 @@ namespace Dapr.Actors.Test.Runtime
using FluentAssertions;
using Moq;
using Xunit;
using Microsoft.Extensions.Logging;
public sealed class ActorTests
{
@ -54,7 +55,8 @@ namespace Dapr.Actors.Test.Runtime
var actorTypeInformation = ActorTypeInformation.Get(typeof(TestActor));
Func<ActorService, ActorId, TestActor> actorFactory = (service, id) =>
new TestActor(service, id, actorStateManager);
var actorService = new ActorService(actorTypeInformation, actorFactory);
var loggerFactory = new LoggerFactory();
var actorService = new ActorService(actorTypeInformation, loggerFactory, actorFactory);
var testActor = actorFactory.Invoke(actorService, ActorId.CreateRandom());
return testActor;
}