We are in need to add performance monitoring to our application.
For the prototype I've created a sample project, which I'm trying to get into work.
I'm trying to use policyInjection for the performance counters, so we'll be able to turn on and off the performance monitoring in the production environment.
So far I can see the actual category in perfmon, but I cannot see any instances (see image), even I'm pretty sure the application is running and instance exists, as you can see in attached sources.
I've tried a lot of things, also googled around, but didn't find any usable solution or clue what to look for.
Application is created as consoleApplication
You can also download a zipped project for VS here:
http://dl.dropbox.com/u/19457132/stackOverflow/Mpd.Instrumentation.PerformanceCounter.zip
Here are my sources.
Program.cs
using System;
using System.Collections;
using System.Configuration.Install;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Installers;
namespace Mpd.Instrumentation.PerformanceCounter
{
class Program
{
static void Main(string[] args)
{
//RemoveCounters();
InstallCounters();
MyCounters myCounter = PolicyInjection.Create<MyCounters>();
for (int i = 0; i < 100000000; i++)
{
myCounter.SampleMethod(i);
}
Console.ReadLine();
}
public static void InstallCounters()
{
PerformanceCountersInstaller installer = new PerformanceCountersInstaller(new SystemConfigurationSource());
IDictionary state = new Hashtable();
installer.Context = new InstallContext();
installer.Install(state);
installer.Commit(state);
Console.WriteLine("Performance counters have been successfully installed. Press enter to continue");
Console.ReadLine();
}
private static void RemoveCounters()
{
PerformanceCountersInstaller installer = new PerformanceCountersInstaller(new SystemConfigurationSource());
installer.Context = new InstallContext();
installer.Uninstall(null);
Console.WriteLine("Performance counters have been successfully removed. Press enter to continue.");
Console.ReadLine();
}
}
}
MyCounters.cs
using System;
using System.Threading;
namespace Mpd.Instrumentation.PerformanceCounter
{
public class MyCounters : IPerformanceCounter
{
public void SampleMethod(int i)
{
Console.WriteLine(i);
Thread.Sleep(50);
}
}
}
IPerformanceCounter.cs
using System;
namespace Mpd.Instrumentation.PerformanceCounter
{
public class IPerformanceCounter : MarshalByRefObject
{
}
}
And finally app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" />
<section name="instrumentationConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation.Configuration.InstrumentationConfigurationSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" />
</configSections>
<policyInjection>
<policies>
<add name="SampleCountersPolicy">
<matchingRules>
<add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MethodSignatureMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
match="SampleMethod" ignoreCase="true" name="Method Signature Matching Rule" />
</matchingRules>
<handlers>
<add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.PerformanceCounterCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
categoryName=".aaaTest" instanceName="Default" useTotalCounter="true"
incrementNumberOfCalls="true" incrementCallsPerSecond="true"
incrementAverageCallDuration="true" incrementTotalExceptions="true"
incrementExceptionsPerSecond="true" order="1" name="Performance Counter Call Handler" />
</handlers>
</add>
</policies>
</policyInjection>
<instrumentationConfiguration performanceCountersEnabled="true"
applicationInstanceName="Default" />
</configuration>
Since the SampleMethod accepts a parameter you need to add that to the matching rules configuration:
<matchingRules>
<add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MethodSignatureMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
match="SampleMethod" ignoreCase="true" name="Method Signature Matching Rule">
<parameters>
<parameter name="i" typeName="System.Int32" />
</parameters>
</add>
</matchingRules>
Without the parameter the matching rule does not match so the call handler is not invoked. If you modify the configuration you should see the instances in perfmon.
Related
i can't figure out what i do wrong.
My project is like that :
MainProject
SubProject (referencing my desires DLL)
I have my app.config (of MainProject) :
<configuration>
<configSections>
<section name="DirectoryServerConfiguration" type="System.Configuration.NameValueSectionHandler"/>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
<section name="GeneralConfiguration" type="System.Configuration.NameValueSectionHandler"/>
<section name="ServerConnectionConfiguration" type="System.Configuration.NameValueSectionHandler"/>
<section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings,Microsoft.Practices.EnterpriseLibrary.Caching"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="ReferencesDLL" />
</assemblyBinding>
</runtime>
<GeneralConfiguration configSource="ConfigFiles\GeneralConfiguration.config"/>
<cachingConfiguration configSource="ConfigFiles\cachingConfiguration.config"/>
<DirectoryServerConfiguration configSource="ConfigFiles\YPAdress.config"/>
<log4net configSource="ConfigFiles\log4net.config"/>
</configuration>
And my compile repository is like that :
Debug
ConfigFiles\ (All the .config files defined in the app.config)
ReferencesDLL\ (All the Dll needed by SubProject)
(All the others compiled files : .exe, .dll, etc..)
As you can see, i have my privatePath define, but when running the app, it can't find the needed dll for SubProject. (no problem for the .config files)
I don't know what i did wrong :( .
You could manually look for the assembly at the known location using an AppDomain.AssemblyResolve event handler:
static void Run()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
// Do work...
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var dllName = new AssemblyName(args.Name).Name + ".dll";
var assemblyPath = Assembly.GetExecutingAssembly().Location;
var referenceDirectory = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(assemblyPath), "ReferencesDLL"));
if (!referenceDirectory.Exists)
return null; // Can't find the reference directory
var assemblyFile = referenceDirectory.EnumerateFiles(dllName, SearchOption.TopDirectoryOnly).FirstOrDefault();
if (assemblyFile == null)
return null; // Can't find a matching dll
return Assembly.LoadFrom(assemblyFile.FullName);
}
I am trying to save user settings in C# and reuse them in the next session.
All over the net, one finds tipps like this:
How to save user settings programatically?
I have a .setting file in my project with the default settings.
When a user changes a setting, I call save, and in %APPDATA% the file appears, with the user settings.
It looks like this:
private void SetSetting(string prop, Object val)
{
try
{
string strval = String.Format("G{0}_{1}", Group_Id, prop);
Properties.Last.Default[strval] = val;
}
catch
{
System.Configuration.SettingsProperty property = new System.Configuration.SettingsProperty(String.Format("G{0}_{1}", Group_Id, prop));
property.PropertyType = Properties.Def.Default[String.Format("G0_{1}", Group_Id, prop)].GetType();
property.DefaultValue = Properties.Def.Default[String.Format("G0_{1}", Group_Id, prop)];
property.PropertyType = val.GetType();
property.Provider = Properties.Last.Default.Providers["LocalFileSettingsProvider"];
property.Attributes.Add(typeof(System.Configuration.UserScopedSettingAttribute), new System.Configuration.UserScopedSettingAttribute());
Properties.Last.Default.Properties.Add(property);
Properties.Last.Default.Reload();
string strval = String.Format("G{0}_{1}", Group_Id, prop);
Properties.Last.Default[strval] = val;
}
Properties.Last.Default.Save();
}
As you can see, I have the settings instance Last as in "settings from last session" and Def as in default.
Basically, a user can add and delete groups at will in the app. Def holds the default configuration for a new group. Last should hold the number of groups in the last user session, as well as the properties of each group. Thus the formatting with the Group_Id and so on.
So, as I said. During runtime, its fine. User settings are properly written to the file in %APPDATA% and everything.
The file is like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5629387e089" >
<section name="Project1.Properties.Last" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5629387e089" " allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<Project1.Properties.Last>
<setting name="G1_do_cut" serializeAs="String">
<value>True</value>
</setting>
</Project1.Properties.Last>
</userSettings>
</configuration>
So, the setting for do_cut for Group 1 is saved as G1_do_cut
But as soon as I restart the application, the user setting is ignored.
The code used is:
private Object GetSetting(string prop)
{
try { return Properties.Last.Default[String.Format("G{0}_{1}", Group_Id, prop)]; }
catch { return Properties.Def.Default[String.Format("G0_{1}", Group_Id, prop)]; }
}
and in the try, an exception G1_do_cut is not found in settings is thrown and the catch loads the default.
During a user session, the GetSettings works correctly - if I try to read G1_do_cut after it has been set, no exception is thrown and I get the correct value.
How do I get C# to reuse the settings after restarting the application?
I want to set a cache limit for my C# program. My program is creating files periodically and saving them to a folder. I want it so if the folder (C:\SysApp) hits this limit (150000KB) it will automatically start deleting the files starting with the oldest ones deleting only a certain amount at a time (149900KB).
So far I have this code:
private void DeleteOldFilesIfOverFolderLimit(string folderPath,
long folderSizeLimit,
long amountToDelete)
{
var folder = new DirectoryInfo(folderPath);
var files = folder.GetFiles();
var folderSize = files.Sum(fi => fi.Length);
if (folderSize > folderSizeLimit)
{
// Sort the list of files with the oldest first.
Array.Sort(files,
(fi1, fi2) => fi1.CreationTime.CompareTo(fi2.CreationTime));
var amountDeleted = 0L;
foreach (var file in files)
{
amountDeleted += file.Length;
file.Delete();
if (amountDeleted >= amountToDelete)
{
break;
}
}
}
}
I'm just trying to figure out where I need to insert the specific data for my program (given in first paragraph in parenthesis).
I'm using Visual Studio Community 2015.
Click on the project options and select settings:
Enter the default values
and your program can read these values (from the .settings file or the defaults) using the following code
static void Main(string[] args)
{
string folder=Properties.Settings.Default.folder;
long limit=Properties.Settings.Default.sizeLimit;
long delete=Properties.Settings.Default.toDelete;
}
If you change the settings value in the program you need to save the new values before exiting the application. This is done with Properties.Settings.Default.Save();. This command creates a .config file with your values. These are read automatically when the program starts.
The contents are an XML file with the settings values clearly visible.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="SO_KeepStettings.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<SO_KeepStettings.Properties.Settings>
<setting name="folder" serializeAs="String">
<value>C:\SysApp</value>
</setting>
<setting name="sizeLimit" serializeAs="String">
<value>157286400</value>
</setting>
<setting name="toDelete" serializeAs="String">
<value>156237824</value>
</setting>
</SO_KeepStettings.Properties.Settings>
</userSettings>
</configuration>
Deleting files is sketchy, if you accidentally pass in a malformed string or simply the wrong string then you will be losing data, such as accidentally deleting your only copy of your PhD thesis or destroying your operating system. So, I'm just going to show you how to call a method instead of showing you how to use this code you were given:
Starting with a Hello World! example:
public class Hello1
{
public static void Main()
{
System.Console.WriteLine("Hello, World!");
// This is here only to pause the console window so it stays open.
System.Console.ReadLine();
}
}
Now let's implement our own method to print any string to the console:
public class Hello1
{
public static void Main()
{
PrintToConsole("Hello World!");
// This is here only to pause the console window so it stays open.
System.Console.ReadLine();
}
private static void PrintToConsole(string stringToPrintToConsole)
{
System.Console.WriteLine(stringToPrintToConsole);
}
}
Lastly, let's pass in another parameter to control how many times the line is printed:
public class Hello1
{
public static void Main()
{
PrintToConsole("Hello World!", 5);
// This is here only to pause the console window so it stays open.
System.Console.ReadLine();
}
private static void PrintToConsole(string stringToPrintToConsole, long numberOfTimesToPrint)
{
for (int i = 0; i < numberOfTimesToPrint; i++)
{
System.Console.WriteLine(stringToPrintToConsole);
}
}
}
You were given a method but no where are you calling that method. Note how in my program I have to call PrintToConsole() somewhere, and this being a console application the entire program starts and finishes in Main() so that is where I put the code. You could technically take the body of your method and paste it directly into Main, then everywhere you see the usage of the variable folderPath you replace it with the actual string "C:\\SysApp" and likewise with the other 2 parameters and the program would work the same.
I'm attempting to implement my first go-around of reading custom configuration elements from an ASP.NET web.config file. It seems pretty simple to me, yet I'm receiving a run-time `Property is not a ConfigurationElement' error. Here's my code:
The web.config file sections:
<?xml version="1.0" encoding="utf-8" ?>...
<configuration>
...
<section name="appConfig" type="ParticipationManagement.AppConfig" allowDefinition="Everywhere" allowLocation="true" requirePermission="false" />
</configSections>
...
<appConfig>
<startRecertVFC>2/15</startRecertVFC>
</appConfig>
</configuration>
The handler:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web;
namespace ParticipationManagement
{
public class AppConfig : ConfigurationSection
{
[ConfigurationProperty("startRecertVFC", IsRequired = false)]
public DateTime RecertVFCStart
{
get
{
string start = (string)this["startRecertVFC"];
string year = DateTime.Now.Year.ToString();
DateTime start_date;
if (DateTime.TryParse(start + "/" + year, out start_date))
{
return start_date;
}
else
{
return DateTime.Today;
}
}
set
{
this["startRecertVFC"] = value;
}
}
}
}
And my invocation in page code:
protected void Page_Init(object sender, EventArgs e)
{
...
AppConfig config = (AppConfig)System.Configuration.ConfigurationManager.GetSection("appConfig");
RecertVFCStart = config.RecertVFCStart;
}
Seems very clean and straight-forward to me, but I'm getting that troubling error at runtime and I cannot narrow it down since I have no experience with this.
Sorry in advance: I see plenty of other posts about this but all seem to address more advanced/complex issues than what I'm trying to accomplish, which is nothing more than embedding a few app-specific values in an external file...
Change your config setting like an example shown below
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="appConfig" type="ParticipationManagement.AppConfig" allowDefinition="Everywhere" allowLocation="true" requirePermission="false"/>
</configSections>
<appConfig startRecertVFC="5/1/2015 8:30:52 AM" />
</configuration>
Try to make the following change in AppConfig file
string start = this["startRecertVFC"].ToString();
Let us know if this solves your problem
I added a strongly-typed DataSet object to my project. It's type name is DocRetrieverDataSet.
I also have in my project settings a row for a user-scope DataSet property named DocRetrieverDataSource to which I want to save an instance of DocRetrieverDataSet.
Here is boiled-down code:
using Settings = MyProjectNameSpace.Properties.Settings;
....
private DocRetrieverDataSet myDocRetrieverDataSet;
public myForm()
{
Initialize();
if (Settings.Default.DocRetrieverDataSource == null)
{
Settings.Default.DocRetrieverDataSource = new DocRetrieverDataSet();
Settings.Default.Save();
}
this.myDocRetrieverDataSet = (DocRetrieverDataSet)Settings.Default.DocRetrieverDataSource;
}
The first time I run it, when Settings.Default.DocRetrieverDataSource is null, it works fine! However, when I run it the second time, I get an InvalidCastException at
this.myDocRetrieverDataSet = (DocRetrieverDataSet)Settings.Default.DocRetrieverDataSource;
It says
Unable to cast object of type 'System.Data.DataSet' to type 'DocRetriever.DocRetrieverDataSet'.
The funny thing is that it doesn't have this problem the first time around. What is going on and how can I fix it?
MORE INFO:
Here's the relevant code from Settings.Designer.cs
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Data.DataSet DocRetrieverDataSource {
get {
return ((global::System.Data.DataSet)(this["DocRetrieverDataSource"]));
}
set {
this["DocRetrieverDataSource"] = value;
}
}
And from app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=abcdefghijkl" >
<section name="DocRetriever.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=abcdefghijkl" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<DocRetriever.Properties.Settings>
<setting name="SpoolDirectoryPath" serializeAs="String">
<value />
</setting>
<setting name="OutputDirectoryPath" serializeAs="String">
<value />
</setting>
</DocRetriever.Properties.Settings>
</userSettings>
</configuration>
You need to change the casting in your Settings file from DataSet to your DocRetrieverDataSet
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Data.DataSet DocRetrieverDataSource {
get {
return ((global::FullNamespace.DocRetrieverDataSet)(this["DocRetrieverDataSource"]));
}
set {
this["DocRetrieverDataSource"] = value;
}
}
You can also do it via the Settings Designer, just go to your property and browse for you class