# Logging

Logging is a fundamental aspect of software development and system administration, providing a valuable means to record and monitor the activities and events within an application or system.

This tutorial aims to equip you with the knowledge and skills to enable logging in your applications or systems effectively.

We will explore the essential concepts of logging, such as log levels, log formats, and log destinations.

By the end of this tutorial, you will have a clear understanding of how to incorporate logging into your projects and locate log files for analysis and debugging purposes.

### Prerequisites

1. Completed the [**Getting Started**](https://docs.licensespring.com/sdks/tutorials/best-practices/broken-reference) Tutorial, specifically:
   * Initialized `LicenseManager` (or `LicenseHandler`) with your configuration using the appropriate settings.
   * Created a `LicenseID` using either `LicenseID::fromKey` or `LicenseID::fromUser` function, depending on the activation method you prefer.
   * Implemented basic license management, including license activations, deactivations, and both online and local license checks.

### Enabling Logging and Verifying Its Status

Logging is enabled within the `Configuration` object, prior to the product and license being configured within the application.

{% hint style="info" %}
**Note:** Logging is **disabled** by default.
{% endhint %}

Logging can be enabled using the following method:

{% tabs %}
{% tab title="C++" %}

```cpp
void LicenseSpring::ExtendedOptions::enableLogging( bool enable )	
```

{% endtab %}

{% tab title="C#" %}

```csharp
bool LicenseSpring.ExtendedOptions.EnableLogging
```

{% endtab %}

{% tab title="Java" %}

```java
public B requestLogging( feign.Logger.Level requestLogging )
```

{% endtab %}

{% tab title="Swift" %}

```swift
// Just set log handler:
LSLog.log = { level, message in
    print("[\(level)] \(message())")
}
```

{% endtab %}

{% tab title="Python" %}

```python
import logging

# Configure logging
logging.basicConfig(
    filename='app.log',   # Name of the log file
    filemode='a',         # Append to the file ('w' for overwrite)
    format='%(asctime)s - %(levelname)s - %(message)s',  # Log format
    level=logging.INFO    # Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**Warning:** Logging is for developer use only, ensure it is disabled in your release builds.
{% endhint %}

To see how to enable logging in an application environment, see below:

{% tabs %}
{% tab title="C++" %}

```cpp
std::string appName = "NAME"; //input name of application
std::string appVersion = "VERSION"; //input version of application

ExtendedOptions options;
options.enableLogging( true ); 

auto configuration = Configuration::Create(
     EncryptStr( "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" ),
     EncryptStr( "XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX" ), 
     EncryptStr( "XXXXXX" ),
     appName, appVersion, options );

auto licenseManager = LicenseManager::create( pConfiguration );
```

{% endtab %}

{% tab title="C#" %}

```csharp
var options = new LicenseSpring.ExtendedOptions();
options.EnableLogging = true;

var configuration = new LicenseSpring.Configuration(
            apiKey: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", 
            sharedKey: "XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX", 
            productCode: "XXXXXX", 
            appName: "NAME",
            appVersion: "VERSION",
            extendedOptions: options );
            
var licenseManager = LicenseManager.GetInstance();
licenseManager.Initialize( configuration );
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration configuration = LicenseSpringConfiguration.builder()
                .apiKey( "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" )
                .productCode( "XXXXXX" )
                .sharedKey( "XXXXXXXXX-XXXXX-XXXXXXXXXXXXX_XXXXXX_XXXXXX" )
                .appName( "NAME" )
                .appVersion( "VERSION" )
                .requestLogging( Logger.Level.FULL ) 
                .build();

LicenseManager licenseManager = LicenseManager.getInstance();
licenseManager.initialize( configuration );
```

{% endtab %}

{% tab title="Python" %}

```python
from licensespring.licensefile.config import Configuration
from licensespring.licensefile.license_manager import LicenseID, LicenseManager
import logging

# Configure logging
logging.basicConfig(
    filename='path_where_you_want_to_store_logs/app.log',   # Name of the log file
    filemode='a',         # Append to the file ('w' for overwrite)
    format='%(asctime)s - %(levelname)s - %(message)s',  # Log format
    level=logging.INFO    # Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
)

conf = Configuration(
        product="your_product_short_code",
        api_key="api_key",
        shared_key="shared_key",
        file_key="your_file_key",
        file_iv="file_iv",
        grace_period_conf=12,
        is_guard_file_enabled=True)


lm = LicenseManager(conf)
license_id = LicenseID.from_key("9FFA-2XZC-SNDJ-49LK")
license = lm.activate_license(license_id)
license.check()
```

{% endtab %}
{% endtabs %}

Developers can chack for whether logging is enabled in the current `Configuration` through using:

{% tabs %}
{% tab title="C++" %}

```cpp
bool LicenseSpring::ExtendedOptions::isLoggingEnabled()
```

{% endtab %}

{% tab title="C#" %}

```csharp
bool LicenseSpring.Configuration.IsLoggingEnabled
```

{% endtab %}

{% tab title="Java" %}

```java
feign.Logger.Level getRequestLogging()
```

{% endtab %}
{% endtabs %}

### Location of the Log File

The location of log files is a critical aspect of logging configuration, determining where logged data is stored and accessed for monitoring, debugging, and analysis purposes.

#### Default Location in Different Environments

The location of the log file depends on the operating system in use.

On Windows, the default SDK data location is: `{SystemDrive}:/Users/{UserName}/AppData/Local/LicenseSpring/{ProductCode}`

On Linux, the default SDK data location is: `HOME/.LicenseSpring/LicenseSpring/{ProductCode}`

On macOS, the default SDK data location is: `~/Library/Application Support/LicenseSpring/{ProductCode}`

These default paths indicate where the log file and other SDK-related data are stored based on the specific operating system.

#### Getting Current Data Location

Log files are stored in the same location as all other LicenseSpring data, including your local license file.

To discover the specific location of this data on your device, you can utilize the corresponding functionality provided within your application.

{% tabs %}
{% tab title="C++" %}

```cpp
std::wstring path = licenseManager->licenseFilePath();
```

{% endtab %}

{% tab title="C#" %}

```csharp
var path = licenseManager.DataLocation;
```

{% endtab %}

{% tab title="Java" %}

```java
String path = configuration.getLicenseFilePath();
```

{% endtab %}

{% tab title="Python" %}

```python
path = lm.data_location()
```

{% endtab %}
{% endtabs %}

#### Changing Data Location

Changing the data location involves modifying the application's configuration or settings to redirect where data, including log files, is stored.

Developers and administrators may implement this change to consolidate data in a centralized location, move data to faster storage media, or ensure data privacy and compliance with regulations.

{% tabs %}
{% tab title="C++" %}

```cpp
licenseManager->setDataLocation(L"new/path/to/LicenseSpring/data");
```

{% endtab %}

{% tab title="C#" %}

```csharp
licenseManager.DataLocation = "new/path/to/LicenseSpring/data";
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseSpringConfiguration.ClientConfigurationBuilder licenseFilePath( String licenseFilePath )
```

{% endtab %}

{% tab title="Python" %}

```python
lm.set_data_location("new/path/to/LicenseSpring/data")
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**Warning:** If there's a license in the new location, it will be set as current license, otherwise the current license will be removed from memory.
{% endhint %}
