我在现有组中创建新计数器时遇到一个奇怪的问题。我有一个Windows服务,它做了一些工作,并允许我通过性能计数器监视其状态。我有性能计数器组和一些性能计数器。在服务安装阶段(具有管理员权限)创建组,并在服务启动时初始化计数器(作为LocalSystem用户)。一切正常,组存在,计数器也存在,我可以监视它们并写入性能计数器日志。服务不断运行。
然后我想添加一些性能计数器。我将它们添加到服务代码中,通过卸载以前的服务实例(卸载代码删除性能计数器组)并重新安装服务来重建和部署到服务器(在安装阶段使用所有新计数器创建性能计数器组)。然后我开始服务。
这是故事中常见的,无趣的部分的结束。奇怪的事情从这里开始。
我转到PerMon,将所有计数器添加到系统监视器视图。我可以看到我的性能计数器组,我看到所有性能计数器,包括我刚刚添加的新性能计数器。我可以将它们添加到系统监视器视图。我可以看到,旧的计数器正在工作。但新计数器不起作用,它们不收集任何数据。好吧,好吧,也许是我的错误,我切换到日志视图并尝试记录性能计数器数据。旧计数器在记录之前记录。但是当我尝试添加新计数器时,我会在事件查看器中找到警告:
该服务无法将计数器'\ AGENT \ MyCountersGroupName \ MyNewCounter'添加到NewCountersLog日志或警报。此日志或警报将继续,但不会收集该计数器的数据。返回的错误是:找不到指定的计数器。
我尝试重新安装服务,删除旧计数器,再次添加它们,并且没有任何更改。旧计数器正在工作,新计数器不起作用。然后我重新启动Windows,新的计数器开始工作!服务没有任何改变,我刚刚重启了服务器。我在2台服务器上遇到此问题,两者都在Windows Server 2003 SP1下运行。所有性能计数器的代码都是相同的,因为我使用泛型代码创建它们。
你可以说“嘿,不要打扰,每当你需要添加新的性能计数器时重新启动Windows”,但我不能。我的服务与其他服务一起在服务器上运行,我们需要这些服务不断工作,每次更改一项服务时都无法重启服务器。
有人可以帮忙解决这个问题吗?
更新 看起来有类似的问题:https://stackoverflow.com/questions/2180005/adding-performance-counters-to-existing-category
更新 我不认为问题出在我的代码中,但是如果它有帮助我在这里发布它。
安装和卸载代码(在安装阶段调用): PerformanceCountersManagerBase.GetCreationData()是一个通用的包装器,用于获取数据集合以创建性能计数器。
public static void Install()
{
CounterCreationDataCollection counters = new CounterCreationDataCollection(
PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());
if (PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.
PerformanceCounterCategory.Create(PerformanceCountersManagerBase.GroupName,
"Group description",
PerformanceCounterCategoryType.SingleInstance, counters);
}
public static void Uninstall()
{
if (!PerformanceCounterCategory.Exists(PerformanceCountersManagerBase.GroupName))
return;
PerformanceCounterCategory.Delete(PerformanceCountersManagerBase.GroupName);
}
初始化服务和更新中的计数器的代码:
internal void Initialize(string name, string groupName)
{
_counter = new PerformanceCounter(groupName, name, false);
_counter.RawValue = 0;
}
internal void Increment()
{
if ((_counter == null) || _counter.ReadOnly)
return;
lock (_counter)
{
_counter.Increment();
}
}
更新3 我更改了代码以通过.NET组件PerformanceCounterInstaller安装计数器,并且没有任何更改。旧计数器在它们工作时工作,并且新创建的不起作用并尝试记录它们导致事件日志中的确切错误(警告)消息。安装程序创建代码如下:
public static PerformanceCounterInstaller GetInstaller()
{
PerformanceCounterGroupAttribute group
= PerformanceCountersManagerBase.ExtractGroupSettings(typeof(TManager));
PerformanceCounterInstaller installer = new PerformanceCounterInstaller();
installer.CategoryName = group.Name;
installer.CategoryHelp = group.Description;
installer.CategoryType = PerformanceCounterCategoryType.SingleInstance;
installer.UninstallAction = UninstallAction.Remove;
installer.Counters.AddRange(PerformanceCountersManagerBase.GetCreationData<TManager>().ToArray());
return installer;
}
答案 0 :(得分:12)
Perf计数器基于共享内存段。当有人仍然拥有共享内存段的句柄时,我已经看到了类似的问题。这可以包括perfmon工具本身。您可以使用handle实用程序查看谁持有共享内存。 您不应该需要重新启动,因此请尝试查看此问题是否消失,先关闭perfmon然后重新创建计数器。还要确保您的服务没有运行。
答案 1 :(得分:3)
在迈克回答之前,我自己处理了这个问题。但我没时间弄清问题的原因。我通过执行以下步骤解决了这个问题:
在这些步骤之后,新的性能计数器出现了。也许没有必要停止记录,但我现在没有时间检查它。我稍后再试。我接受迈克的答案是正确的,因为它指的是问题的原因。
答案 2 :(得分:1)
我有一个类似的情况,我为系统的不同部分创建了一些性能计数器,并将它们添加到字典中以便按名称直接访问,并且它们都写入了一个(任何一个的任何增量都会更新其余部分)。
令我惊讶的是,解决方案是关闭 性能监视器 Windows工具,然后创建计数器。问题是被锁定的二手共享内存。