mirror of https://github.com/dapr/dotnet-sdk.git
Logging changes to use ILogger (#453)
* logging changes to use ILogger Co-authored-by: Ryan Nowak <nowakra@gmail.com>
This commit is contained in:
parent
aa682eb462
commit
0ccddf73ff
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue