/// <summary> /// Loads an implementation of <see cref="IRelayNode"/> into a new <see cref="AppDomain"/>. /// </summary> /// <param name="changedDelegate">The delegate that is called when the assembly is changed.</param> /// <returns>Returns an instance of an implementation of <see cref="IRelayNode"/></returns> internal IRelayNode GetRelayNode(LoadedAssemblyChangeDelegate changedDelegate) { EnsureDomainIsLoaded(); try { Factory nodeFactory = (Factory)_nodeDomain.CreateInstanceFromAndUnwrap( "MySpace.DataRelay.NodeFactory.dll", "MySpace.DataRelay.Factory" ); _nodeChanged = changedDelegate; if (_log.IsInfoEnabled) { _log.Info("Loaded relay node domain."); } return((IRelayNode)nodeFactory.LoadClass("MySpace.DataRelay.RelayNode", "MySpace.DataRelay.RelayNode", out _nodeFileName)); } catch (Exception ex) { if (_log.IsErrorEnabled) { _log.ErrorFormat("Error loading relay node: {0}", ex); } return(null); } }
/// <summary> /// Initialize all the counters /// </summary> /// <param name="instanceName">instance Name</param> public void InitializeCounters(string instanceName) { CreateCounterCategory(this.perfCounterCategoryNameString); // check if instance already there if ((this.perfCounterInstanceName == instanceName) && (this.CounterArray != null)) { Log.Info("Performance counters instance " + instanceName + " is already exists, instance will not be re-initialized."); } else { BdbCounterInstance myInstance = new BdbCounterInstance(); int numberOfCounter = BerkeleyBinaryStorePerformanceCounterConstant.CounterInfo.GetLength(0); myInstance.counters = new PerformanceCounter[numberOfCounter]; for (int i = 0; i < numberOfCounter; i++) { myInstance.counters[i] = new PerformanceCounter( this.perfCounterCategoryNameString, BerkeleyBinaryStorePerformanceCounterConstant.CounterInfo[i, 0], instanceName, false); if (myInstance.counters[i] != null) { myInstance.counters[i].RawValue = 0; } } Interlocked.Exchange(ref this.perfCounterInstanceName, instanceName); Interlocked.Exchange(ref this.CounterArray, myInstance); } }
private void InitializeInstance(RelayNodeConfig config, ForwardingConfig forwardingConfig, Dictionary <string, Dictionary <string, MessageQueue> > errorQueues) { Counters = new ForwardingCounters(); if (config != null) { //without this we'll get a null ref exception if (forwardingConfig == null) { throw new ArgumentNullException("forwardingConfig", "Requires a forwardingConfig to initialize"); } Config = config; ForwardingConfig = forwardingConfig; _zoneDefinitions = config.RelayNodeMapping.ZoneDefinitions; Counters.Initialize(Config.InstanceName); if (InMessageDispatcher != null) { if (_log.IsInfoEnabled) { _log.Info("Relay Forwarder Node Manager Initialized with non-null Dispatcher."); } } else { InMessageDispatcher = new Dispatcher(forwardingConfig.NumberOfThreads, ThreadPriority.Normal, true, "Relay Forwarder"); } if (OutMessageDispatcher == null) { OutMessageDispatcher = new Dispatcher(forwardingConfig.NumberOfOutMessageThreads, ThreadPriority.Normal, true, "Relay Forwader Out Messages"); } NodeGroup.MaximumQueuedItems = forwardingConfig.MaximumTaskQueueDepth; BuildNodeGroups(config, errorQueues); if (config.MyAddresses != null && config.MyAddresses.Count > 0) { for (int i = 0; i < config.MyAddresses.Count; i++) { AddressFamily family = config.MyAddresses[i].AddressFamily; if (family == AddressFamily.InterNetwork && !IPAddress.Loopback.Equals(config.MyAddresses[i]) ) { MyIpAddress = config.MyAddresses[i]; break; } } } _queuedMessageCounterTimer = new Timer(CountQueuedMessages, null, 5000, 5000); _aggregateCounterTickTimer = new Timer(AggregateCounterTicker, null, 500, 500); _myNodeDefinition = GetMyNodeDefinition(); } }
public void Info_Valid_Fact() { _wrapper.Info("This is a Fact"); _eventArgs.Should().NotBeNull(); _eventArgs.Name.Should().Be("This is a Fact"); _eventArgs.Level.Should().Be(LogLevel.Info); }
private void AddLog(string Msg, StackTrace stack = null, string Tittle = "", int TenantId = 0, int UserId = 0, LogType logtype = LogType.Debug, Object Context = null) { try { if (stack == null) { stack = new StackTrace(true); } var methodBase = stack.GetFrame(1).GetMethod(); Type stacktype = methodBase.DeclaringType; string fileName = stacktype.FullName; //文件名 string methodName = methodBase.Name; //方法名 var logModel = new LogModel { TenantId = TenantId, UserId = UserId, Message = Msg, Title = Tittle, MethodName = methodName, FileName = fileName, CodeLine = "0" }; var jsonValue = JsonConvert.SerializeObject(logModel); switch (logtype) { case LogType.Debug: _log.Debug(jsonValue); break; case LogType.Info: _log.Info(jsonValue); break; case LogType.Warn: _log.Warn(jsonValue); break; case LogType.Error: _log.Error(jsonValue); break; case LogType.Fatal: _log.Fatal(jsonValue); break; default: _log.Debug(jsonValue); break; } } catch { } }
public static void HandleException(Exception ex, string msg, string sectionName) { //this sucks, but we need to prevent recursive calling for creating ErrorTrackerConfig if (sectionName != "ErrorTrackerConfig") { logger.HandleException(new ConfigurationErrorsException(msg, ex), "ConfigurationManager"); } else { logger.Info("ConfigurationManager", new ConfigurationErrorsException(msg, ex)); } }
private void InitializeInstance(RelayNodeConfig config, ForwardingConfig forwardingConfig, Dictionary <string, Dictionary <string, ErrorQueue> > errorQueues) { Counters = new ForwardingCounters(); if (config != null) { //without this we'll get a null ref exception if (forwardingConfig == null) { throw new ArgumentNullException("forwardingConfig", "Requires a forwardingConfig to initialize"); } Config = config; ForwardingConfig = forwardingConfig; _zoneDefinitions = config.RelayNodeMapping.ZoneDefinitions; Counters.Initialize(Config.InstanceName); ExtractCommonConfigValues(forwardingConfig); if (InMessageDispatcher != null) { if (_log.IsInfoEnabled) { _log.Info("Relay Forwarder Node Manager Initialized with non-null Dispatcher."); } } else { InMessageDispatcher = new Dispatcher(forwardingConfig.NumberOfThreads, ThreadPriority.Normal, true, "Relay Forwarder"); } if (OutMessageDispatcher == null) { OutMessageDispatcher = new Dispatcher(forwardingConfig.NumberOfOutMessageThreads, ThreadPriority.Normal, true, "Relay Forwader Out Messages"); } BuildNodeGroups(config, errorQueues); MyIpAddress = config.GetAddressToUse(); _queuedMessageCounterTimer = new Timer(CountQueuedMessages, null, 5000, 5000); _aggregateCounterTickTimer = new Timer(AggregateCounterTicker, null, 500, 500); _myNodeDefinition = GetMyNodeDefinition(); _myZone = Node.DetermineZone(_myNodeDefinition); } }
private static T GetSourcedObject <T>(string basePath, XmlNode sectionNode) where T : class { T sourcedObject = default(T); Type objectType = typeof(T); try { if (Log.IsInfoEnabled) { Log.Info("Getting sourced config of type " + objectType.FullName); } XmlSerializer ser = new XmlSerializer(objectType); string configSource = sectionNode.Attributes["configSource"].Value; if (configSource != String.Empty) { XmlReader reader = XmlReader.Create(Path.Combine(Path.GetDirectoryName(basePath), configSource)); sourcedObject = ser.Deserialize(reader) as T; reader.Close(); } } catch (Exception ex) { if (Log.IsErrorEnabled) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Error getting sourced config of type {0}: {1}", objectType.FullName, ex); Log.Error(sb.ToString(), ex); } } return(sourcedObject); }
public override bool Init() { ModuleManager.Instance.AddModule <WebSocketModule>(); //test rpc var channel = ChannelHelper.Instance.GetChannel("LogicServer"); RpcHelper <Greeter.GreeterClient> .Client = new Greeter.GreeterClient(channel); string user = "******"; try { var reply = RpcHelper <Greeter.GreeterClient> .Client.SayHello(new HelloRequest { Name = user }); LogWrapper.Info("Greeting: " + reply.Message); var secondReply = RpcHelper <Greeter.GreeterClient> .Client.SayHelloAgain(new HelloRequest { Name = user }); LogWrapper.Info("Greeting: " + secondReply.Message); } catch (Exception e) { LogWrapper.Info(e.Message); } finally { channel.ShutdownAsync().Wait(); } return(true); }
public override void processMessage(D2LogicalModel d2LogicalModel) { if (logWrapper.isInfo()) { logWrapper.Info("VMSAndMatrix Update"); } bool fullRefresh = false; string feedType = d2LogicalModel.payloadPublication.feedType; if (feedType.ToLower().Contains(FULL_REFRESH_TEXT)) { if (logWrapper.isInfo()) { logWrapper.Info("VMS Full Refresh received"); } fullRefresh = true; vMSDataStore.clearDataStore(); } VmsPublication payloadPublication = (VmsPublication)d2LogicalModel.payloadPublication; DateTime publicationTime = payloadPublication.publicationTime; if (payloadPublication != null) { VmsUnit[] vmsUnits = payloadPublication.vmsUnit; if (logWrapper.isInfo()) { logWrapper.Info("VMS Update(" + vmsUnits.Length + " objects)"); } for (int vmsUnitsPos = 0; vmsUnitsPos < vmsUnits.Length; vmsUnitsPos++) { VmsUnit vmsUnit = vmsUnits[vmsUnitsPos]; processVmsUnit(vmsUnit, publicationTime, fullRefresh); } } if (logWrapper.isInfo()) { logWrapper.Info("VMSAndMatrix Update Complete"); } }
public override void processMessage(D2LogicalModel d2LogicalModel) { if (logWrapper.isDebug()) { logWrapper.Debug("Event Update"); } bool fullRefresh = false; String feedType = d2LogicalModel.payloadPublication.feedType; if (feedType.ToLower().Contains(fullRefreshText)) { logWrapper.Info("Event Full Refresh received"); fullRefresh = true; lock (eventDataStore){ eventDataStore.clearDataStore(); } } SituationPublication situationPublication = (SituationPublication)d2LogicalModel.payloadPublication; DateTime publicationTime = situationPublication.publicationTime; if (situationPublication != null) { Situation[] situationList = situationPublication.situation; if (logWrapper.isDebug()) { logWrapper.Debug("Event Update(" + situationList.Length + " objects)"); } for (int situationListPos = 0; situationListPos < situationList.Length; situationListPos++) { Situation situation = situationList[situationListPos]; processSituation(situation, publicationTime, fullRefresh); } } if (logWrapper.isDebug()) { logWrapper.Debug("Event Update Complete"); } }
private DATEXIIUpdateService() { logWrapper = new LogWrapper("DATEXIIUpdateService"); logWrapper.Info("Creating DATEXIIUpdateService object"); messageQueue = new Queue <UpdateMessage>(); Timer processQueueTimer = new Timer(); processQueueTimer.Elapsed += new ElapsedEventHandler(processDATEXIIUpdateXML); processQueueTimer.Interval = QUEUE_PROCESSING_TIMER_PERIOD; processQueueTimer.Enabled = true; }
private void ElasticSearchConfig_ConfigChanged(object sender, EventArgs e) { var elasticSearchConfig = sender as ElasticSearchConfig; if (elasticSearchConfig != null) { logger.Info("ElasticSearchConfig config reloading"); _config = elasticSearchConfig; foreach (var esNode in _config.Clusters) { BuildCluster(esNode.ClusterName, esNode.TransportType); ClusterThriftNodes[esNode.ClusterName] = BuildThriftNodes(esNode.ThriftNodes); ClusterHttpNodes[esNode.ClusterName] = BuildHttpNodes(esNode.HttpNodes); } logger.Info("ElasticSearchConfig config reloaded"); } else { logger.Error("Attempt to reload with null ElasticSearchConfig config"); } }
public void Initialize(string instanceName) { if (!PerformanceCounterCategory.Exists(PerformanceCategoryName)) { CreatePerformanceCounterCategory(); } BdbInstanceInfo bdbInstanceInfo; if (Instances.TryGetValue(instanceName, out bdbInstanceInfo)) { Log.Info("Performance counters instance " + instanceName + " is already exists, instance will not be re-initialized."); } else { try { bdbInstanceInfo = new BdbInstanceInfo(); int numCounters = PerformanceCounterNames.Length; bdbInstanceInfo.counters = new PerformanceCounter[numCounters]; for (int i = 0; i < numCounters; i++) { bdbInstanceInfo.counters[i] = new PerformanceCounter( PerformanceCategoryName, PerformanceCounterNames[i], instanceName, false ); } bdbInstanceInfo.getHitCounter = new MinuteAggregateCounter(); bdbInstanceInfo.getAttemptCounter = new MinuteAggregateCounter(); bdbInstanceInfo.saveHitCounter = new MinuteAggregateCounter(); bdbInstanceInfo.saveAttemptCounter = new MinuteAggregateCounter(); Instances.Add(instanceName, bdbInstanceInfo); ResetCounters(bdbInstanceInfo.counters); StartTimer(); } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.ErrorFormat("BerkeleyDbCounters:Initialize() Exception creating Memory Store Counters: {0}. The counters might need to be reinstalled via InstallUtil." , ex); } } Log.DebugFormat("Performance counters instance {0} initialized.", instanceName); } }
private void UpdateConfig(RelayNodeConfig config) { if (config != null) { _log.Info("Loading RelayNodeConfig."); _servers.UpdateConfig(config); _typeSettings.UpdateConfig(config); } else { _log.Error("Attempt to reload a RelayNode config with null config"); } }
private DATEXIIProcessServiceFactory(DATEXIIUpdateService datexIIUpdateService) { logWrapper = new LogWrapper("DATEXIIProcessServiceFactory"); logWrapper.Info("Creating DATEXIIProcessServiceFactory object"); datexIIVMSProcessService = new DATEXIIVMSProcessService(); datexIIANPRProcessService = new DATEXIIANPRProcessService(); datexIIMIDASProcessService = new DATEXIIMIDASProcessService(); datexIITMUProcessService = new DATEXIITMUProcessService(); datexIIFusedSensorOnlyProcessService = new DATEXIIFusedSensorOnlyProcessService(); datexIIFusedFVDAndSensorProcessService = new DATEXIIFusedFVDAndSensorProcessService(); datexIINetworkModelUpdateService = new DATEXIINetworkModelUpdateService(datexIIUpdateService); datexIIModelUpdateNotificationProcessService = new DATEXIIModelUpdateNotificationProcessService(this); datexIIEventProcessService = new DATEXIIEventProcessService(); datexIINTISModelVMSProcessService = new DATEXIINTISModelVMSProcessService(); datexIINTISModelMeasurementSitesProcessService = new DATEXIINTISModelMeasurementSitesProcessService(); datexIINTISModelPredefinedLocationProcessService = new DATEXIINTISModelPredefinedLocationProcessService(); }
internal void ProcessFileChanged(string fileName) { EventHandler delegateMethod = GetEventHandler(fileName); if (delegateMethod != null) { try { string filePath = directory + "\\" + fileName; delegateMethod(filePath, EventArgs.Empty); logger.Info("File reload: '" + filePath + "' successfully"); } catch (Exception ex) { logger.HandleException(ex, "FileWatcher"); } } }
private void removeExistingNetworkModel() { logWrapper.Info("Removing existing network model"); try { if (Directory.Exists(nwkModelDirectory)) { Directory.Delete(nwkModelDirectory, true); } } catch (Exception e) { logWrapper.Error("Error removing directory: " + nwkModelDirectory + nwkModelPath); logWrapper.Error(e.StackTrace); return; } }
public override void processMessage(D2LogicalModel d2LogicalModel) { if (logWrapper.isInfo()) { logWrapper.Info("TMU Update"); } MeasuredDataPublication measuredDataPublication = (MeasuredDataPublication)d2LogicalModel.payloadPublication; if (measuredDataPublication != null) { DateTime publicationTime = measuredDataPublication.publicationTime; SiteMeasurements[] siteMeasurementsList = measuredDataPublication.siteMeasurements; if (logWrapper.isDebug()) { logWrapper.Debug("TMU Update(" + siteMeasurementsList.Length + " objects)"); } Dictionary <String, LinkedList <SiteMeasurements> > siteMeasurementsIndex = new Dictionary <String, LinkedList <SiteMeasurements> >(); for (int siteMeasurementsListPos = 0; siteMeasurementsListPos < siteMeasurementsList.Length; siteMeasurementsListPos++) { SiteMeasurements siteMeasurements = siteMeasurementsList[siteMeasurementsListPos]; processSituation(siteMeasurements, publicationTime, siteMeasurementsIndex); } foreach (String tmuIdentifier in siteMeasurementsIndex.Keys) { TMUData tmuData = new TMUData(tmuIdentifier, publicationTime, siteMeasurementsIndex[tmuIdentifier]); tmuDataStore.updateData(tmuData); } } if (logWrapper.isDebug()) { logWrapper.Debug("TMU Update Complete"); } }
/// <summary> /// Waits for the future to complete. /// </summary> public void Wait() { if (IsComplete) { return; } lock (SyncRoot) { while (!IsComplete) { ++_waiterCount; try { Monitor.Wait(SyncRoot); } catch (ThreadAbortException) { int availableWorkers, availableIocp; ThreadPool.GetAvailableThreads(out availableWorkers, out availableIocp); int maxWorkers, maxIocp; ThreadPool.GetMaxThreads(out maxWorkers, out maxIocp); int minWorkers, minIocp; ThreadPool.GetMinThreads(out minWorkers, out minIocp); var builder = new StringBuilder(); builder.AppendLine("ThreadAbortException thrown on Future.Wait()"); builder.AppendLine("AvailableWorkers = " + availableWorkers); builder.AppendLine("AvailableIocp = " + availableIocp); builder.AppendLine("MaxWorkers = " + maxWorkers); builder.AppendLine("MaxIocp = " + maxIocp); builder.AppendLine("MinWorkers = " + minWorkers); builder.AppendLine("MinIocp = " + minIocp); _log.Info(builder.ToString()); throw; } finally { --_waiterCount; } } } }
public override bool Init() { //ModuleManager.Instance.AddModule<WebSocketModule>(); ServerConfig cfg = ConfigManager.Instance.GetCurrentServerConfig(); if (cfg != null && cfg.RpcPort > 0) { Server server = new Server { Services = { Greeter.BindService(new GreeterImpl()) }, Ports = { new ServerPort(cfg.RpcIp, cfg.RpcPort, ServerCredentials.Insecure) } }; server.Start(); LogWrapper.Info("Greeter server listening on port " + cfg.RpcPort); //server.ShutdownAsync().Wait(); } return(true); }
protected async Task RunServerAsync() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } LogWrapper.Info($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); LogWrapper.Info($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); LogWrapper.Info("\n"); _bossGroup = new MultithreadEventLoopGroup(1); _workGroup = new MultithreadEventLoopGroup(); var bootstrap = new ServerBootstrap(); bootstrap .Group(_bossGroup, _workGroup) .Channel <TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast( new HttpServerCodec(), new HttpObjectAggregator(65536), //new WebSocketServerCompressionHandler(), new WebSocketServerProtocolHandler("/websocket", null, true), new BinaryWebSocketFrameHandler(), new ProtocolDecoder(), new ProtocolEncoder(), new MessageHandler(this.ChannelGroup)); })); int port = 18089; _bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); LogWrapper.Info("Listening on " + $"ws://127.0.0.1:{port}/websocket"); }
/// <summary> /// Initializes the <see cref="RelayNode"/> with the given <see cref="ComponentRunState"/>s, /// must be called before calling <see cref="Start"/> /// </summary> /// <param name="componentRunStates"></param> public void Initialize(ComponentRunState[] componentRunStates) { try { if (log.IsInfoEnabled) { if (componentRunStates == null) { log.Info("Initializing Relay Node."); } else { log.Info("Initialzing Relay Node with Component Run States."); } } EnvironmentManager.EnvironmentChanged += EnvironmentChangedHandler; GetConfig(); if (configuration == null) { throw new ConfigurationErrorsException("config failed to load, is null"); } SetClusterAddresses(configuration); fatalFailureTimeout = configuration.FatalShutdownTimeout < 0 ? TimeSpan.FromMinutes(5) : TimeSpan.FromSeconds(configuration.FatalShutdownTimeout); components = new RelayComponents(configuration); if (configuration != null) { messageTracer = new MessageTracer(configuration.TypeSettings.MaxTypeId, configuration.TraceSettings); messageTracer.Activated = configuration.OutputTraceInfo; const string inThreadsName = "DataRelayNode"; if (configuration.NumberOfThreads > 0) { inDispatcher = new Dispatcher(configuration.NumberOfThreads, ThreadPriority.Normal, true, inThreadsName); } else { inDispatcher = new Dispatcher() { Name = inThreadsName }; } const string outThreadsName = "DataRelayNodeOUT"; if (configuration.OutMessagesOnRelayThreads) { if (configuration.NumberOfOutMessageThreads > 0) { outDispatcher = new Dispatcher(configuration.NumberOfOutMessageThreads, ThreadPriority.Normal, true, outThreadsName); } else { outDispatcher = new Dispatcher { Name = outThreadsName }; } outMessagePort = new Port <RelayMessageAsyncResult>(); outMessagesPort = new Port <RelayMessageListAsyncResult>(); outMessageQueue = new DispatcherQueue("DataRelayDispatcherQueueOUT", outDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumOutMessageQueueDepth); Arbiter.Activate(outMessageQueue, Arbiter.ReceiveWithIterator(true, outMessagePort, HandleOutMessage)); Arbiter.Activate(outMessageQueue, Arbiter.ReceiveWithIterator(true, outMessagesPort, HandleOutMessages)); } inMessageQueue = new DispatcherQueue("DataRelayDispatcherQueue", inDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumMessageQueueDepth); queuedTaskThreshold = (int)Math.Floor(0.9 * configuration.MaximumMessageQueueDepth); // setup RelayServicesClient before initalizing components RelayServicesClient.Instance.RelayNodeServices = this; Arbiter.Activate(inMessageQueue, Arbiter.Receive <RelayMessage>(true, inMessagePort, HandleInMessage)); Arbiter.Activate(inMessageQueue, Arbiter.Receive <RelayMessageWithContext>(true, inMessageWithContextPort, HandleInMessage)); Arbiter.Activate(inMessageQueue, Arbiter.Receive <IList <RelayMessage> >(true, inMessagesPort, HandleInMessages)); //by having after the Arbiter.Activate it allows Initialize components to use //IRelayNodeServices that require Message handling components.Initialize(componentRunStates, configuration.IgnoredMessageTypes); queuedMessageCounterTimer = new Timer(CountQueuedMessages, null, 5000, 5000); } } catch (Exception ex) { if (log.IsErrorEnabled) { log.ErrorFormat("Exception initializing relay node: {0}", ex); } throw; //should bring server down } }
/// <summary> /// info /// </summary> /// <param name="message"></param> public static void Info(string message) { _log.Info(message); }
public void initialise() { logWrapper.Info("Initialise network model update service"); numberOfNetworkModelRetries = MAX_NUMBER_OF_NETWORK_MODEL_RETRIES; updateNetworkModel(null, null); }
public override void ExceptionCaught(IChannelHandlerContext ctx, Exception e) { //异常,关闭连接 LogWrapper.Info($"{nameof(MessageHandler)} {e.Message}\n{e.StackTrace}"); ctx.CloseAsync(); }
protected override void ChannelRead0(IChannelHandlerContext ctx, IMessage msg) { LogWrapper.Info($"recv {msg.GetType()}"); }