You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+82-24Lines changed: 82 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,7 +84,7 @@ var log = new LoggerConfiguration()
84
84
85
85
## Table definition
86
86
87
-
You'll need to create a table like this in your database:
87
+
You'll need to create a table like this in your database. Many other variations are possible. In particular, give careful consideration to whether you need the Id column (discussed in the next section). The table definition shown here is the default configuration.
88
88
89
89
```
90
90
CREATE TABLE [Logs] (
@@ -95,8 +95,7 @@ CREATE TABLE [Logs] (
95
95
[Level] nvarchar(128) NULL,
96
96
[TimeStamp] datetimeoffset(7) NOT NULL, -- use datetime for SQL Server pre-2008
97
97
[Exception] nvarchar(max) NULL,
98
-
[Properties] xml NULL,
99
-
[LogEvent] nvarchar(max) NULL
98
+
[Properties] xml NULL
100
99
101
100
CONSTRAINT [PK_Logs]
102
101
PRIMARY KEY CLUSTERED ([Id] ASC)
@@ -107,23 +106,76 @@ CREATE TABLE [Logs] (
107
106
) ON [PRIMARY];
108
107
```
109
108
110
-
**Remember to grant the necessary permissions for the sink to be able to write to the log table.**
109
+
If you don't plan to use a column, you can specify which columns to exclude in the `columnOptions.Store` parameter (see below).
111
110
112
-
If you don't plan on using one or more columns, you can specify which columns to include in the *columnOptions.Store* parameter (see below).
113
-
114
-
The Level column should be defined as a TinyInt if the *columnOptions.Level.StoreAsEnum* is set to true.
111
+
The Level column should be defined as a `tinyint` when `columnOptions.Level.StoreAsEnum` is set to `true`.
115
112
116
113
117
114
### Automatic table creation
118
115
119
-
If you set the `autoCreateSqlTable` option to `true`, the sink will create a table for you in the database specified in the connection string. Make sure that the user associated with this connection string has enough rights to make schema changes.
116
+
If you set the `autoCreateSqlTable` option to `true`, the sink will create a table for you in the database specified in the connection string. Make sure that the user associated with this connection string has enough rights to make schema changes; see below.
117
+
118
+
119
+
### Permissions
120
+
121
+
SQL permissions are a very complex subject. Here is an example of one possible solution (valid for SQL 2012 or later):
122
+
123
+
```
124
+
CREATE ROLE [SerilogAutoCreate];
125
+
GRANT SELECT ON sys.tables TO [SerilogAutoCreate];
126
+
GRANT SELECT ON sys.schemas TO [SerilogAutoCreate];
127
+
GRANT ALTER ON SCHEMA::[dbo] TO [SerilogAutoCreate]
128
+
GRANT CREATE TABLE ON DATABASE::[SerilogTest] TO [SerilogAutoCreate];
129
+
130
+
CREATE ROLE [SerilogWriter];
131
+
GRANT SELECT TO [SerilogWriter];
132
+
GRANT INSERT TO [SerilogWriter];
133
+
134
+
CREATE LOGIN [Serilog] WITH PASSWORD = 'password';
135
+
136
+
CREATE USER [Serilog] FOR LOGIN [Serilog] WITH DEFAULT_SCHEMA = dbo;
137
+
GRANT CONNECT TO [Serilog];
138
+
139
+
ALTER ROLE [SerilogAutoCreate] ADD MEMBER [Serilog];
140
+
ALTER ROLE [SerilogWriter] ADD MEMBER [Serilog];
141
+
```
142
+
143
+
This creates a SQL login named `Serilog`, a database user named `Serilog`, and assigned to that user are the roles `SerilogAutoCreate` and `SerilogWriter`. As the name suggests, the SerilogAutoCreate role is not needed if you create the database ahead of time, which is the recommended course of action if you're concerned about security at this level.
144
+
145
+
Also, ideally the SerilogWriter role would be restricted to the log table only, and that table has to already exist for table-specific GRANT statements to execute, so that's another reason that you probably don't want to use auto-create. Table-level restrictions would look like this (assuming you name your log table SecuredLog, of course):
146
+
147
+
```
148
+
GRANT SELECT ON [dbo].[SecuredLog] TO [SerilogWriter];
149
+
GRANT SELECT ON [dbo].[SecuredLog] TO [SerilogWriter];
150
+
```
151
+
152
+
There are many possible variations. For example, you could also create a new schema that was specific to the log(s) and restrict access that way.
153
+
154
+
155
+
## Id Column Options
156
+
157
+
Previous versions of this sink assumed the Id column is always present as an `int``IDENTITY` primary key with a clustered index. Other configurations are available, however this is still the default strictly for backwards-compatibility reasons.
158
+
159
+
You should consider your anticipated logging volume and query requirements carefully. The default setting is not especially useful in real-world query scenarios since a clustered index is primarily of use when the key is used for sorting or range searches, which will rarely be the case for the Id column.
160
+
161
+
### No Id Column
162
+
163
+
If you eliminate the Id column completely, the log table is stored as an unindexed heap. This is the ideal write-speed scenario for logging, however any non-clustered indexes you add will degrade write performance. One way to mitigate this is to keep the non-clustered indexes offline and use batch reindexing on a scheduled basis. If you create your table ahead of time, simply omit the Id column and the constraint shown in the previous section.
164
+
165
+
### Unclustered Id Column
166
+
167
+
You can also retain the Id column as an `IDENTITY` primary key, but without a clustered index. The log is still stored as an unindexed heap, but writes with non-clustered indexes are slightly faster. The non-clustered indexes will reference the Id primary key. However, read performance will be slightly degraded since it requires two reads (the covering non-clustered index, then dereferencing the heap row from the Id). To create this type of table ahead of time, change the constraint in the previous section to `NONCLUSTERED` and leave out the `WITH` clause.
168
+
169
+
### Bigint Data Type
170
+
171
+
For very large log tables, you may wish to create the Id column with the `bigint` datatype. This 8-byte integer will permit a maximum identity value of 9,223,372,036,854,775,807. The only change to the table syntax in the previous section is the datatype where `[Id]` is defined.
120
172
121
173
122
174
## Standard columns
123
175
124
-
The "standard columns" used by this sink (apart from obvious required columns like Id) are described by the StandardColumn enumeration and controlled through code by the `columnOptions.Store` collection.
176
+
The "standard columns" used by this sink are described by the `StandardColumn` enumeration and controlled through code by the `columnOptions.Store` collection. By default (and consistent with the SQL command to create a table, above) these columns are included:
125
177
126
-
By default (and consistent with the SQL command to create a table, above) these columns are included:
You can also store your own log event properties as additional columns; see below.
145
-
196
+
You can also store your own log event properties in additional custom columns; see below.
146
197
147
-
### Saving properties in additional columns
198
+
### Saving properties in custom columns
148
199
149
200
By default any log event properties you include in your log statements will be saved to the Properties column (and/or LogEvent column, per columnOption.Store). But they can also be stored in their own columns via the AdditionalDataColumns setting.
150
201
@@ -153,25 +204,30 @@ var columnOptions = new ColumnOptions
The log event properties `User` and `Other` will now be placed in the corresponding column upon logging. The property name must match a column namein your table. Be sure to include them in the table definition.
217
+
The log event properties `UserName` and `RequestUri` will be written to the corresponding columns whenever those values (with the exact same property name) occur in a log entry. Be sure to include them in the table definition if you create your table ahead of time.
167
218
219
+
Variable-length data types like `varchar` require a `DataLength` property. Use -1 to specify SQL's `MAX` length.
168
220
169
-
#### Excluding redundant items from the Properties column
221
+
**Standard column names are reserved. Even if you exclude a standard column, never create a custom column by the same name.**
222
+
223
+
224
+
#### Excluding redundant Properties or LogEvent data
170
225
171
226
By default, additional properties will still be included in the data saved to the XML Properties or JSON LogEvent column (assuming one or both are enabled via the `columnOptions.Store` parameter). This is consistent with the idea behind structured logging, and makes it easier to convert the log data to another (e.g. NoSQL) storage platform later if desired.
172
227
173
-
However, if necessary, then the properties being saved in their own columns can be excluded from the data. Use the `columnOptions.Properties.ExcludeAdditionalProperties` parameter in the sink configuration to exclude the redundant properties from the XML.
228
+
However, if necessary, the properties being saved in their own columns can be excluded from the data. Use the `columnOptions.Properties.ExcludeAdditionalProperties` parameter in the sink configuration to exclude the redundant properties from the XML, or `columnOptions.LogEvent.ExcludeAdditionalProperties` if you've added the JSON LogEvent column.
174
229
230
+
The standard columns are always excluded from the Properties and LogEvent columns.
175
231
176
232
### Columns defined by AppSettings (.NET Framework)
177
233
@@ -219,7 +275,7 @@ The equivalent of adding custom columns as shown in the .NET Framework example a
219
275
}
220
276
```
221
277
222
-
As the name suggests, `columnOptionSection` is an entire configuration section in its own right. All possible entries and some sample values are shown below. All properties and subsections are optional.
278
+
As the name suggests, `columnOptionSection` is an entire configuration section in its own right. All possible entries and some sample values are shown below. All properties and subsections are optional. It is not currently possible to specify a `PropertiesFilter` predicate in configuration.
223
279
224
280
```json
225
281
"columnOptionsSection": {
@@ -230,7 +286,7 @@ As the name suggests, `columnOptionSection` is an entire configuration section i
@@ -256,11 +312,13 @@ As the name suggests, `columnOptionSection` is an entire configuration section i
256
312
```
257
313
258
314
259
-
### Options for serialization of the log event data
315
+
### Options for serialization of event data
316
+
317
+
Typically you will choose either XML or JSON serialization, but not both.
260
318
261
319
#### JSON (LogEvent column)
262
320
263
-
The log event JSON can be stored to the LogEvent column. This can be enabled by adding the LogEvent column to the `columnOptions.Store` collection. Use the `columnOptions.LogEvent.ExcludeAdditionalProperties` parameter to exclude redundant properties from the JSON. This is analogue to excluding redundant items from XML in the Properties column.
321
+
Event data items can be stored to the LogEvent column. This can be enabled by adding the LogEvent column to the `columnOptions.Store` collection. Use the `columnOptions.LogEvent.ExcludeAdditionalProperties` parameter to exclude redundant properties from the JSON. This is analogue to excluding redundant items from XML in the Properties column.
264
322
265
323
#### XML (Properties column)
266
324
@@ -276,7 +334,7 @@ If `OmitDictionaryContainerElement`, `OmitSequenceContainerElement` or `OmitStru
276
334
277
335
If `OmitElementIfEmpty` is set then if a property is empty, it will not be serialized.
278
336
279
-
##### Querying the properties XML
337
+
##### Querying the Properties XML data
280
338
281
339
Extracting and querying the properties data directly can be helpful when looking for specific log sequences.
Copy file name to clipboardExpand all lines: src/Serilog.Sinks.MSSqlServer/Configuration/Microsoft.Extensions.Configuration/LoggerConfigurationMSSqlServerExtensions.cs
0 commit comments