<div style="text-align:center"><img src="https://raw.githubusercontent.com/manjatech/logos/main/loris.jpg" /></div>
<p></p>
<p></p>
<p>
<span><img src="https://img.shields.io/badge/pypi-3775A9?style=for-the-badge&logo=pypi&logoColor=white"/></span>
<span><img src="https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&logo=python&logoColor=blue"/></span>
<span><img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white"/></span>
<span><img src="https://img.shields.io/badge/License-MIT-yellow.svg"/></span>
<span><img src="https://raw.githubusercontent.com/manjatech/logos/main/loris_log_coverage/coverage.svg"/></span>
</p>

# PYTZ Library Country Region

The complete list of [country region](https://gist.github.com/heyalexej/8bf688fd67d7199be4a1682b3eec7568) at PYTZ library could refers to pytz library documentation.

# Python Application Logging Module 

The centralized application logging library.

# Logging Data Level

- **`FATAL`**: Log the application/ solution/ API state or behaviours that causes the system to terminate unintentionally; or have to cause the system to halt.
- **`ERROR`**: Log the application/ solution/ API state or behaviours that causes the system response abnormally; or is returning not expected out; but the system is still running.
- **`DEBUG`**: Log the application/ solution/ API behaviours or state change.
- **`INFO`**: Log the AI model performance or output.

# Unique ID Generation

Please do use uuid4 for generating the random unique ID.

```python 
import uuid 
from loris_log.boto3Client import Boto3Client

# generating the random uu_id for each calling session.
id = uuid.uuid4()
```

Otherwise use uuid5 for fixed id generation.

```python
import uuid 

# generating the fixed uu_id for each calling session.
id = uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
```

# Log Message onto CloudWatch Examples

## Construct the Error Log Message

This shows the example of constructing the error log message for CloudWatch.

**`def set_error_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of an application/ remote host IP address/ service.
- **`message (list)`**: The error message.

```python
from loris_log.customLog import CustomLog
import uuid

# get the random uuid generated
id = uuid.uuid4()
# define the error log message as the string list.
error_message = ["[400]", "Service not found."]
# define the name (string), oftenly is the IP address of remote host, or the application name
name = "192.168.0.0"

# then, construct the corresponding error log message by initialize set_error_message
# function, and passing in the id (uuid::UUID), name (string), and error_message (list).
error_log = CustomLog.set_error_message(id, name, error_message)
```

## Construct the Debug Log Message

This shows the example of constructing the debug log message for CloudWatch. 

**`def set_debug_message(uu_id, name, message)`:**


Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of the application/ remote host IP address/ service.
- **`message (list)`**: The debug message.


```python
from loris_log.customLog import CustomLog
import uuid 

# get the random uuid
id = uuid.uuid4()
# define the debug message as the string list
debug_message = ["[200]", "Service ok"]
# define the name (string), oftenly is the IP address of remote host, or the application name
name = "192.168.0.0"

# then, construct the corresponding debug log message by calling set_debug_message function,
# and passing in the id (uuid::UUID), name (string), and debug_message (string).
debug_log = CustomLog.set_debug_message(id, name, debug_message)
```

## Construct the Fatal Log Message

This shows the example of constructing the fatal log message for CloudWatch.

**`def set_fatal_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of the application/ remote host IP address/ service.
- **`message (list)`**: The fatal message.

```python

from loris_log.customLog import CustomLog 
import uuid 

# get the random uuid
id = uuid.uuid4()
# define the fatal message as the string list 
fatal_message = ["[500", "Service terminated unexpectedly"]
# define the name (string), oftenly is the IP address of remote host, or the application name.
name = "192.168.0.0"

# then, construct the corresponding fatal log message by calling the set_fatal_message
# function and passing it id (uuid::UUID), name (string), and message (list).
fatal_log = CustomLog.set_fatal_message(id, name, fatal_message)
```

## Construct the Info Log Message

This shows the example of constructing the info log message for CloudWatch.

**`def set_info_message(uu_id, name, message)`**

Arguments:

- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of the application/ remote IP address/ service.
- **`message (list)`**: The info message.

```python
from loris_log.customLog import CustomLog 
import uuid 

# get the random uuid generated.
id = uuid.uuid4()
# define the fatal message as the string list.
info_message = ["[200]", "the accuracy is 0.99"]
# define the name (string), oftenly is the IP address of remote host, or the application name.
name = "192.168.0.0"

# then, construct the corresponding info log message via calling set_info_message function.
# by passing in the id (uuid::UUID), name (string), and example_fatal_message (string).
info_log = CustomLog.set_info_message(id, name, fatal_message)

```


## Pushing Log Message onto the CloudWatch 

This shows the example of establishing the connection to the AWS CloudWatch service via the following method:

**`def Boto3Client(region_name, aws_key, aws_secret)`**

Arguments:
- **`region_name (string)`**: The AWS service region name. Refers here [region_name](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html).
- **`aws_key (string)`**: The AWS service role access key.
- **`aws_secret (string)`**: The AWS service role secret key.

Then, pushing the constructed message onto the CloudWatch via the `set_log_message` function, after defining its log group and log stream:

**`def set_log_message(log_group_name, log_stream_name, log_message, country_region)`**

Arguments:
- **`log_group_name (string)`**: The name of the log group.
- **`log_stream_name (string)`**: The name of the log stream.
- **`log_message (list)`**: A list of application/ service/ api message.
- **`country_region (string)`**: The country region, follows pytz library. Example `"Asia/Tokyo"`

Below shows the complete example of pushing an log message onto the AWS CloudWatch.


```python
import uuid
from loris_log.customLog import CustomLog
from loris_log.boto3Client import Boto3Client

# constuct the log message uses the above elaborated approach. The example
# here creates a sample fatal log message.
# ========================================================================
# get the random uuid
id = uuid.uuid4()
# define the fatal message as the string list 
fatal_message = ["[500]", "Service terminated unexpectedly"]
# define the log name (string), oftenly is the IP address of remote host, or the application name.
name = "192.168.0.0"

# then, construct the corresponding fatal log message
fatal_log = CustomLog.set_fatal_message(id, name, fatal_message)

# Subsequently, push the created fatal log message onto the Cloudwatch
# ###############################################################################
# initialize the boto3 client by first define the log group(string), log stream (string), region (string),
# as well as the key (string) and secret (string). All in form of string.
log_group = ""
log_stream = ""
aws_region = ""
aws_key = ""
aws_secret = ""
country_region = ""
# establish the boto3 connection by initialize Boto3Client instance, then
# passing the aws_region (string), aws_key (string) and aws_secret (string).
client = Boto3Client(aws_region, aws_key, aws_secret)
# then push the log message via following set_log_message method by passing them
# log_group name (string), log_stream name (string, the log_messsage (list),
# and the country region
client.set_log_message(log_group, log_stream, fatal_log, country_region)
```

# Log Message onto Remote Server Via FTP Examples

## Construct the Debug Log Message

This shows the example of constructing the debug log message onto the remote FTP server using `set_debug_message` function.

**`def set_debug_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of an application/ remote host IP address/ service.
- **`message (list)`**: The debug message.

```python
from loris_log.customLog import CustomLog 

# randomly generated an id using uuid library
id = uuid.uuid4()
# then define the debug log message that is a list
debug_log = ["[200]", "OK"]
# and define the log name that is a string, which usually is the application name
# or the remote host IP address.
name = "192.168.1.1" 

# afterwards, build the complete debug log message string using set_debug_message
# function by passing the id (id::UUID), name (string), and debug_log (list).
debug_message = CustomLog.set_debug_message(id, name, debug_log)
```

## Construct the Info Log Message

This shows the example of constructing the info log message onto the remmote FTP server via the `set_info_message` function.

**`def set_info_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of an application/ remote host IP address/ service.
- **`message (list)`**: The info message.

```python
from loris_log.customLog import CustomLog
import uuid 

# get the random uuid generated
id = uuid.uuid4()
# define the info log message as the string list
info_message = ["[200]", "result is 0.9"]
# define the name (string), oftenly is an IP address of remote host, or the application name
name = "192.168.0.0"

# then, construct the corresponding info log message by initialize the set_info_message
# function, and passing in the id (uuid::UUID), name (string), and error_message(list)
info_log = CustomLog.set_info_message(id, name, info_message)
```

## Construct the Error Log Message

This shows the example of constructing the error log message onto the FTP remote server via the `set_error_message` function.

`def set_error_message(uu_id, name, message)`

Arguments:

- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of an application/ remote host IP address/ service.
- **`message (list)`**: The error message.

```python
from loris_log.customLog import CustomLog
import uuid

# get the random uuid generated
id = uuid.uuid4()
# define the error log message as the string list.
error_message = ["[400]", "Service not found."]
# define the name (string), oftenly is the IP address of remote host, or the application name
name = "192.168.0.0"

# then, construct the corresponding error log message by initialize set_error_message
# function, and passing in the id (uuid::UUID), name (string), and error_message (list).
error_log = CustomLog.set_error_message(id, name, error_message)
```

## Construct the Fatal Log Message

This shows the example of constructing the fatal log message for CloudWatch via the `set_fatal_message(uu_id, name, message)` function.

**`def set_fatal_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of application/ remote host IP address/ service.
- **`message (list)`**: The fatal message.

```python

from loris_log.customLog import CustomLog 
import uuid 

# get the random uuid
id = uuid.uuid4()
# define the fatal message as the string list 
fatal_message = ["[500", "Service terminated unexpectedly"]
# define the name (string), oftenly is the IP address of remote host, or the application name.
name = "192.168.0.0"

# then, construct the corresponding fatal log message by calling the set_fatal_message
# function and passing it id (uuid::UUID), name (string), and message (list).
fatal_log = CustomLog.set_fatal_message(id, name, fatal_message)
```

## Construct the Log for the Sensor Data

This shows the example of constructing the log message from some embedded device data via the `set_ftp_log_data` function.

**`def set_ftp_log_data(uu_id, starttime, endttime, result, groundtruth)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`starttime (string)`**: The start time of an operation. Conversion from `datetime.datetime.now()`.
- **`endtime (string)`**: The end time of an operation. Conversion from `datetime.datetime.now()`.
- **`result (string)`**: The result of the embedded device/ system/ model etc. Conversion from `double\ float\ long`.
- **`groundtruth (string)`**: The result of embedded device/ system/ model etc. Conversion from `double\ float\ long`.

```python
import datetime 
import uuid
from loris_log.customLog import CustomLog

# generate the uuid
id = uuid.uuid4()
# define the start time
starttime = datetime.datetime.now().strftime("%H:%M:%S")
# define the end time
endtime = datetime.datetime.now().strftime("%H:%M:%S")
# define the result
result = str(32)
# define the groundtruth
groundtruth = str(3)

# construct the log data message
data_log = CustomLog.set_ftp_log_data(id, starttime, endtime, result, groundtruth)
```

# Pushing Info Log Message onto Remote FTP Server

This example shows the approach to push the log message onto the remote FTP server. It first involves construction of the relevant log message. This example, for instance, create the info log message via the `set_info_message` function. 

**`def set_info_message(uu_id, name, message)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`name (string)`**: The name of an application/ remote host IP address/ service.
- **`message (list)`**: The info message.

```python
from loris_log.customLog import CustomLog
import uuid 

# get the random uuid generated
id = uuid.uuid4()
# define the info log message as the string list
info_message = ["[200]", "result is 0.9"]
# define the name (string), oftenly is an IP address of remote host, or the application name
name = "192.168.0.0"

# then, construct the corresponding info log message by initialize the set_info_message
# function, and passing in the id (uuid::UUID), name (string), and error_message(list)
info_log = CustomLog.set_info_message(id, name, info_message)

```

Then, attempt to establish the communication with the target remote FTP server by providing the FTP server `hostname (string)`, `port number (string)`, `username (string)`, as well as the `password (string)` via the `FTPClient` instance

**`def FTPClient(hostname, port_num, username, password)`**

Arguments:
- **`hostname (string)`**: FTP server's hostname.
- **`port_num (integer)`**: FTP server's port number.
- **`username (string)`**: FTP server's username.
- **`password (string)`**: FTP server's password.

as elaborated in the code snippet below.

```python
from loris_log.ftpClient import FtpClient

hostname = ""
port_num = 22
username = ""
password = ""

# Establish the connection to the remote FTP server
client = FtpClient(hostname, port_num, username, password)
```

After the connection was successfully established. It is time to publish the corresponding log message onto the remote FTP server, based on the define file path, and filename via the `set_ftp_log_file` method.

**`def set_ftp_log_file(directory_name, file_name, message, region_country)`**

Arguments:
- **`directory_path (string)`**: The path to the log file.
- **`file_name (string)`**: The log file name (without extension).
- **`message (string)`**: The log message
- **`region_country (string)`**: The log message local timezone; follows pytz timezone.



```python
# define the path for the log file, must follow the defined format
file_path = "log/testing/data"
# then define the log file name and its file extensions
filename = "sample"
# then define the local timezone
country_region = ""

# Push the log file onto the remote FTP server. New log will
client.set_ftp_log_file(file_path, filename, info_log, country_region)
```

If the log file (.log) was previously not created, please remember 
create the relevant folders and file using `create_ftp_log_file`

**`def create_ftp_log_file(file_path, filename, root)`**:

- **`file_path`**: the path to the log file.
- **`filename`**: the name of log file without extension.
- **`root`**: decision whether to create the log file from root directory

```python
file_path = "log_testing/data"
filename = "sample"
root = True

client.create_ftp_log_file(file_path, filename, root)
```

This shows the complete code example

```python
from loris_log.customLog import CustomLog
from loris_log.ftpClient import FtpClient
import uuid

# get the random uuid generated
id = uuid.uuid4()
# define the info log message as the string list
info_message = ["[200]", "result is 0.9"]
# define the name (string), oftenly is an IP address of remote host, or the application name
name = "192.168.0.0"
# then, construct the corresponding info log message by initialize the set_info_message
# function, and passing in the id (uuid::UUID), name (string), and error_message(list)
info_log = CustomLog.set_info_message(id, name, info_message)

# define the FTP server hostname
hostname = ""
# define the FTP server port number
port_num = 22
# define the FTP server username 
username = ""
# define the FTP server password
password = ""
# Establish the connection to the remote FTP server
client = FtpClient(hostname, port_num, username, password)


# define the path for the log file, must follow the defined format
file_path = "log/testing/data"
# then define the log file name and its file extensions
filename = "sample"
# also, define the local timexone
country_region = ""
# then decide if wanted to create the file from root
# directory, true if wanted to, or otherwise.
root = True

# If previously did not create the log message, create the relevant
# log file first
# @note: ignore this step write to existing log file
client.create_ftp_log_file(file_path, filename, root)

# Push the log file onto the remote FTP server. New log will
client.set_ftp_log_file(file_path, filename, info_log, country_region)
```

Please uses `set_error_message`, `set_info_message`, `set_fatal_message`, or `set_debug_message` method to log the `error`, `info`, `fatal` or `debug` message.

# Example of Pushing Sensor Data to Remote FTP Server

This example shows the example of pushing sensor data as log message onto the remote FTP server.

First, construct the log message using the sensor data via the `set_ftp_log_data` method.

**`def set_ftp_log_data(uu_id, starttime, endtime, result, groundtruth)`**

Arguments:
- **`uu_id (uuid::UUID)`**: The generated uuid.
- **`starttime (string)`**: The start time of an operation. Conversion from datetime.datetime.now().
- **`endtime (string)`**: The end time of an operation. Conversion from datetime.datetime.now().
- **`result (string)`**: The result of the sensors, embedded device, system, model etc. Conversion from double/ float/ long.
- **`groundtruth (string)`**: The result of the sensors, embedded device, system, model etc. Conversion from double/ float/ long.

```python
import datetime 
import uuid
from loris_log.customLog import CustomLog

# generate the uuid
id = uuid.uuid4()
# define the start time
starttime = datetime.datetime.now().strftime("%H:%M:%S")
# define the end time
endtime = datetime.datetime.now().strftime("%H:%M:%S")
# define the result
result = str(32)
# define the groundtruth
groundtruth = str(3)

# construct the log data message
data_log = CustomLog.set_ftp_log_data(id, starttime, endtime, result, groundtruth)
```

Once the log message was crafted, it is time to attempt to establish communication with the remote FTP server using the `FTPClient` method.

**`def FTPClient(hostname, port_num, username, password)`**

Arguments:
- **`hostname (string)`**: FTP server's hostname.
- **`port_num (integer)`**: FTP server's port number.
- **`username (string)`**: FTP server's username.
- **`password (string)`**: FTP server's password.

as elaborated in the code snippet below.

```python
from loris_log.ftpClient import FtpClient

hostname = ""
port_num = 22
username = ""
password = ""

# Establish the connection to the remote FTP server
client = FtpClient(hostname, port_num, username, password)
```

Then, defining the path and filename of the corresponding log file, and have the data pushing onto an log file of a FTP server using the `set_ftp_log_data` method.

**`def set_ftp_log_data(directory_path, file_name, log_data)`**

Arguments:
- **`directory_path (string)`**: The path to the log file.
- **`file_name (string)`**: The name of the log file without extension.
- **`log_data (byte)`**: The data to be logged.

```python
# define the path to the log file
directory_path = "/log_testing/data"
# define the log file with its extension
file_name = "log"
# push the log data onto the remote FTP server.
client.set_ftp_log_data(directory_path, file_name, data_log)
```

If the log file (csv file) was not previously created. Please create one
using the method `create_ftp_log_data`.

**`def create_ftp_log_data(file_path, filename, root)`**:

- **`file_path`**: The directory of the log file.
- **`filename`**: The name of log file without extension (without extension).
- **`root`**: The decision whether to start creating the log file from the root directory.

The complete example is as demonstrated below.

```python
import datetime 
import uuid
from loris_log.customLog import CustomLog
from loris_log.ftpClient import FtpClient

# generate the uuid
id = uuid.uuid4()
# define the start time
starttime = datetime.datetime.now().strftime("%H:%M:%S")
# define the end time
endtime = datetime.datetime.now().strftime("%H:%M:%S")
# define the result
result = str(32)
# define the groundtruth
groundtruth = str(3)
# construct the log data message
data_log = CustomLog.set_ftp_log_data(id, starttime, endtime, result, groundtruth)

# define FTP server hostname
hostname = ""
# define FTP server port number
port_num = 22
# define FTP server username
username = ""
# define FTP server password
password = ""
# Establish the connection to the remote FTP server
client = FtpClient(hostname, port_num, username, password)

# define the path to the log file
directory_path = "/log_testing/data"
# define the log file with its extension
file_name = "log"
# define whether to start log creation from root directory
root = True

# @optional, create the log file if it was never created. Ignore this line, if
# the file was existed.
client.create_ftp_log_data(directory_path, file_name, root)

# push the log data onto the remote FTP server.
client.set_ftp_log_data(directory_path, file_name, data_log)

```

# Example of Constructing the Info Log Message for A Sensor 

This example shows the approach to construct the info log message for an sensor using its id whose often is a string of text. 
This is achieve via the `set_sensor_info_message` method as elaborated below.

**`def set_sensor_info_message(sensor_id, name, message)`**

- **`sensor_id (string)`**: The sensor's serial number.
- **`name (string)`**: The name of the application/ service or API.
- **`message (list)`**: A collection of the info log message.

The usage of this method is as presented in code snippet below.

```Python
from log_loris.customLog import CustomLog

sensor_info_log = CustomLog.set_sensor_info_message("[camera-01-2300001]", "[my application]", ["[200]", "OK"])
```

# Example of Constructing the Debug Log Message for A Sensor

This example shows the approach to construct the debug log message for an sensor using its id whose often is a string of text.
This is achieve via the `set_sensor_debug_message` method as elaborated below.

**`def set_sensor_debug_message(sensor_id, name, message)`**

- **`sensor_id (string)`**: The sensor's serial number.
- **`name (string)`**: The name of the application/ service or API.
- **`message (list)`**: A collection of the info log message.

The usage of this method is as presented in code snippet below:

```Python
from log_loris.customLog import CustomLog 

sensor_debug_log = CustomLog.set_sensor_debug_message("[camera-01-2300001]", "[my application]", ["[200]", "OK"])
```

# Example of Constructing the Error Log Message for A Sensor 

This example shows the approach to construct the error log message for an sensor using its id whose often is a string of text.
This is achieve via the `set_sensor_error_message` method as elaborated below.

**`def set_sensor_error_message(sensor_id, name, message)`**

- **`sensor_id (string)`**: The sensor's serial number.
- **`name (string)`**: The name of the application/ service or API.
- **`message (list)`**: A collection of the error log message.

The usage of this method is as presented in code snippet below:

```Python
from loris_log.customLog import CustomLog

sensor_error_log = CustomLog.set_sensor_error_message("[camera-01-2300001]", "[my application]", ["[200]", "OK"])
```

# Example of Constructing the Fatal Log Message for A Sensor 

This example shows the approach to construct the fatal log message for an sensor using its id whose often is a string of text.
This is achieve via the `set_sensor_fatal_message` method as elaborated below.

**`def set_sensor_fatal_message`**: The sensor's serial number.

- **`sensor_id (string)`**: The sensor's serial number.
- **`name (string)`**: The name of the applicatioon/ service or API.
- **`message (list)`**: A collection of the error log message.

The usage of this method is as presented in code snippet below:

```Python
from loris_log.customLog import CustomLog

sensor_fatal_log = CustomLog.set_sensor_fatal_message("[camera-01-2300001]", "[my application]", ["[200]", "OK"])
```


# Example of Publishing Sensor Info Message onto CloudWatch

The initial step requires establishing the connection onto the CloudWatch via the `Boto3Client` as elaborated below.

**`Boto3Client(aws_region, aws_key, aws_secret)`**

- **`aws_region (string)`**: The AWS region.
- **`aws_log_group (string)`**: The AWS CloudWatch log group name.
- **`aws_log_stream (string)`**: The AWS CloudWatch log stream name.

This is follow by constructing the relevant log message 
using  `set_Sensor_info_message`.

**`def set_sensor_info_message(sensor_id, name, message)`**

- **`sensor_id`**: The sensor's serial number.
- **`name`**: The name of the application/ service or API.
- **`message (list)`**: A collection of the info log message.

Follows by pushing the log on the AWS CloudWatch.

**`def set_log_message(log_group, log_stream, info_log, country_region)`**

- **`log_group (string)`**: The AWS CloudWatch log group name.
- **`log_stream (string)`**: The AWS CloudWatch log stream name.
- **`info_log (string)`**: The info log message.
- **`country_region (string)`**: The local timezone, follows pytz library. Example `Asia/Tokyo`.

The complete codes snippet is as below:

```python
from loris_log.boto3Client import BotoClient 
from loris_log.customLog immport CustomLog 

# First, establish the connection to the AWS CloudWatch.
aws_region = ""
aws_log_group = ""
aws_log_stream = ""
client = Boto3Client(aws_region, aws_log_group, aws_log_stream)

# Then, construct the relevant log message; in this example
# a info log message for a sensor
info_message = CustomLog.set_sensor_info_message(
    "[camera-01-2300001]", "[my-app]", ["[200]", "OK"]
)

# Lastly, publishing the log message onto the CloudWatch
log_group = ""
log_stream = ""
country_region = ""
client.set_log_message(log_group, log_stream, info_message, country_region)
```

# Example of Publishing the Info Log Message onto FTP server.

This demonstrates the approach of how to publishing a sensor log message onto
a remote FTP server.

This requires user first establishes the connection to a remote
FTP server using the `FtpClient` method

**`def FtpClient(hostname, port_num, username, password)`**:

- **`hostname (string)`**: The FTP server hostname (IP address).
- **`port_nun (int)`**: The FTP server port number.
- **`username (string)`**: The FTP server username.
- **`password (string)`**: The FTP server password.

Then, it is follows by creating the info log message for the 
sensor using the `set_sensor_info_message` method.

**`def set_sensor_info_message(sensor_id, name, message)`

- **`sensor_id (string)`**: The sensor's id.
- **`name (string)`**: The application/ API name.
- **`message (list)`**: The sensor's log message.

Lastly, publishing the log message and write it onto
a log file via `set_ftp_log_file` method.

**`def set_ftp_log_file(file_path, filename, log_message, country_region)`**

- **`file_path (string)`**: The directory path of the log file.
- **`filename (string)`**: The log file's file name.
- **`log_message (list)`**: The sensor kog message.
- **`country_region`**: The local country timezone, follows pytz library. Example `Asia/Tokyo`

If the log file (.log) was never created, create one first using 
the method `create_ftp_log_file`.

**`def create_ftp_log_file(file_path, filename, root)`**:

- **`file_path`**: The path to the log file.
- **`filename`**: The name of log file without extension.
- **`root`**: The decision to whether create log file started from the root directory.

The complete example code is as presented below:

```python
from loris_log.ftpClient import FtpClient
from loris_log.customLog import CustomLog

hostname = ""
port_num = 00
username = ""
password = ""
# establish connction 
client = FtpClient(hostname, port_num, username, password)

# Then construct the info log message for the sensor
info_message = CustomLog.set_sensor_info_message(
    "camera01-E11]]",
    "[my-app]", ["[200]", "OK"]
)

# Lastly push onto the FTP server.
file_path = "log/testing/data"
filename = "sample"
root = True
country_region = ""

# Optional, create the file if log file not existed
# Otherwise, ignore this line
client.create_ftp_log_file(file_path, filename, root)

# push the log message onto the log file.
client.set_ftp_log_file(file_path, filename, info_message, country_region)
```
# Example of creating the log file from root directory

This demonstrates the approach to create log file from the parent directory.

First, establising the connection to the remote FTP server via `FTPClient` method.

**`FTPClient(hostname, port, username, password)`**:

- **`hostname`**: the host name of the FTP server.
- **`port`**: the port number of the FTP server.
- **`username`**: the username of the FTP server.
- **`password`**: the password of the FTP server.

subsequently, create the log file by setting the root parameter to True inside
`create_ftp_log_file` method.

**`create_ftp_log_file(file_path, filename, root)`**:

- **`file_path`**: the log file's file path.
- **`filename`**: the name of the log file.
- **`root`**: let the log file created from the root directory.

The complete code snippet is as below

```python
from loris_log.ftpClient import FtpClient

port = 22
hostname = ""
username = ""
password = ""

# establish the connection with the remote FTP server.
client = FtpClient(hostname, port, username, password)

# then, create the log file from the root directory
file_path = "testing/sample"
filename = "sample"
root = True

client.create_ftp_log_file(
    file_path, filename, root
)
```

# Example of creating the log file but not from root directory

This demonstrates the approach to create the log file, but not from the parent directory.

First, establising the connection to the remote FTP server via `FTPClient` method

**`FTPClient(hostname, port, username, password)`**:

- **`hostname`**: the host name of the FTP server.
- **`port`**: the port number of the FTP server.
- **`username`**: the username of the FTP server.
- **`password`**: the password of the FTP server.

subsequently, create the log file by setting the root parameter to True inside
`create_ftp_log_file` method.

**`create_ftp_log_file(file_path, filename, root)`**:

- **`file_path`**: the log file's file path.
- **`filename`**: the name of the log file.
- **`root`**: let the log file created from the root directory.

The complete code snippet is as below

```python
from loris_log.ftpClient import FtpClient

port = 22
hostname = ""
username = ""
password = ""

# establish the connection with the remote FTP server.
client = FtpClient(hostname, port, username, password)

# then, create the log file from the root directory
file_path = "testing/sample"
filename = "sample"
root = False

client.create_ftp_log_file(
    file_path, filename, root
)
```

# Example of creating the log file for sensor's data from root directory

This demonstrates the approach to create log file from the parent directory.

First, establising the connection to the remote FTP server via `FTPClient` method.

**`FTPClient(hostname, port, username, password)`**:

- **`hostname`**: the host name of the FTP server.
- **`port`**: the port number of the FTP server.
- **`username`**: the username of the FTP server.
- **`password`**: the password of the FTP server.

subsequently, create the log file by setting the root parameter to True inside
`create_ftp_log_data` method.

**`create_ftp_log_data(file_path, filename, root)`**:

- **`file_path`**: the log file's file path.
- **`filename`**: the name of the log file.
- **`root`**: let the log file created from the root directory.

The complete code snippet is as below

```python
from loris_log.ftpClient import FtpClient

port = 22
hostname = ""
username = ""
password = ""

# establish the connection with the remote FTP server.
client = FtpClient(hostname, port, username, password)

# then, create the log file from the root directory
file_path = "testing/sample"
filename = "sample"
root = True

client.create_ftp_log_data(
    file_path, filename, root
)
```
# Example of creating the log file for sensor's data not from root directory

This demonstrates the approach to create the log file, but not from the parent directory.

First, establising the connection to the remote FTP server via `FTPClient` method.

**`FTPClient(hostname, port, username, password)`**:

- **`hostname`**: the host name of the FTP server.
- **`port`**: the port number of the FTP server.
- **`username`**: the username of the FTP server.
- **`password`**: the password of the FTP server.

subsequently, create the log file by setting the root parameter to True inside
`create_ftp_log_data` method.

**`create_ftp_log_data(file_path, filename, root)`**:

- **`file_path`**: the log file's file path.
- **`filename`**: the name of the log file.
- **`root`**: let the log file created from the root directory.

The complete code snippet is as below

```python
from loris_log.ftpClient import FtpClient

port = 22
hostname = ""
username = ""
password = ""

# establish the connection with the remote FTP server.
client = FtpClient(hostname, port, username, password)

# then, create the log file from the root directory
file_path = "testing/sample"
filename = "sample"
root = False

client.create_ftp_log_data(
    file_path, filename, root
)
```
