I have a .NET 3.5 web application for which I have implemented a class called CalculationsCounterManager (code below). This class has some shared/static members that manage the creation and incrementing of two custom performance counters that monitor data calls to a SQL Server database. Execution of these data calls drives the creation of the counters if the don't exist. Of course, everything works fine through the unit tests that are executed through the nUnit GUI for this class. The counters are created and incremented fine.
However, when the same code executes through the ASPNET worker process, the following error message occurs: "Requested registry access is not allowed.". This error happens on line 44 in the CalculationsCounterManager class when a read is done to check if the counter category already exists.
Does anyone know a way to provide enough priveledges to the worker process account in order to allow it to create the counters in a production environment without opening the server up to security problems?
Thanks in advance!
Namespace eA.Analytics.DataLayer.PerformanceMetrics
''' <summary>
''' Manages performance counters for the calculatioins data layer assembly
''' </summary>
''' <remarks>GAJ 09/10/08 - Initial coding and testing</remarks>
Public Class CalculationCounterManager
Private Shared _AvgRetrieval As PerformanceCounter
Private Shared _TotalRequests As PerformanceCounter
Private Shared _ManagerInitialized As Boolean
Private Shared _SW As Stopwatch
''' <summary>
''' Creates/recreates the perf. counters if they don't exist
''' </summary>
''' <param name="recreate"></param>
''' <remarks></remarks>
Public Shared Sub SetupCalculationsCounters(ByVal recreate As Boolean)
If PerformanceCounterCategory.Exists(CollectionSettings.CalculationMetricsCollectionName) = False Or recreate = True Then
Dim AvgCalcsProductRetrieval As New CounterCreationData(CounterSettings.AvgProductRetrievalTimeCounterName, _
CounterSettings.AvgProductRetrievalTimeCounterHelp, _
CounterSettings.AvgProductRetrievalTimeCounterType)
Dim TotalCalcsProductRetrievalRequests As New CounterCreationData(CounterSettings.TotalRequestsCounterName, _
CounterSettings.AvgProductRetrievalTimeCounterHelp, _
CounterSettings.TotalRequestsCounterType)
Dim CounterData As New CounterCreationDataCollection()
' Add counters to the collection.
CounterData.Add(AvgCalcsProductRetrieval)
CounterData.Add(TotalCalcsProductRetrievalRequests)
If recreate = True Then
If PerformanceCounterCategory.Exists(CollectionSettings.CalculationMetricsCollectionName) = True Then
PerformanceCounterCategory.Delete(CollectionSettings.CalculationMetricsCollectionName)
End If
End If
If PerformanceCounterCategory.Exists(CollectionSettings.CalculationMetricsCollectionName) = False Then
PerformanceCounterCategory.Create(CollectionSettings.CalculationMetricsCollectionName, CollectionSettings.CalculationMetricsDescription, _
PerformanceCounterCategoryType.SingleInstance, CounterData)
End If
End If
_AvgRetrieval = New PerformanceCounter(CollectionSettings.CalculationMetricsCollectionName, CounterSettings.AvgProductRetrievalTimeCounterName, False)
_TotalRequests = New PerformanceCounter(CollectionSettings.CalculationMetricsCollectionName, CounterSettings.TotalRequestsCounterName, False)
_ManagerInitialized = True
End Sub
Public Shared ReadOnly Property CategoryName() As String
Get
Return CollectionSettings.CalculationMetricsCollectionName
End Get
End Property
''' <summary>
''' Determines if the performance counters have been initialized
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Shared ReadOnly Property ManagerInitializaed() As Boolean
Get
Return _ManagerInitialized
End Get
End Property
Public Shared ReadOnly Property AvgRetrieval() As PerformanceCounter
Get
Return _AvgRetrieval
End Get
End Property
Public Shared ReadOnly Property TotalRequests() As PerformanceCounter
Get
Return _TotalRequests
End Get
End Property
''' <summary>
''' Initializes the Average Retrieval Time counter by starting a stopwatch
''' </summary>
''' <remarks></remarks>
Public Shared Sub BeginIncrementAvgRetrieval()
If _SW Is Nothing Then
_SW = New Stopwatch
End If
_SW.Start()
End Sub
''' <summary>
''' Increments the Average Retrieval Time counter by stopping the stopwatch and changing the
''' raw value of the perf counter.
''' </summary>
''' <remarks></remarks>
Public Shared Sub EndIncrementAvgRetrieval(ByVal resetStopwatch As Boolean, ByVal outputToTrace As Boolean)
_SW.Stop()
_AvgRetrieval.RawValue = CLng(_SW.ElapsedMilliseconds)
If outPutToTrace = True Then
Trace.WriteLine(_AvgRetrieval.NextValue.ToString)
End If
If resetStopwatch = True Then
_SW.Reset()
End If
End Sub
''' <summary>
''' Increments the total requests counter
''' </summary>
''' <remarks></remarks>
Public Shared Sub IncrementTotalRequests()
_TotalRequests.IncrementBy(1)
End Sub
Public Shared Sub DeleteAll()
If PerformanceCounterCategory.Exists(CollectionSettings.CalculationMetricsCollectionName) = True Then
PerformanceCounterCategory.Delete(CollectionSettings.CalculationMetricsCollectionName)
End If
End Sub
End Class
End Namespace
-
Yes, it’s not possible. You can’t add privileges to the worker process without opening the server up to potential security / DOS problems in a production environment. An installer (like a MSI) usually runs with elevated permissions, and installs / uninstalls the performance counter categories and counters as well as other locked down objects.
For example, Windows Installer XML (WiX) has support for Performance Counters...
From George Tsiokos
0 comments:
Post a Comment