Nlog direct access working but not PostSharp default - postsharp

I'm new in learning about how PostSharp works. I've written some code using NLog that I want to improve using PostSharp.
The Nlog output is working (output is done both on console & file).
The PostSharp isn't working at all (no output to file, no output console).
I tried to follow to documentation from PostSharp website : https://doc.postsharp.net/nlog
I don't understand where my mistake is :(
Can somebody give me a little hand to solve this problem ?
Thanks for help.
using System;
using PostSharp.Patterns.Diagnostics;
using PostSharp.Patterns.Diagnostics.Backends.NLog;
using NLog.Config;
using NLog.Targets;
using System.Text;
using NLog;
using LogLevel = PostSharp.Patterns.Diagnostics.LogLevel;
using static PostSharp.Patterns.Diagnostics.FormattedMessageBuilder;
namespace MyNameSpace
{
static class LogSources
{
// Configure a prototype LogSource that you will reuse in several classes.
public static readonly LogSource Default = LogSource.Get().WithLevels(LogLevel.Trace, LogLevel.Warning);
}
/// <summary>
/// Main class
/// </summary>
[Log]
class Program
{
static LoggingConfiguration config;
static readonly LogSource logSource = LogSource.Get().WithLevels(LogLevel.Trace, LogLevel.Warning);
/// <summary>
/// MAIN ENTRY
/// </summary>
static void Main()
{
InitNLog(Environment.ExpandEnvironmentVariables (#"%TEMP%\MyLog.txt"));
InitPostSharp();
LogMe();
logSource.Default.Write (Formatted("This is a TEST message"));
NLog.LogManager.GetCurrentClassLogger().Trace("This is a Trace message");
NLog.LogManager.GetCurrentClassLogger().Debug("This is a Debug message");
NLog.LogManager.GetCurrentClassLogger().Info("This is an Info message");
NLog.LogManager.GetCurrentClassLogger().Warn("This is a Warn message");
NLog.LogManager.GetCurrentClassLogger().Error("This is an Error message");
NLog.LogManager.GetCurrentClassLogger().Fatal("This is a Fatal error message");
Console.ReadKey();
}
[Log]
public static void LogMe()
{
logSource.Default.Write(Formatted("pleassseee loggggg meeeee"));
}
/// <summary>
/// Initializes PostSharp.
/// </summary>
private static void InitPostSharp()
{
LoggingServices.DefaultBackend = new NLogLoggingBackend(new LogFactory(config));
}
/// <summary>
/// Init NLog system
/// </summary>
/// <param name="outputFileName">Full path for output logging file.</param>
static void InitNLog(string outputFileName)
{
// NLOG CONFIGURATION - https://github.com/NLog/NLog/wiki/Tutorial
// Step 1. Create configuration object
config = new LoggingConfiguration();
// Step 2. Create targets and add them to the configuration
ColoredConsoleTarget consoleTarget = new ColoredConsoleTarget();
consoleTarget.Layout = #"${date:universalTime=true:format=HH\:mm\:ss.fff} ${message} ${exception:format=Message}";
consoleTarget.UseDefaultRowHighlightingRules = false;
consoleTarget.RowHighlightingRules.Clear();
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Trace and starts-with('${message}','[THREAD:')", ConsoleOutputColor.Cyan, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Trace", ConsoleOutputColor.DarkCyan, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Debug", ConsoleOutputColor.DarkGray, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Info", ConsoleOutputColor.White, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Warn", ConsoleOutputColor.Yellow, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Error", ConsoleOutputColor.Red, ConsoleOutputColor.Black));
consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level >= LogLevel.Fatal", ConsoleOutputColor.White, ConsoleOutputColor.DarkRed));
consoleTarget.Encoding = Encoding.Unicode;
config.AddTarget("console", consoleTarget);
FileTarget fileTarget = new FileTarget();
config.AddTarget("file", fileTarget);
fileTarget.FileName = outputFileName;
// Step 3. Set target properties
consoleTarget.Layout = "${logger}|${message}";
fileTarget.Layout = "${machinename}|${longdate}|${logger}|${level:uppercase=true}|${message}|${exception:separator=\r\n:format=message,type,method,stackTrace:maxInnerExceptionLevel=10:innerExceptionSeparator=\r\n:innerFormat=message,type,method,stackTrace}";
// Step 4. Define rules
config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Trace, consoleTarget));
config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Trace, fileTarget));
// Step 5. Activate the configuration
LogManager.Configuration = config;
LogManager.EnableLogging();
}
}
}

