i would log my data with NLog and MongoDB. I configured my NLog.config like this:
<extensions>
<add assembly="NLog.Mongo"/>
</extensions>
...
<target xsi:type="Mongo"
name="mongo"
includeDefaults="false"
connectionString="mongodb://localhost"
collectionName="myCollection"
databaseName="logs"
cappedCollectionSize="26214400">
<field name="_id" layout="${Id}"/>
<field name="ts" layout="${Timestamp}" bsonType="DateTime"/>
<field name="cap" layout="${ApplicationCaller}" />
</target>
But how can i pass value ID, Timestamp, ApplicationCaller in my log??
I try this code:
public void LogExceptionOnMongo(string callIdentifier, string applicationCaller)
{
var _myLogger = LogManager.GetLogger("mongo");
var logEventInfo = new LogEventInfo(LogLevel.Fatal, "", "Exception");
logEventInfo.Properties["CallIdentifier"] = callIdentifier;
logEventInfo.Properties["TimeStamp"] = DateTime.UtcNow;
logEventInfo.Properties["ApplicationCaller"] = applicationCaller;
_myLogger.Log(logEventInfo);
}
and this configuration:
<target xsi:type="Mongo"
name="mongo"
includeDefaults="false"
connectionString="mongodb://localhost"
collectionName="myCollection"
databaseName="logs"
cappedCollectionSize="26214400">
<field name="_id" layout="${event-properties:item=CallIdentifier}"/>
<field name="ts" layout="${event-properties:item=TimeStamp}" bsonType="DateTimeUtc"/>
<field name="cap" layout="${event-properties:item=ApplicationCaller}" />
</target>
But i obtain this log in mongo (I don't wont circled data):
Please can anyone help me?? Thank you and sorry for my English
There would have to be a code change to accommodate this. See Issue for more information.
New property includeEventProperties can now be configured:
<target xsi:type="Mongo"
name="mongo"
includeDefaults="false"
includeEventProperties="false"
connectionString="mongodb://localhost"
collectionName="myCollection"
databaseName="logs"
cappedCollectionSize="26214400">
<field name="_id" layout="${event-properties:item=CallIdentifier}"/>
<field name="ts" layout="${event-properties:item=TimeStamp}" bsonType="DateTimeUtc"/>
<field name="cap" layout="${event-properties:item=ApplicationCaller}" />
</target>
Just use ver. 4.6.0.68 from nuget: https://www.nuget.org/packages/NLog.Mongo
This morning i have tried use the new version of library, this is the new configuration:
<target xsi:type="Mongo"
name="mongo"
includeDefaults="false"
connectionString="mongodb://localhost"
collectionName="myCollection"
databaseName="logs"
cappedCollectionSize="26214400"
includeEventProperties="false">
<field name="_id" layout="${event-properties:item=CallIdentifier}"/>
<field name="ts" layout="${event-properties:item=TimeStamp}" bsonType="DateTime"/>
<field name="cap" layout="${event-properties:item=ApplicationCaller}" />
</target>
with new tag includeEventProperties=false and with its new property in the class MongoTarget and it works fine. This is the result:
Thank you so much, great job
Related
I have the following NLOG target in the config file :
<target xsi:type="File" name="communicationTarget" fileName="${basedir}/logs/${shortdate}.log">
<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="10">
<attribute name="message" layout="${message}" />
</layout>
</target>
Is there any way to read the maxRecursionLimit from C# code?
I have tried these :
LogManager.Configuration.AllTargets.Where(c => c.Name == "communicationTarget").FirstOrDefault();
LogManager.Configuration.FindTargetByName<FileTarget>("communicationTarget");
No maxRecursionLimit found so far.
Maybe something like this:
var myTarget = LogManager.Configuration.FindTargetByName("communicationTarget");
var myTarget = ((myTarget as NLog.Targets.Wrappers.WrapperTargetBase)?.WrappedTarget) ?? myTarget;
var jsonLayout = (myTarget as NLog.Targets.TargetWithLayout)?.Layout as NLog.Layouts.JsonLayout;
var maxRecursionLimit = jsonLayout?.MaxRecursionLimit;
This will also handle that you should activate <targets async="true">.
P.S. Have not tried to compile the code :)
Our tack is c# .net 4.7 logging through NLog library to a "Graylog" GELF input which of course is storing them in an elasticsearch cluster.
The application utilizes logging heavily, but EVERYTHING is sent through as strings - no matter if it was something other than a string in code.
I want to be able send my custom logger properties as their true data types so that I can aggregate on my statistical number fields.
I DO NOT want to constrain my developers and do this with scripted fields, or pre-mapping an index in elasticsearch - in fact, graylog manages my index for me. Nor do I want to utilize graylog pipeline processor - my poor graylog does enough work. I want them to be able to send stat data as their real data types and have them mapped as "long" or "number".
A code snippet from my stuff:
public void InfoExtended2(String Message, Dictionary<string, int> extrafields, [CallerMemberName] string callerMethodName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
var fileName = callerFilePath.Substring(callerFilePath.LastIndexOf(#"\") + 1).Replace(".cs", "");
var caller = $"{fileName}.{callerMethodName}()Line:{sourceLineNumber}";
var logger = LogManager.GetLogger(caller);
if (!(extrafields.Count == 0))
{
foreach (var field in extrafields)
{
string mykey = field.Key.ToString();
extrafields.TryGetValue(field.Key, out int myvalue);
//be careful whats in object!
if (!logger.Properties.ContainsKey(mykey)) { logger.Properties.Add(mykey, "{#myvalue}"); } else { logger.Properties[mykey] = "{#myvalue}"; }
}
}
logger.Info()
.Message(Message)
.Property("ComeOnNow3", 87)
.Write();
// Create the LogEventInfo object
//LogEventInfo logEvent = new LogEventInfo();
// Now add the event characteristics
//logEvent.Properties["EventCode"] = 2222;
//logEvent.Level = NLog.LogLevel.Info;
//logEvent.Properties["EventCode]."]
//logEvent.Message = "My Message";
////logEvent.Exception = ex;
//logger.Log(logEvent);
//logger.Info("{#Message}", new Dictionary<string, int> { { "key1", 1 }, { "key2", 2 } }); // dict. Result: Test "key1"=1, "key2"=2
}
I've tried a few different ways there with no luck.
If I make a POST GELF call myself with JSON fields representing ints instead of strings, it works. My field is brand new to the index and when I go check the mapping it comes back as a long. I want my code to do that.
Test GELF Call:
{
"version": "1.1",
"host": "example.org",
"short_message": "A short message that helps you identify what is going on",
"full_message": "Backtrace here\n\nmore stuff",
"timestamp": 1385053862.3072,
"level": 1,
"_user_id": 9001,
"_some_info": "foo",
"_some_env_var": "bar"
}
Resulting mapping for user id:
"user_id" : {
"type" : "long"
What our nlog target currently looks like:
<targets>
<target name="gelftcp"
type="gelftcp"
facility="Custom Facility"
remoteaddress="192.168.95.15"
remoteport="12201"
layout="${longdate}${newline}type: ${level:uppercase=true}${newline}class: ${logger}${newline}stacktrace: ${stacktrace}${newline}error message: ${message}${newline}exception: ${exception:format=tostring,data:maxinnerexceptionlevel=10}">
<parameter name="logged_at" layout="${longdate}" />
<parameter name="type" layout="${level:uppercase=true}" />
<parameter name="class" layout="${logger}" />
<parameter name="CustomInt" layout="${event-properties:item=CustomInt}" as="number" />
<parameter name="stacktrace" layout="${stacktrace}" />
<parameter name="error_message" layout="${message}" />
<parameter name="ComeOnNow3" layout="${event-properties:item=ComeOnNow3} " />
<parameter name="exception" layout="${exception:format=tostring,data:maxinnerexceptionlevel=10}" />
<attribute name="eventProperties" encode="false" >
<layout type='JsonLayout' includeAllProperties="true" maxRecursionLimit="2"/>
</attribute>
<variable name="ComeOnNow2" value ="${event-context:ComeOnNow2}" />
</target>
Take it easy on me, I'm not the original author of this code. Just someone tasked with picking up slack & deploying in its current state.
UPDATE:
Tried the first suggestion. Even added the field I'm testing:
<field name="ComeOnNow3" layout="${threadid}" type="System.Int32" />
Attempted this log entry:
logger.Info()
.Message(Message)
.Property("ComeOnNow3", 87)
.Write();
My mapping still comes back as "keyword".
SOLVED:
The trick was to switch to Http instead of Tcp.
Instead of using "gelftcp". Then you can try out GelfLayout instead:
https://www.nuget.org/packages/NLog.GelfLayout
You can combine it with the TCP network-target:
<nlog>
<extensions>
<add assembly="NLog.Layouts.GelfLayout" />
</extensions>
<targets async="true">
<target type="Network" name="gelftcp" address="tcp://192.168.95.15:12201" newLine="true" lineEnding="Null">
<layout type="GelfLayout" facility="MyFacility">
<field name="threadid" layout="${threadid}" type="System.Int32" />
</layout>
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="gelftcp" />
</rules>
</nlog>
It also has some automatic conversion logic for simple NLog LogEventInfo.Properties (Decimal + Double + Integer + Boolean)
More examples can be found here: https://github.com/farzadpanahi/NLog.GelfLayout
here is my code
regXmppClient.SetUsername("abcd");
regXmppClient.SetXmppDomain("abcd.com");
regXmppClient.Password = "abcd";
regXmppClient.RegisterNewAccount = true;
regXmppClient.Open();
regXmppClient.OnRegister += new EventHandler<Matrix.EventArgs>(xmppCon_OnRegister);
regXmppClient.OnRegisterInformation +=
new EventHandler<Matrix.Xmpp.Register.RegisterEventArgs>(xmppCon_OnRegisterInformation);
regXmppClient.OnRegisterError += new EventHandler<Matrix.Xmpp.Client.IqEventArgs>(xmppCon_OnRegisterError);
XMl Error log
<iq type="error" id="MX_2" from="abcd.com" to="abcd.com/55ce2afc" xmlns="jabber:client">
<query xmlns="jabber:iq:register">
<username>abcd</username>
<password>abcd</password>
<email />
<name />
<x xmlns="jabber:x:data" type="form">
<title>XMPP Client Registration</title>
<instructions>Please provide the following information</instructions>
<field var="FORM_TYPE" type="hidden">
<value>jabber:iq:register</value>
</field>
<field var="username" type="text-single" label="Username">
<required />
</field>
<field var="name" type="text-single" label="Full name" />
<field var="email" type="text-single" label="Email" />
<field var="password" type="text-private" label="Password">
<required />
</field>
</x>
</query>
<error code="400" type="modify">
<jid-malformed xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
</error>
</iq>
I got solution finally, I can Register new account using XmppClientConnection
_xmppConnection.Server = SERVER_NAME;
_xmppConnection.ConnectServer = SERVER_NAME;
_xmppConnection.Username = objxmppData.UserName;
_xmppConnection.Password = objxmppData.password;
**_xmppConnection.RegisterAccount = true;**
_xmppConnection.Open();
_xmppConnection.OnAuthError += loginFailed;
_xmppConnection.OnLogin += new ObjectHandler(xmpp_OnLogin);
As in above code make RegisterAccount = true will do both create new account and loggedin with the same.
you code submits a xdata from and the old jabber style fields , , and . Some servers have problems with that, and I guess they are right.
If you want to use old jabber style registration then remove the xdata from in your set query. If you want to use xdata then remove the old jabber style fields.
see also: http://forum.ag-software.net/thread/874-How-to-Register-a-new-Account-on-an-xmpp-server
I've created a list (sharepoint 2010) that contains a cumstom field. The custom field inherits from SPFieldUser.
After I created a new ListItem (webfrontend) and have a look on the elements details the field is empty.
Webfronted NewItemForm
Webfronted ItemDetailsForm
Webfronted EditItemForm
My Code:
public class Vertreter_FieldType:SPFieldUser
{
public Vertreter_FieldType(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{
}
public Vertreter_FieldType(SPFieldCollection fields, string typeName, string fieldName)
: base(fields, typeName, fieldName)
{
}
public override object GetFieldValue(string value)
{
return base.GetFieldValue(value);
}
public override string DefaultValue
{
get
{
return base.DefaultValue;
}
set
{
base.DefaultValue = value;
}
}
}
XML-fldtypes:
<FieldTypes>
<FieldType>
<Field Name="TypeName">Vertreter_FieldType</Field>
<Field Name="ParentType">User</Field>
<Field Name="TypeDisplayName">Vertreter</Field>
<Field Name="TypeShortDescription">Auswahl Vertreter</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="FieldTypeClass">CustomFieldTypes.Vertreter_FieldType, $SharePoint.Project.AssemblyFullName$</Field>
</FieldType>
</FieldTypes>
My Contenttype the List bases on:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
...
<Field ID="{2C338272-3BC8-45bc-B33E-5FBD1223F398}"
DisplayName="Administrator" Name="Administrator"
Type="Admin_FieldType" Required="TRUE"
UnlimitedLengthInDocumentLibrary="FALSE"
/>
<Field ID="{585CE72A-72D7-4ecc-8324-484BA1E483F1}"
DisplayName="Vertreter" Name="Vertreter"
Type="Vertreter_FieldType" Required="TRUE"
UnlimitedLengthInDocumentLibrary="FALSE"
>
</Field>
...
<FieldRefs>
...
<FieldRef ID="{2C338272-3BC8-45bc-B33E-5FBD1223F398}" Name="Administrator" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE" />
<FieldRef ID="{585CE72A-72D7-4ecc-8324-484BA1E483F1}" Name="Vertreter" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE" />
...
</FieldRefs>
</ContentType>
</Elements>
My environment: sharepoint 2010, visualstudio 2010
Thanks for your help!
Found the solution: I had to add List="UserInfo" to the FieldDefinition.
<Field ID="{585CE72A-72D7-4ecc-8324-484BA1E483F1}" DisplayName="Vertreter" Name="Vertreter" Type="Vertreter_FieldType" Required="TRUE" UnlimitedLengthInDocumentLibrary="FALSE" List="UserInfo">
I'm trying to implement an MSDN tutorial to create an activity library for Sharepoint Designer, and it gives me this error:
Namespace1.CreateTaskInListOnSite' does not contain a definition for 'ListName' and no extension method 'ListName' accepting a ...
and the same for AssignedTo and 'SiteUrl`.
Shouldn't 'AssignedTo', 'ListName' and 'SiteUrl' be inherited members from SequenceActivity class?
Here is the code which is erred:
protected override ActivityExecutionStatus
Execute(ActivityExecutionContext executionContext)
{
try
{
SPSite sitecollection = new SPSite(this.SiteUrl); //here
SPWeb web = sitecollection.OpenWeb();
SPUser user = web.Users[this.AssignTo[0].ToString()]; // here
SPList list = web.Lists[this.ListName]; // and here
SPListItem item = list.Items.Add();
item["Title"] = this.TaskTitle;
item["AssignedTo"] = user;
item.Update();
}
catch (Exception ex)
{
EventLog.WriteEntry("MSDN Workflow", ex.ToString());
}
return ActivityExecutionStatus.Closed;
}
Here is the .actions file:
<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="Create Task in List On Site"
ClassName="Namespace1.CreateTaskInListOnSite"
Assembly="CustomWorkflowActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"
AppliesTo="all" Category="Cross Site Actions">
<RuleDesigner
Sentence="Create task titled %1 for %2 on site %3 in
list %4">
<FieldBind Field="TaskTitle" DesignerType="TextArea"
Id="1"/>
<FieldBind Field="AssignTo" DesignerType="Person"
Text="this user" Id="2"/>
<FieldBind Field="SiteUrl" DesignerType="TextArea" Id="3"/>
<FieldBind Field="ListName" DesignerType="TextArea" Id="4"/>
</RuleDesigner>
<Parameters>
<Parameter Name="TaskTitle" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="AssignTo" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="SiteUrl" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="ListName" Type="System.String, mscorlib"
Direction="In" />
</Parameters>
</Action>
The .ACTIONS file calls the ClassName as MSDN.HowTo.CreateTaskInListOnSite, where as in your code file you seem to use the namespace Namespace1. The two have to match.
So either you change .ACTIONS to this:
<Action Name="Create Task in List On Site"
ClassName="MSDN.HowTo.CreateTaskInListOnSite" .... />
or change the namespace definition in your code file to MSDN.HowTo.
The assembly attribute values also have to be correct. You can use the sn.exe tool to retrieve the public key token for your assembly.