The C# and Visual Basic compilers support a /errorlog:<file> switch on
the command line to log all diagnostics in a structured, JSON format.

The log format is SARIF (Static Analysis Results Interchange Format):
See https://sarifweb.azurewebsites.net/ for the format specification,
JSON schema, and other related resources.

## SARIF v2 format

This section provides a high level overview of the contents of the SARIF v2 error log file generated by the C# and Visual Basic compilers. A more formal and detailed schema specification for the SARIF v2 format is specified at http://json.schemastore.org/sarif-2.1.0.

1. `schema` and `version` information: The first two lines of the error log file specifies the SARIF schema and version information. For example:

```json
"$schema": "http://json.schemastore.org/sarif-2.1.0",
"version": "2.1.0",
```

2. `runs` information: The core entry in the error log file is the `runs` section with a single run entry within it for the build. The run entry has the following main parts:
   1. `results` section: This section contains an array of result entries, where each result corresponds to information about a reported compiler or analyzer `Diagnostic`. More details in [`Result` format for each compiler or analyzer `Diagnostic` instance](#result-format-for-each-compiler-or-analyzer-diagnostic-instance).
   2. `properties` section: This section contains custom key-value properties associated with the run. Following properties are currently emitted:
      1. `analyzerExecutionTime`: Execution time in seconds for execution of all analyzers, as reported with the `/reportAnalyzer` compiler switch.
   3. `tools` section: This section contains information about the compiler build and version. Additionally, it contains a `rules` array, where each rule entry corresponds to metadata or `DiagnosticDescriptor` information about each reported analyzer diagnostic. More details in [`Rule` format for each analyzer supported `DiagnosticDescriptor` instance](#rule-format-for-each-analyzer-supported-diagnosticdescriptor-instance)
   4. `invocations` section: This section contains information about the end user specified configurations for the rules for compiler invocation/run. We emit this section only if at least one rule had one or more severity configuration overrides for a part or whole of the compilation via options. More details in [`Rule Configuration Override` format for each rule severity override](#rule-configuration-override-format-for-each-rule-severity-override).
   5. `columnKind` section: This section contains information about the unit in which the tool measures columns. C# and Visual Basic compilers uses utf16 code units.

Example `runs` section, with stripped off `results`, `rules` and `ruleConfigurationOverrides` sections:
```json
"runs": [
{
  "results": [
  ],
  "properties": {
    "analyzerExecutionTime": "x.xxx"
  },
  "tool": {
    "driver": {
      "name": "Microsoft (R) Visual C# Compiler",
      "version": "4.4.0-dev (<developer build>)",
      "dottedQuadFileVersion": "42.42.42.42",
      "semanticVersion": "42.42.42",
      "language": "en-US",
      "rules": [
      ]
    }
  },
  "invocations": [
    {
      "executionSuccessful": true,
      "ruleConfigurationOverrides": [
      ]
    }
  ],
  "columnKind": "utf16CodeUnits"
}
]
```

### `Result` format for each compiler or analyzer `Diagnostic` instance

The results section contains an array of result entries, where each result corresponds to information about a reported compiler or analyzer `Diagnostic`. It contains the below data:
1. `ruleId`: Rule ID or diagnostic ID for the diagnostic.
2. `ruleIndex`: Index into the `rules` section for the underlying `DiagnosticDescriptor` for the diagnostic. See [`Rule` format for each analyzer supported `DiagnosticDescriptor` instance](#rule-format-for-each-analyzer-supported-diagnosticdescriptor-instance) for more details.
3. `level`: Severity level for the diagnostic, such as `error`, `warning`, `note`, etc.
4. `message`: User facing message for the diagnostic.
5. `suppressions`: For each diagnostic instance that is suppressed with a pragma directive, SuppressMessageAttribute or via a DiagnosticSuppressor, the result entry contains `suppressions` section with the following data:
   1. `kind` information: C# and Visual Basic compilers support a single `inSource` suppression kind.
   2. `justification` information: Justification pertaining to the suppression. Currently, this field is populated only for `SuppressMessageAttribute` based suppression, with a non-null justification argument.
   3. `suppressionType` property with one of these three values: `Pramga Directive`, `SuppressMessageAttribute`, or `DiagnosticSuppressor`. This data helps analyze the preferred in-source suppression mechanisms in a code base.
6. `locations`: One or more locations associated with the diagnostic.
7. `properties`: One or more custom key-value string pairs associated with the diagnostic.

Example `result` entry:
```json
{
  "ruleId": "CA1822",
  "ruleIndex": 97,
  "level": "warning",
  "message": {
    "text": "Member 'M2' does not access instance data and can be marked as static"
  },
  "suppressions": [
  {
    "kind": "inSource",
    "justification": "<Pending>",
    "properties": {
      "suppressionType": "SuppressMessageAttribute"
    }
  }
  ],
  "locations": [
  {
    "physicalLocation": {
      "artifactLocation": {
        "uri": "file:///C:/source/repos/ClassLibrary1/Class1.cs"
      },
      "region": {
        "startLine": 13,
        "startColumn": 10,
        "endLine": 13,
        "endColumn": 12
      }
    }
  }
  ],
  "properties": {
    "warningLevel": 1
  }
}
```

### `Rule` format for each analyzer supported `DiagnosticDescriptor` instance

The `rules` section contains a rule entry that corresponds to metadata or `DiagnosticDescriptor` information about supported descriptors for each analyzer. We report the `DiagnosticDescriptor` info for all analyzers that were provided to the compilation, regardless of whether or not they executed on the entire compilation, part of the compilation or were disabled for the entire compilation. A `rule` entry contains the below data:
1. `id`: Rule ID or Diagnostic ID associated with the descriptor.
2. `shortDescription`: User facing short description or `Title` associated with the descriptor.
3. `fullDescription`: User facing full description or `Description` associated with the descriptor.
4. `defaultConfiguration`: Default severity level for the diagnostics reported for the descriptor, such as `error`, `warning`, `note`, etc.
5. `helpUri`: Help uri for help information associated with the descriptor.
6. `properties`: One or more custom properties associated with the descriptor. It includes the following:
   1. `category`: `Category` associated with the descriptor, such as, `Design`, `Performance`, `Security`, etc.
   2. `isEverSuppressed` and `suppressionKinds`: If a rule had either a source suppression or was disabled for part or whole of the compilation via options, the rule metadata contains a special flag `isEverSuppressed = true` and an array `suppressionKinds` with either or both of the below suppression kinds:
      1. `inSource` suppression kind for one or more reported diagnostic(s) that were suppressed through pragma directive, SuppressMessageAttribute or a DiagnosticSuppressor.
      2. `external` suppression kind for diagnostic ID that is disabled either for the entire compilation (via global options such as /nowarn, ruleset, globalconfig, etc.) or for certain files or folders in the compilation (via editorconfig options).
   3. `executionTimeInSeconds`: Execution time in seconds associated with the analyzer, as reported with the `/reportAnalyzer` compiler switch. Values less than `0.001` seconds are reported as `<0.001`.
   4. `executionTimeInPercentage`: Execution time in percentage associated with the analyzer, as reported with the `/reportAnalyzer` compiler switch. Values less than `1` are reported as `<1`.
   5. `tags`: An array of one of more `CustomTags` associated with the descriptor.
  
Example `rule` entry:
```json
{
  "id": "CA1001",
  "shortDescription": {
    "text": "Types that own disposable fields should be disposable"
  },
  "fullDescription": {
    "text": "A class declares and implements an instance field that is a System.IDisposable type, and the class does not implement IDisposable. A class that declares an IDisposable field indirectly owns an unmanaged resource and should implement the IDisposable interface."
  },
  "defaultConfiguration": {
    "level": "note"
  },
  "helpUri": "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1001",
  "properties": {
    "category": "Design",
    "isEverSuppressed": "true",
    "suppressionKinds": [
      "external"
    ],
    "executionTimeInSeconds": "x.xxx",
    "executionTimeInPercentage": "xx",
    "tags": [
      "PortedFromFxCop",
      "Telemetry",
      "EnabledRuleInAggressiveMode"
    ]
  }
}
```

### `Rule Configuration Override` format for each rule severity override

The `ruleConfigurationOverrides` section contains an array of entries, with an entry for every rule severity configuration override for the whole or part of the compilation via options, i.e. editorconfig, globalconfig, command line options, ruleset, etc. Each rule configuration override entry contains the following information:
1. `descriptor`: Property containing information to map back to the relevant `descriptor` or the `rule` in the `rules` section. Currently, it contains the below child properties:
   1. `id`: Rule id string for the rule or diagnostic.
   2. `index`: A zero-based integral index value into the `rules` array for the rule mapping.
2. `configuration`: Configuration property for the effective overridden severity for the rule. Currently, it may include one of the below child properties:
   1. `enabled`: A boolean property indicating if the rule has been explicitly disabled or enabled with the configuration override entry.
   1. `level`: Property for the effective severity of the rule, such as `error`, `warning` or `note`. Note that this property is not emitted for rules disabled with configuration override, we instead emit `enabled: false` for them.

Note that we can have multiple `ruleConfigurationOverride` entries for the same descriptor if the rule is configured to fire at different severities across different parts of the compilation. For example, editorconfig based severity configurations can specify different effective severity for the same rule ID for different files or folders in a project.

Example `ruleConfigurationOverride` entry:
```json
{
  "descriptor": {
    "id": "CA1000",
    "index": 0
  },
  "configuration": {
    "level": "error"
  }
},
{
  "descriptor": {
    "id": "CA1000",
    "index": 0
  },
  "configuration": {
    "enabled": false
  }
},
{
  "descriptor": {
    "id": "CA1001",
    "index": 1
  },
  "configuration": {
    "level": "warning"
  }
}
```