PostSharp only logs methods annotated with [Log] and it only starts logging after you set the backend, which you did in InitPostSharp.
If you add to your class Program the following method:
[Log]
public static void LogMe()
{
}
and call LogMe() from Main after InitPostSharp, it will be logged into NLog.
A problem with your code is also this line:
[Log(AttributeExclude=true)] which means "remove logging" (because of the AttributeExclude). If you instead use simply [Log], the attribute will multicast down on all methods of the class, including LogMe. Still, methods calls that started before you set up the backend in InitPostSharp will not be affected.

Related

Using serilog with .NET MAUI

I have a very simple .NET MAUI app (not a Blazor one). I've installed Seriolog and Serilog.Extensions.Logging (so I can use AppCenter). I have the following in my startup code to initialise Serilog
public static MauiApp CreateMauiApp()
{
// set up logging
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
path = Path.Combine(path, "debugcode.txt");
Log.Logger = new LoggerConfiguration()
//.MinimumLevel.Debug()
.WriteTo.File(path)
.WriteTo.AppCenterCrashes(restrictedToMinimumLevel: LogEventLevel.Information)
.WriteTo.Console()
.CreateLogger();
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.Logging.AddSerilog(Log.Logger);
return builder.Build();
}
This compiles without an issue. I've added into the main.xaml.cs the code for logging (the code is just the default .NET MAUI test app shipped with VisualStudio). The minimum debug line is commented out, but it makes no difference if it's not commented out.
protected override void OnDisappearing()
{
base.OnDisappearing();
Log.CloseAndFlush();
}
void OnCounterClicked(object sender, EventArgs e)
{
count++;
var nums = $"Current count: {count}";
CounterLabel.Text = nums;
Log.Debug($"***** Current count: {nums}");
SemanticScreenReader.Announce(CounterLabel.Text);
}
I have tried changing the debug level, but no matter what, nothing is showing in the console for the debug information.
Here is a working example:
Install These nuget packages:
Serilog
Serilog.Extensions.Logging
Serilog.Sinks.File
Code:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
SetupSerilog();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
builder.Services.AddMauiBlazorWebView();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
#endif
builder.Logging.AddSerilog(dispose: true);
return builder.Build();
}
private static void SetupSerilog()
{
var flushInterval = new TimeSpan(0, 0, 1);
var file = Path.Combine(FileSystem.AppDataDirectory, "MyApp.log");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File(file, flushToDiskInterval: flushInterval, encoding: System.Text.Encoding.UTF8, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 22)
.CreateLogger();
}
Adding Serilog.Sinks.Xamarin and calling .WriteTo.AndroidLog() in LoggerConfiguration works. For iOS, I think that .WriteTo.NSLog() should work too.
A couple points.
Make sure you include using Serilog; in the classes that write to the log e.g. Log.Debug($"***** Current count: {nums}");
If writing to the AndroidLog, use Tools -> Android -> Device Log. Make sure your LoggerConfiguration includes something you can filter on, such as specifying the Source.
.WriteTo.AndroidLog()
.Enrich.WithProperty(Serilog.Core.Constants.SourceContextPropertyName, ".yourappname")
It's a good idea to also add Serilog.Sinks.Debug to your project and add .WriteTo.Debug() to your LoggerConfiguration.

Eclipse Marking std namespace as 'could not be resolved'

I am having issues with setting up Eclipse CDT to correctly do development in C++11. It's highlighting std::error_code and honestly everything in the std namespace. While the application compiles just fine on the command line.
Screen shot included.
The full project can be found on github.com/rbaindourov/OpenWeatherMapDSLink including the hidden files used by Eclipse.
I can host the the OVA of the virtual machine if you like as well.
Thanks in advance to any industrious individual who is willing to take the time to help me configure Eclipse CDT correctly.
And apologies if my question is not to your liking.
The source for the main.cpp file originally came from:
https://github.com/CiscoDevNet/kinetic-efm-cpp-sdk/blob/master/efm-cpp-sdk-1.0.15-Ubuntu16.04-dslink-dev/examples/simple_responder/main.cpp
// #copyright_start
// Copyright (c) 2019 Cisco and/or its affiliates. All rights reserved.
// #copyright_end
#include <efm_link.h>
#include <efm_link_options.h>
#include <efm_logging.h>
#include "error_code.h"
#include <iostream>
#include <random>
#include <sstream>
/// #brief The simple responder link example demonstrates the EFM SDK API for responder implementations. Shows node,
/// action creation, and stream handling.
class SimpleResponderLink
{
public:
/// Constructs the responder link implementation.
/// #param link The link to work with.
SimpleResponderLink(cisco::efm_sdk::Link& link)
: link_(link)
, responder_(link.responder())
{
}
/// The initialize callback that will be called as soon as the initialization including serialization is complete.
/// Will create the first level node hierarchy. Only nodes not created by the deserialization will actually be
/// created.
/// #param link_name The name of the link.
/// #param ec The error code will be set to an error if the initialization failed.
void initialize(const std::string& link_name, const std::error_code& ec)
{
if (!ec) {
LOG_EFM_DEBUG(
"SimpleResponderLink", cisco::efm_sdk::DebugLevel::l1, "Responder link '" << link_name << "' initialized");
} else {
LOG_EFM_ERROR(ec, "could not initialize responder link");
}
cisco::efm_sdk::NodeBuilder builder{"/"};
builder.make_node("sdk version")
.display_name("SDK Version")
.type(cisco::efm_sdk::ValueType::String)
.value(link_.get_version_info());
builder.make_node("text")
.display_name("String")
.type(cisco::efm_sdk::ValueType::String)
.value("Hello, World!")
.writable(
cisco::efm_sdk::Writable::Write, std::bind(&::SimpleResponderLink::set_text, this, std::placeholders::_1))
.on_subscribe(std::bind(&::SimpleResponderLink::on_subscribe_text, this, std::placeholders::_1));
builder.make_node("set_text")
.display_name("Set Text")
.action(cisco::efm_sdk::Action(
cisco::efm_sdk::PermissionLevel::Read,
std::bind(
&SimpleResponderLink::set_text_called,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4))
.add_param(cisco::efm_sdk::ActionParameter{"String", cisco::efm_sdk::ValueType::String})
.add_column({"Success", cisco::efm_sdk::ValueType::Bool})
.add_column({"Message", cisco::efm_sdk::ValueType::String}));
responder_.add_node(
std::move(builder),
std::bind(&SimpleResponderLink::nodes_created, this, std::placeholders::_1, std::placeholders::_2));
}
/// Callback that will be called upon construction of the first level nodes.
/// #param paths The paths of the nodes that were actually created. A path that was added to the NodeBuilder is
/// not part of the paths vector means that the node was already created. Normally, there is no need to check for
/// the presence of a path. If the error code signals no error, just continue with your work.
/// #param ec The error code will be set to an error if the node creation failed.
void nodes_created(const std::vector<cisco::efm_sdk::NodePath>& paths, const std::error_code& ec)
{
if (!ec) {
LOG_EFM_DEBUG("SimpleResponderLink", cisco::efm_sdk::DebugLevel::l1, "created nodes");
for (const auto& path : paths) {
LOG_EFM_DEBUG("SimpleResponderLink", cisco::efm_sdk::DebugLevel::l2, "created path - " << path);
}
}
}
/// Called every time the link connects to the broker.
/// Will set the value on the '/text' path.
/// #param ec The error code will be set to an error if the connect failed.
void connected(const std::error_code& ec)
{
if (!ec) {
disconnected_ = false;
LOG_EFM_INFO(responder_error_code::connected);
responder_.set_value(text_path_, cisco::efm_sdk::Variant{"Hello, World!"}, [](const std::error_code&) {});
}
}
/// Called every time the link is disconnected from the broker.
/// Will set a flag to signal the disconnected status.
/// #param ec The error code will be set to an error if the disconnect failed.
void disconnected(const std::error_code& ec)
{
LOG_EFM_INFO(responder_error_code::disconnected, ec.message());
disconnected_ = true;
}
/// Will be called the node '/text' is set via an \#set action.
/// #param value The value that was set.
void set_text(const cisco::efm_sdk::Variant& value)
{
LOG_EFM_INFO(responder_error_code::set_text, value);
}
/// Action callback for the '/set_text' action. Will set the value of the path '/text' to the given one. It will also
/// echo back the set parameter.
/// The stream will be closed automatically by the link.
/// #param stream The stream to add a result to.
/// #param parent_path The path of the node the action was called for.
/// #param params The parameters set by the peer.
/// #param ec The error code will be set to an error if the action failed.
void set_text_called(
const cisco::efm_sdk::MutableActionResultStreamPtr& stream,
const cisco::efm_sdk::NodePath& parent_path,
const cisco::efm_sdk::Variant& params,
const std::error_code& ec)
{
(void)parent_path;
if (!ec) {
LOG_EFM_DEBUG("SimpleResponderLink", cisco::efm_sdk::DebugLevel::l3, "set_text_called");
const auto* input = params.get("String");
if (input) {
auto text = *input;
responder_.set_value(text_path_, text, [stream, text](const std::error_code& ec) {
if (!ec) {
stream->set_result(cisco::efm_sdk::UniqueActionResultPtr{new cisco::efm_sdk::ActionValuesResult{
cisco::efm_sdk::ActionValuesResult(cisco::efm_sdk::ActionSuccess).add_value(true).add_value(text)}});
} else {
stream->set_result(cisco::efm_sdk::UniqueActionResultPtr{
new cisco::efm_sdk::ActionValuesResult{cisco::efm_sdk::ActionValuesResult(cisco::efm_sdk::ActionError)
.add_value(false)
.add_value("Could not set value")}});
}
});
return;
}
}
stream->set_result(cisco::efm_sdk::UniqueActionResultPtr{
new cisco::efm_sdk::ActionValuesResult{cisco::efm_sdk::ActionValuesResult(cisco::efm_sdk::ActionError)
.add_value(false)
.add_value("Could not set value")}});
}
/// Will be called if a subscribe or unsubscribe is issued for the '/text' node.
/// #param subscribe True if a subscribe was done or false if an unsubscribe was done.
void on_subscribe_text(bool subscribe)
{
if (subscribe) {
LOG_EFM_INFO(responder_error_code::subscribed_text);
} else {
LOG_EFM_INFO(responder_error_code::unsubscribed_text);
}
}
private:
cisco::efm_sdk::Link& link_;
cisco::efm_sdk::Responder& responder_;
cisco::efm_sdk::NodePath text_path_{"/text"};
bool disconnected_{true};
};
int main(int argc, char* argv[])
{
cisco::efm_sdk::FileConfigLoader loader;
cisco::efm_sdk::LinkOptions options("Simple-Responder-Link", loader);
if (!options.parse(argc, argv, std::cerr)) {
return EXIT_FAILURE;
}
cisco::efm_sdk::Link link(std::move(options), cisco::efm_sdk::LinkType::Responder);
LOG_EFM_INFO(::responder_error_code::build_with_version, link.get_version_info());
SimpleResponderLink responder_link(link);
link.set_on_initialized_handler(
std::bind(&SimpleResponderLink::initialize, &responder_link, std::placeholders::_1, std::placeholders::_2));
link.set_on_connected_handler(std::bind(&SimpleResponderLink::connected, &responder_link, std::placeholders::_1));
link.set_on_disconnected_handler(
std::bind(&SimpleResponderLink::disconnected, &responder_link, std::placeholders::_1));
link.run();
return EXIT_SUCCESS;
}

