{"id":31915469,"url":"https://github.com/stackify/stackify-api-dotnet","last_synced_at":"2025-10-13T19:47:29.361Z","repository":{"id":23089563,"uuid":"26443472","full_name":"stackify/stackify-api-dotnet","owner":"stackify","description":"Stackify API for .Net - Logs, Errors, Metrics - log4net, NLog","archived":false,"fork":false,"pushed_at":"2025-09-11T00:50:49.000Z","size":19961,"stargazers_count":58,"open_issues_count":10,"forks_count":32,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-09-13T07:37:14.019Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-11-10T15:56:17.000Z","updated_at":"2025-09-11T00:50:02.000Z","dependencies_parsed_at":"2024-02-05T21:26:31.154Z","dependency_job_id":"f942aa6b-8af6-4edd-a85c-02507f69120f","html_url":"https://github.com/stackify/stackify-api-dotnet","commit_stats":{"total_commits":304,"total_committers":40,"mean_commits":7.6,"dds":0.6776315789473684,"last_synced_commit":"cbac1237c6c6d78325f0e86d5804615cb85482b7"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/stackify/stackify-api-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackify%2Fstackify-api-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackify%2Fstackify-api-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackify%2Fstackify-api-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackify%2Fstackify-api-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackify","download_url":"https://codeload.github.com/stackify/stackify-api-dotnet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackify%2Fstackify-api-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279016839,"owners_count":26085889,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-13T19:47:27.377Z","updated_at":"2025-10-13T19:47:29.344Z","avatar_url":"https://github.com/stackify.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Stackify API for .NET\n\n[![Build status](https://ci.appveyor.com/api/projects/status/6suxse470ab4bdxl?svg=true)](https://ci.appveyor.com/project/jaredcnance/stackify-api-dotnet)\n[![NuGet](https://img.shields.io/nuget/v/StackifyLib.svg)](https://www.nuget.org/packages/StackifyLib/)\n\nLibrary for Stackify users to integrate Stackify in to their projects. Provides support for sending errors, logs, and custom metrics to Stackify. Also some support for querying metric data back out of Stackify for use in external projects.\n\n**Important links:**\n- [Stackify homepage](http://www.stackify.com)\n- [Stackify documentation site](https://docs.stackify.com/docs)\n- [NuGet packages](https://www.nuget.org/packages?q=Stackify)\n- [Supported .NET logging frameworks](https://docs.stackify.com/docs/errors-and-logs-net-supported-frameworks)\n- [Best practices for logging with C#](https://stackify.com/csharp-logging-best-practices/)\n- [Why you should use tags in your logs](https://stackify.com/get-smarter-log-management-with-log-tags/)\n- [Ultimate log4net Tutorial for .Net Logging](https://stackify.com/log4net-guide-dotnet-logging/)\n\n\n**Read me sections:**\n- [Basics](#basics)\n- [Errors \u0026 Logs](#errors-and-logs)\n- [StackifyLib NLog](#nlog)\n- [StackifyLib log4net 2.0+](#log4net-v20-v1211)\n- [StackifyLib log4net 1.2.10](#log4net-v1210)\n- [Direct API](#direct-api)\n- [Configuring with Azure service definitions](#configuring-with-azure-service-definitions)\n\n## Basics\n\nSeveral nuget packages are available for Stackify's core API as well as various logging frameworks. Please install the proper packages. All of the available packages for various logging frameworks are wrapper on top of StackifyLib which can also be used directly for logging. \n\nFeatures\n\n - Asynchronous logging framework for high performance\n - Automatic queueing and error fall back logic \n - Support for NLog, log4net, ELMAH, and direct API usage\n - Can be plugged in to custom built or other logging frameworks\n - Does not depend on the Stackify monitoring agent. All data is sent directly to Stackify.\n\nThe packages for log4net, NLog and Elmah all depend on StackifyLib. StackifyLib also has support for custom metrics and accessing some of Stackify's API to pull data back out.\n\nThe following is required in your App.config or Web.config:\n\n```xml\n\u003cappSettings\u003e\n        \u003cadd key=\"Stackify.ApiKey\" value=\"YOUR API KEY HERE\" /\u003e\n        \u003cadd key=\"Stackify.AppName\" value=\"YOUR APP NAME\" /\u003e\n        \u003cadd key=\"Stackify.Environment\" value=\"OPTIONAL ENVIRONMENT NAME LIKE PROD, DEV\" /\u003e\n\u003c/appSettings\u003e\n```\n\nOptionally, you can set the config settings on your machine's environment variables with the same configuration key and value.\n\tExample are executed in window's cmd as an admin:\n```\nsetx Stackify.ApiKey \"YOUR API KEY HERE\" /m\nsetx Stackify.Environment \"MY ENVIRONMENT HERE\" /m\n```\n\nYou can set the config settings in code like so which will override the appSettings configs as well.\n\n```\nStackifyLib.Logger.GlobalApiKey = \"\";\nStackifyLib.Logger.GlobalAppName = \"\";\nStackifyLib.Logger.GlobalEnvironment = \"\";\n```\n\nBy default the library will use the WebRequest.DefaultWebProxy. If you want to set a specific proxy server only for StackifyLib, you can do so in code OR via config.\n\nFor proxy using custom credentials:\n```xml\n\u003cappSettings\u003e\n        \u003cadd key=\"Stackify.ProxyServer\" value=\"http://test:test@172.19.1.1:8888/\" /\u003e\n\u003c/appSettings\u003e\n```\n\nFor proxy using default credentials:\n```xml\n\u003cappSettings\u003e\n        \u003cadd key=\"Stackify.ProxyUseDefaultCredentials\" value=\"true\" /\u003e\n\u003c/appSettings\u003e\n```\n\nFor proxy that needs to be tailor fit\n```csharp\nStackifyLib.Utils.HttpClient.CustomWebProxy = new WebProxy();\n```\n\nIn case it need some web request intervention, a delegate has been provided to customize the http request\n```csharp\nStackifyLib.Utils.HttpClient.CustomRequestModifier = (request) =\u003e\n{\n        // Examples:\n        request.PreAuthenticate = true; // If proxy needs pre-authentication\n        request.Timeout = 30000;\n};\n```\n\nIf you are having problems you can get logging out of the framework by hooking in to its custom logging.\n\n```csharp\nStackifyLib.Utils.StackifyAPILogger.LogEnabled = true;\nStackifyLib.Utils.StackifyAPILogger.OnLogMessage += StackifyAPILogger_OnLogMessage;\n\nstatic void StackifyAPILogger_OnLogMessage(string data)\n{\n        Debug.WriteLine(data);\n}\n```\n\n## Additional Settings\n\nThese settings are available to further customize what information is captured and transmitted to Stackify.\n\n```xml\n\u003cappSettings\u003e\n       \u003cadd key=\"Stackify.CaptureErrorHeaders\" value=\"true\" /\u003e\n       \u003cadd key=\"Stackify.CaptureServerVariables\" value=\"false\" /\u003e\n       \u003cadd key=\"Stackify.CaptureSessionVariables\" value=\"false\" /\u003e\n       \u003cadd key=\"Stackify.CaptureErrorCookies\" value=\"false\" /\u003e\n       \u003cadd key=\"Stackify.CaptureErrorUserName\" value=\"true\" /\u003e\n       \u003cadd key=\"Stackify.CaptureErrorPostdata\" value=\"false\" /\u003e\n\u003c/appSettings\u003e\n```\n\n\n## Errors and Logs\n\nIf you log an object with the message, Stackify's log viewer makes it easy to search by these parameters. You can always search by the text in the log message itself, but searching by the logged properties provides a lot more power. If you always logged a \"clientid\" for example on every log message, you could search in Stackify for \"json.clientid:1\" and quickly see all logs and errors affecting that specific client. Another big difference and advantage to logging objects is you can do a range type search \"json.clientid:[1 TO 10]\" which would not be possible by a straight text search.\n\n\n### NLog\n\n**Install via NuGet package**\n```\nPM\u003e Install-Package NLog.Targets.Stackify\n```\n\n**Sample config:**\n```xml\n\u003cnlog\u003e\n        \u003cextensions\u003e\n                \u003cadd assembly=\"NLog.Targets.Stackify\"/\u003e\n        \u003c/extensions\u003e\n        \u003ctargets\u003e\n                \u003ctarget name=\"stackify\" type=\"StackifyTarget\" logAllParams=\"false\"\u003e\n                        \u003ccontextproperty name=\"gdcKey1\" layout=\"${gdc:item=gdcKey1}\" /\u003e\n                        \u003ccontextproperty name=\"mdlcKey2\" layout=\"${mdlc:item=mdlcKey2}\" /\u003e\n                \u003c/target\u003e\n        \u003c/targets\u003e\n        \u003crules\u003e\n                \u003clogger name=\"*\" writeTo=\"stackify\" minlevel=\"Debug\" /\u003e\n        \u003c/rules\u003e\n\u003c/nlog\u003e\n```\n\n\nNLog 4.5 (and newer) supports message templates, where structured properties becomes searchable in Stackify's log viewer\n\n```csharp\nstatic NLog.Logger nlog = NLog.LogManager.GetCurrentClassLogger();\nnLog.Debug(\"{clientid} chose {color}\", 1, \"red\");\n```\n\nLogging custom objects are also supported and will be searchable in Stackify's log viewer\n\n```csharp\nstatic NLog.Logger nlog = NLog.LogManager.GetCurrentClassLogger();\nDictionary\u003cstring, object\u003e dictionary = new Dictionary\u003cstring, object\u003e();\ndictionary[\"clientid\"] = 1;\ndictionary[\"color\"] = \"red\";\nnlog.Debug(\"Test message\", dictionary);\n\nnlog.Debug(\"Test message\", new { clientid = 2, color = \"blue\" });\n```\n\n**Options:**\n\n- IncludeEventProperties - Include LogEvent-Properties for structured logging.\n- IncludeMdlc - Include NLog MappedDiagnosticsLogicalContext MDLC-Properties for structured logging.\n- IncludeCallSite - Include LogEvent CallSite so method names will show up in the StackifyLog viewer (Replaces old property logMethodNames)\n- logLastParameter - Serialize the last parameter provided with the LogEvent.\n- logAllParams - Serialize all the parameters provided with the LogEvent (arg0, arg1, etc.)\n- GlobalContextKeys - Comma delimited list of keys for NLog GDC. !OBSOLETE! Instead use contextproperty-Layout as shown in sample config above.\n- MappedContextKeys - Comma delimited list of keys for NLog MDC. !OBSOLETE! Instead use contextproperty-Layout as shown in sample config above.\n- CallContextKeys - Comma delimited list of keys for use with CallContext.LogicalSetData(key, value). Research LogicalSetData online to learn more. !OBSOLETE! Instead use contextproperty-Layout as shown in sample config above. \n\n### log4net v2.0+ (v1.2.11+)\n\n**Install via NuGet package**\n```\nPM\u003e Install-Package StackifyLib.log4net\n```\n\nNote: Nuget packages are compiled against 2.0.0 (1.2.11) but any newer version will work with a valid assembly binding redirect. log4net 2.0.3 is actually 1.2.13 which makes the binding redirect look strange.\n\n```xml\n\u003cdependentAssembly\u003e\n        \u003cassemblyIdentity name=\"log4net\" publicKeyToken=\"669e0ddf0bb1aa2a\" culture=\"neutral\" /\u003e\n        \u003cbindingRedirect oldVersion=\"1.2.11.0-1.2.13.0\" newVersion=\"1.2.13.0\" /\u003e\n\u003c/dependentAssembly\u003e\n```\n\n**Sample config:**\n```xml\n\u003clog4net\u003e\n        \u003croot\u003e\n                \u003clevel value=\"DEBUG\" /\u003e\n                \u003cappender-ref ref=\"StackifyAppender\" /\u003e\n        \u003c/root\u003e\n        \u003cappender name=\"StackifyAppender\" type=\"StackifyLib.log4net.StackifyAppender, StackifyLib.log4net\"\u003e\n                \u003cglobalContextKeys\u003eexamplekey1,key2\u003c/globalContextKeys\u003e\n                \u003cthreadContextKeys\u003e\u003c/threadContextKeys\u003e\n                \u003clogicalThreadContextKeys\u003e\u003c/logicalThreadContextKeys\u003e\n\n                \u003ccallContextKeys\u003e\u003c/callContextKeys\u003e\n\n                \u003c!-- If logging a very high rate of messages, disable logging method names for performance --\u003e\n                \u003clogMethodNames\u003etrue\u003c/logMethodNames\u003e\n\n                \u003c!-- Only log errors and fatals by using filters and setting levelMin and levelMax appropriately --\u003e\n                \u003c!-- http://logging.apache.org/log4net/release/manual/configuration.html --\u003e\n                \u003cfilter type=\"log4net.Filter.LevelRangeFilter\"\u003e\n                        \u003clevelMin value=\"DEBUG\" /\u003e\n                        \u003clevelMax value=\"FATAL\" /\u003e\n                \u003c/filter\u003e\n        \u003c/appender\u003e\n\u003c/log4net\u003e\n```\n\n**Options:**\n\n- GlobalContext, ThreadContext, and LogicalThreadContext keys are fully supported by setting the parameters in the config as a comma delimited list of keys. See sample config above.\n- CallContextKeys is an additional feature unrelated to log4net that uses the local thread storage for more advanced tracking of context variables. LogicalThreadContext provides the same functionality but uses an internal property collection. We have seen instances where the serialization of that collection can cause exceptions. This was created as an alternative method to the built in function. It is used via CallContext.LogicalSetData(key, value). Research LogicalSetData online to learn more. It is supposed to work better across child Task objects and with async.\n- logMethodNames - Method names will show up in the StackifyLog viewer most of the time as the class name that did the logging. For exceptions it will usually show the method name. To enable the exact method name for all logging, set this property to true. Note that it does cause a small performance hit due to walking the StackTrace.\n\n\n#### log4net Extension Methods\n\nlog4net does not internally have methods for logging a log message along with an object. Stackify's appenders work fine if you log an object directly or we have created some friendly extension methods to make it easy to log an object with your message at the same time.\n\n```csharp\nusing StackifyLib; //extension methods are here\nstatic log4net.ILog logger = log4net.LogManager.GetLogger(typeof(Program));\nDictionary\u003cstring, object\u003e dictionary = new Dictionary\u003cstring, object\u003e();\ndictionary[\"clientid\"] = 1;\ndictionary[\"name\"] = \"process name\";\nlogger.Debug(\"Starting some process for client 1\"); //Normal basic log message works fine\nlogger.Debug(dictionary); //This works fine and is indexed and searchable by Stackify \nlogger.Debug(\"Starting some process for client 1\", dictionary); //extension method\n```\n\n### log4net v1.2.10\n\n**Install via NuGet package**\n```\nPM\u003e Install-Package StackifyLib.log4net.v1_2_10\n```\n\nNote: If you use 1.2.10 then you must use our special nuget package for that version. There is no way to use an assembly redirect because the public key of log4net v1 and v2 are different. Everything else is the same about using log4net with Stackify.\n\n\n### Direct API\n\n**Install via NuGet package**\n```\nPM\u003e Install-Package StackifyLib\n```\n\nIf you use a custom logging framework or a framework not currently supported, you can easily send logs to Stackify with our core library and API like so:\n\n```csharp\nStackifyLib.Logger.Queue(\"DEBUG\", \"My log message\");\nStackifyLib.Logger.QueueException(\"Test exception\", new ApplicationException(\"Sky is falling\"));\n\nStackifyLib.Logger.Shutdown(); //should be called before your app closes to flush the log queue\n        \n//More advanced example\nLogMsg msg = new LogMsg();\nmsg.Ex = StackifyError.New(new ApplicationException(\"Exception goes here\"));\nmsg.AppDetails = new LogMsgGroup() {AppName = \"My app\", Env = \"Prod\", ServerName = Environment.MachineName};\nmsg.data = StackifyLib.Utils.HelperFunctions.SerializeDebugData(new { color= \"red\"}, true);\nmsg.Msg = \"My log message\";\nmsg.Level = \"ERROR\";\nStackifyLib.Logger.QueueLogObject(msg);\n```\n\n*Make sure you call StackifyLib.Logger.Shutdown() before your app ends to flush the queue*\n\n### Configuring with Azure service definitions\n\nStackifyLib reads the license key, app name, and environment settings from normal web.config appSettings. If you would prefer to store the settings in an [azure cloud deployment cscfg](http://msdn.microsoft.com/en-us/library/azure/hh369931.aspx#NameValue), then you can create a little code to read the settings from there and set the StackifyLib settings in code like this in some similar way.\n\n```csharp\npublic class MvcApplication : System.Web.HttpApplication\n{\n        public override void Init()\n        {\n                base.Init();\n                StackifyLib.Logger.GlobalApiKey = GetConfig(\"Stackify.ApiKey\");\n                StackifyLib.Logger.GlobalEnvironment = GetConfig(\"Stackify.Environment\");\n                StackifyLib.Logger.GlobalAppName = \"My App Name\"; //probably no reason to make this one configurable\n        }\n}\n\npublic static string GetConfig(string configName)\n{\n        //Doing an if here in case it's being used outside of azure emulator.\n        //Do this however works best for your project\n        try\n        {\n        if (RoleEnvironment.IsAvailable)\n        {\n                return RoleEnvironment.GetConfigurationSettingValue(configName);\n        }\n        else\n        {\n                return ConfigurationManager.AppSettings[configName];\n        }\n        }\n        catch (Exception ex)\n        {\n        }\n        return null;\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackify%2Fstackify-api-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackify%2Fstackify-api-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackify%2Fstackify-api-dotnet/lists"}