Reading PerfMon Counters in T-SQL with CLR

A collegue of mine asked me if it is possible to read out PerfMon counters that are not in the sys.dm_os_performance_counters DMV. I searched everywhere but the only possibility I could think of is by using a CLR user defined function.

So I wrote an assembly (I'm still a VB programmer, I never bothered to learn C#. And I'm never going to as long as VB.Net exists J ):

 

The code is fairly simple:

Imports System

Imports System.Data

Imports System.Data.SqlClient

Imports System.Data.SqlTypes

Imports Microsoft.SqlServer.Server

 

Partial
Public
Class UserDefinedFunctions

    <Microsoft.SqlServer.Server.SqlFunction()> _

    Public
Shared
Function ReadPerfMonCounter(ByVal Category As
String, ByVal Counter As
String, ByVal Instance As
String) As SqlString

        '******************************************************************************

        '* Disclaimer: I'm a lousy programmer!!!!                                     *

        '* ****************************************************************************

 

        Dim sTemp As
String

        Try

            Dim perfCounter As
New System.Diagnostics.PerformanceCounter(Category, Counter, Instance, "localhost")

 

            'Somehow it won't return a result on the first NextValue call.

            'Never mind: we just call it 2 times :).

            sTemp = perfCounter.NextValue().ToString

 

            'And wait a little while, but now she's ready to go.

            Threading.Thread.Sleep(1000)

 

            Return
New SqlString(perfCounter.NextValue.ToString)

        Catch ex As Exception

            Return
New SqlString(ex.Message)

        End
Try

 

    End
Function

End
Class

 

The only problem I had was the problem that the NextValue method of the perfCounter didn't return anything but 0 on its first call. That's why I call it 2 times now.

Once compiled you can deploy this assembly on your server. If you don't have .Net but want the assembly, just mail me.

I deployed it to the AdventureWorksTest database, which is a copy of the regular AdventureWorks database.

 

If you deploy it make sure your database has TRUSTWORTHY ON because I didn't sign the assembly. This assembly needs unrestricted access. That's unsafe on SQL 2005.

 

When you have done all that you can use a select statement like:

SELECT
AdventureWorksTest.dbo.ReadPerfMonCounter('PhysicalDisk','% Idle Time','0 C: D: E:');

 

That's all. Error handling could be better by the way. When you make a typo in your counter you'll wait forever instead of getting an error.

If you don't like the unsafe setting on the assembly you could transfer that part to a class library and reference it from your .NET stored procedure. Plenty opportunities left….

I didn't bother on execution context and all that. On my machine the service account is a local admin. You might need some impersonification code if not.

 

Regards,

Menzo

Comments

  • Anonymous
    March 25, 2009
    PingBack from http://blog.a-foton.ru/index.php/2009/03/25/reading-perfmon-counters-in-t-sql-with-clr/

  • Anonymous
    April 14, 2009
    The comment has been removed

  • Anonymous
    April 14, 2009
    The comment has been removed

  • Anonymous
    April 15, 2009
    Dim perfCounter As New System.Diagnostics.PerformanceCounter(Category, Counter, Instance, ".") or System.Diagnostics.PerformanceCounter(Category, Counter, Instance, "localhost") shouldn't make much of a difference. On my system it runs (Win2008 Ent) but it could differ on other windows versions. Thanks for the tip!

  • Anonymous
    March 05, 2010
    The comment has been removed

  • Anonymous
    March 09, 2010
    The comment has been removed