Running Selenium via NUnit and Cruise Control .NET

I'm having an issue running Selenium tests in NUnit from Cruise Control .NET. I have a simple test that runs fine when I run from the NUnit GUI on our continuous integration server. However when the NUnit test is run from Cruise Control .NET on the same server, the test always fails. Tests that don't use Selenium run fine from both the NUnit GUI and from Cruise Control.
[SetUp]
public void SetupTest()
{
Driver = new InternetExplorerDriver();
}
[TearDown]
public void TeardownTest()
{
Driver.Quit();
}
/// <summary>
/// Test basic Selenium functionality.
/// </summary>
[Test]
public void SeleniumTest()
{
Driver.Navigate().GoToUrl(TestConfig.TestURL);
IWebElement testEle = WaitForElement(Driver, By.Id, "body", TestConfig.TestWaitMS);
Assert.IsTrue(true);
}
private static IWebElement WaitForElement(IWebDriver driver, ByFunc byFunc, string elementId, int waitMs,
string waitOutput = null, int pause = 50)
{
bool elementFound = false;
int i = 0;
IWebElement webElement = null;
while (!elementFound && (i * pause) < waitMs)
{
try
{
webElement = driver.FindElement(byFunc(elementId));
elementFound = true;
}
catch (NoSuchElementException)
{
i++;
Thread.Sleep(pause);
if (waitOutput != null)
Console.Write(waitOutput);
}
}
if (elementFound)
return webElement;
else
throw new NoSuchElementException(string.Format("Could not find element {0} after waiting {1}ms.", elementId, waitMs));
}
WaitForElement is just a helper function that allows me to assign specific waits for certain elements rather than have a blanket waiting time for the entire test run.
The test fails when the NoSuchElementException is raised from the WaitForElement function.
I've found some links on Google saying that you need to run SeleniumRC as a service to get it to run from Cruise Control. I don't think that applies here as I'm using the WebDriver version. Please correct me if I'm wrong.
IE version 8
Cruise Control .NET 1.8.3.0
NUnit 2.6
Selenium 2.0.0
Thanks for the pointers #Arran. Switching to a Firefox driver fixed the issue. I guess the fault must lie somewhere in the Internet Explorer driver.
[SetUp]
public void SetupTest()
{
Driver = new FirefoxDriver();
}

