The positions of arguments in a logging call should match the positions of their message template placeholders.

## Why is this an issue?

The placeholders of a message template are defined by their name and their position. Log methods specify the values for the placeholder at runtime by passing them in a params array:

    logger.LogError("{First} placeholder and {Second} one.", first, second);

This rule raises an issue if the position of an argument does not match the position of the corresponding placeholder:

    // 'first' and 'second' are swapped
    logger.LogError("{First} placeholder and {Second} one.", second, first);
    //                                                       ^^^^^^  ^^^^^

### What is the potential impact?

Logging providers use placeholder names to create key/value pairs in the log entry. The key corresponds to the placeholder and the value is the argument passed in the log call.

If the positions of the placeholder and the argument do not match, the value is associated with the wrong key. This corrupts the logs entry and makes log analytics unreliable.

## How to fix it

Make sure that the placeholder positions and the argument positions match. Use local variables, fields, or properties for the arguments and name the placeholders accordingly.

### Code examples

#### Noncompliant code example

'path' and 'fileName' are swapped and therefore assigned to the wrong placeholders.

    logger.LogError("File {FileName} not found in folder {Path}", path, fileName);
    //                                                            ^^^^  ^^^^^^^^

#### Compliant solution

Swap the arguments.

    logger.LogError("File {FileName} not found in folder {Path}", fileName, path);

#### Noncompliant code example

'Name' is detected but 'Folder' is not. The placeholder’s name should correspond to the name from the argument.

    logger.LogError("File {Name} not found in folder {Folder}", file.DirectoryName, file.Name);
    //                                                                                   ^^^^

#### Compliant solution

Swap the arguments and rename the placeholder to 'DirectoryName'.

    logger.LogError("File {Name} not found in folder {DirectoryName}", file.Name, file.DirectoryName);

#### Noncompliant code example

Not detected: A name for the arguments can not be inferred. Use locals to support detection.

    logger.LogError("Sum is {Sum} and product is {Product}", x * y, x + y); // Not detected

#### Compliant solution

Help detection by using arguments with a name.

    var sum = x + y;
    var product = x * y;
    logger.LogError("Sum is {Sum} and product is {Product}", sum, product);

## Resources

### Documentation

- Message Templates - Message template specification
- Microsoft Learn - Log message template
- Serilog - Structured Data
- NLog - How to use structured logging