如何在NLog MongoDB配置中动态指定集合名与运行时修改数据库名
Alright, let's break down how to solve both of your requirements for NLog's MongoDB target. I've worked through similar scenarios before, so here's a practical approach:
1. Using a Variable for collectionName
NLog lets you use layout renderers or configuration variables to make collectionName dynamic. This is straightforward since the Mongo target supports layout values for this property.
Option 1: Use a Configuration Variable
Define a variable in your NLog config, then reference it in the target:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="true"> <!-- Define your collection name variable --> <variable name="LogCollection" value="DefaultLogDocument" /> <extensions> <add assembly="NLog.Mongo" /> </extensions> <targets async="true"> <target xsi:type="Mongo" name="mongoCustom" includeDefaults="false" connectionString="mongodb://mongodb0.example.com:27017" databaseName="logDb" <!-- Reference the variable here --> collectionName="${var:LogCollection}" cappedCollectionSize="26214400"> <field name="Date" layout="${longdate}" bsonType="DateTime" /> <field name="Level" layout="${level}"/> <field name="Message" layout="${message}" /> <field name="Logger" layout="${logger}"/> <field name="Location" layout="${callsite:className=true:methodName=true}" /> <field name="Exception" layout="${exception:format=tostring}" /> <field name="ThreadId" layout="${threadid}" bsonType="Int32" /> <field name="ThreadName" layout="${threadname}" /> <field name="ProcessId" layout="${processid}" bsonType="Int32" /> <field name="ProcessName" layout="${processname:fullName=true}" /> </target> </targets> <rules> <logger name="*" minlevel="Warn" writeTo="mongoCustom" /> </rules> </nlog>
Option 2: Dynamic Collection Name (e.g., Date-Based)
For more flexibility, you can use a layout renderer directly to generate collection names on the fly (like daily collections):
collectionName="Log_${date:format=yyyyMMdd}"
This creates a new collection each day (e.g., Log_20240520).
2. Dynamically Change databaseName at Runtime
Unlike collectionName, databaseName isn't always layout-compatible in older NLog.Mongo versions. The most reliable way is to update the target's property directly in code and reconfigure NLog.
Step 1: Update the Target in Code
Since your target is wrapped in an AsyncTargetWrapper, you'll need to access the underlying MongoTarget first:
// Get the async wrapper target var asyncWrapper = LogManager.Configuration.FindTargetByName<AsyncTargetWrapper>("mongoCustom"); // Extract the actual Mongo target from the wrapper var mongoTarget = asyncWrapper.WrappedTarget as MongoTarget; if (mongoTarget != null) { // Update to your desired database name mongoTarget.DatabaseName = "newLogDb"; // Apply changes to all existing loggers LogManager.ReconfigExistingLoggers(); }
If your target isn't async, skip the wrapper step:
var mongoTarget = LogManager.Configuration.FindTargetByName<MongoTarget>("mongoCustom"); if (mongoTarget != null) { mongoTarget.DatabaseName = "newLogDb"; LogManager.ReconfigExistingLoggers(); }
Option 2: Per-Context Database Name (Advanced)
If you need to switch databases based on request or logical context, use NLog's Mapped Diagnostics Logical Context (MDLC) (requires a recent NLog.Mongo version that supports layout for databaseName):
- Update the config to use MDLC:
databaseName="${mdlc:item=CurrentDatabase:default=logDb}"
- Set the database name in your code when needed (e.g., at the start of a request):
// Assign database name for the current logical context MappedDiagnosticsLogicalContext.Set("CurrentDatabase", "userSpecificDb");
This routes logs to the specified database for all events in that context (works seamlessly with async/await).
Key Notes
- Ensure you're using a recent version of NLog.Mongo to support these features.
- If
autoReload="true"is enabled, config file changes will override code-based updates—adjust this setting if needed. - Always call
LogManager.ReconfigExistingLoggers()after modifying target properties to apply changes immediately.
内容的提问来源于stack exchange,提问作者Mico