Test Event expiration in Drools Fusion CEP

Ciao, I have tested in several ways, but I'm still unable to test and verify the Event expiration mechanism in Drools Fusion, so I'm looking for some little guidance, please?
I've read the manual and I'm interested in this feature:
In other words, one an event is inserted into the working memory, it is possible for the engine to find out when an event can no longer match other facts and automatically retract it, releasing its associated resources.
I'm using the Drools IDE in Eclipse, 5.4.0.Final and I modified the template code created by the "New Drools Project" wizard to test and verify for Event expiration.
The code below. The way I understood to make the "lifecycle" to work correctly is that:
You must setup the KBase in STREAM mode - check
You must Insert the Events in temporal order - check
You must define temporal constraints between Events - check in my case is last Message()
However, when I inspect the EventFactHandle at the end, none of the Event() has expired.
Thanks for your help.
Java:
public class DroolsTest {
public static final void main(String[] args) {
try {
KnowledgeBase kbase = readKnowledgeBase();
// I do want the pseudo clock
KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
conf.setOption(ClockTypeOption.get("pseudo"));
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(conf, null);
SessionPseudoClock clock = ksession.getSessionClock();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// Insert of 2 Event:
Message message = new Message();
message.setMessage("Message 1");
message.setStatus(Message.HELLO);
ksession.insert(message);
ksession.fireAllRules();
clock.advanceTime(1, TimeUnit.DAYS);
Message message2 = new Message();
message2.setMessage("Message 2");
message2.setStatus(Message.HELLO);
ksession.insert(message2);
ksession.fireAllRules();
clock.advanceTime(1, TimeUnit.DAYS);
ksession.fireAllRules();
// Now I do check what I have in the working memory and if EventFactHandle if it's expired or not:
for (FactHandle f : ksession.getFactHandles()) {
if (f instanceof EventFactHandle) {
System.out.println(((EventFactHandle)f)+" "+((EventFactHandle)f).isExpired());
} else {
System.out.println("not an Event: "+f);
}
}
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
// following 2 lines is the template code modified for STREAM configuration
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption( EventProcessingOption.STREAM );
return kbase;
}
/*
* This is OK from template, as from the doc:
* By default, the timestamp for a given event is read from the Session Clock and assigned to the event at the time the event is inserted into the working memory.
*/
public static class Message {
public static final int HELLO = 0;
public static final int GOODBYE = 1;
private String message;
private int status;
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public int getStatus() {
return this.status;
}
public void setStatus(int status) {
this.status = status;
}
}
}
Drools:
package com.sample
import com.sample.DroolsTest.Message;
declare Message
#role(event)
end
declare window LastMessageWindow
Message() over window:length(1)
end
rule "Hello World"
when
accumulate( $m : Message(status==Message.HELLO) from window LastMessageWindow,
$messages : collectList( $m ) )
then
System.out.println( ((Message)$messages.get(0)).getMessage() );
end
Please note: even if I add expiration of 1second to the Message event, by
#expires(1s)
I still don't get the expected result that the very first Message event inserted, I would have expected is now expired? Thanks for your help.
Found solution! Obviously it was me being stupid and not realizing I was using Drools 5.4.0.Final while still referring to old documentation of 5.2.0.Final. In the updated documentation for Drools Fusion 5.4.0.Final, this box is added for 2.6.2. Sliding Length Windows:
Please note that length based windows do not define temporal constraints for event expiration from the session, and the engine will not consider them. If events have no other rules defining temporal constraints and no explicit expiration policy, the engine will keep them in the session indefinitely.
Therefore the 3rd requirement I originally enlisted of "You must define temporal constraints between Events" is obviously NOT met because I now understand Sliding Length Window in Drools 5.4.0.Final:
Message() over window:length(1)
are indeed NOT a definition of a temporal constraints for event expiration from the session.
Updating this answer hopefully somebody will find it helpful. Also, just so for your know, me being stupid actually for relying on googling in order to reach the doc, and sometimes you don't get redirected to the current release documentation, so it seems...

Reset performance counter from command line

I want to execute a command from command line to reset given performance counter to 0.
I could write a simple "3" lines console app to do that, but wondering if VS or Windows or Windows SDK already comes with such utility. I did not find such option in either typeperf or logman.
Context:
Windows 7 x64 (with Admin access)
Background:
I use a performance counter to debug/develop/stress-test a web service. Web service increments a performance counter every time it is hit.
So the scenario is to hit web service 10000 times and verify no messages have been lost (I test MSMQ + out-of-order processing + persistence + Windows Workflow Service)
While I'm waiting for a better answer, here is a complete "rstpc.exe" utility to reset performance counter (of NumberOfItems32 type):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ResetPerformanceCounter
{
internal class Program
{
private static int Main(string[] args)
{
if (args.Length != 2)
{
string fileName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
Console.WriteLine("Usage: {0} <PC Category> <PC Name>", fileName);
Console.WriteLine("Examlpe: {0} {1} {2}", fileName, "GEF", "CommandCount");
return -1;
}
string cat = args[0];
string name = args[1];
if (!PerformanceCounterCategory.CounterExists(name, cat))
{
Console.WriteLine("Performance Counter {0}\\{1} not found.", cat, name);
return - 2;
}
var pc = new System.Diagnostics.PerformanceCounter(cat, name, false);
if (pc.CounterType != PerformanceCounterType.NumberOfItems32)
{
Console.WriteLine("Performance counter is of type {0}. Only '{1}' countres are supported.", pc.CounterType.ToString(), PerformanceCounterType.NumberOfItems32);
return -3;
}
Console.WriteLine("Old value: {0}", pc.RawValue);
pc.RawValue = 0;
Console.WriteLine("New value: {0}", pc.RawValue);
Console.WriteLine("Done.");
return 0;
}
}
}