Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit b021c25

Browse files
authored
[client] Add JSON format and timestamp for logs (#208)
* [client] Add JSON format and timestamp for logs * [client] modifications regarding comments
1 parent 96bfb65 commit b021c25

File tree

4 files changed

+45
-4
lines changed

4 files changed

+45
-4
lines changed

pycti/api/opencti_api_client.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# coding: utf-8
2-
32
import datetime
43
import io
54
import json
65
import logging
76
from typing import Union
87

98
import magic
9+
from pythonjsonlogger import jsonlogger
1010
import requests
1111
import urllib3
1212

@@ -50,6 +50,19 @@
5050
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5151

5252

53+
class CustomJsonFormatter(jsonlogger.JsonFormatter):
54+
def add_fields(self, log_record, record, message_dict):
55+
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
56+
if not log_record.get("timestamp"):
57+
# This doesn't use record.created, so it is slightly off
58+
now = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
59+
log_record["timestamp"] = now
60+
if log_record.get("level"):
61+
log_record["level"] = log_record["level"].upper()
62+
else:
63+
log_record["level"] = record.levelname
64+
65+
5366
class File:
5467
def __init__(self, name, data, mime="text/plain"):
5568
self.name = name
@@ -76,9 +89,19 @@ class OpenCTIApiClient:
7689
"https: "http://my_proxy:8080"
7790
}
7891
```
92+
:param json_logging: format the logs as json if set to True
93+
:type json_logging: bool, optional
7994
"""
8095

81-
def __init__(self, url, token, log_level="info", ssl_verify=False, proxies={}):
96+
def __init__(
97+
self,
98+
url,
99+
token,
100+
log_level="info",
101+
ssl_verify=False,
102+
proxies={},
103+
json_logging=False,
104+
):
82105
"""Constructor method"""
83106

84107
# Check configuration
@@ -94,7 +117,17 @@ def __init__(self, url, token, log_level="info", ssl_verify=False, proxies={}):
94117
numeric_level = getattr(logging, self.log_level.upper(), None)
95118
if not isinstance(numeric_level, int):
96119
raise ValueError("Invalid log level: " + self.log_level)
97-
logging.basicConfig(level=numeric_level)
120+
121+
if json_logging:
122+
log_handler = logging.StreamHandler()
123+
log_handler.setLevel(self.log_level.upper())
124+
formatter = CustomJsonFormatter(
125+
"%(timestamp)s %(level)s %(name)s %(message)s"
126+
)
127+
log_handler.setFormatter(formatter)
128+
logging.basicConfig(handlers=[log_handler], level=numeric_level, force=True)
129+
else:
130+
logging.basicConfig(level=numeric_level)
98131

99132
# Define API
100133
self.api_token = token

pycti/connector/opencti_connector_helper.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ def __init__(self, config: Dict) -> None:
381381
self.opencti_ssl_verify = get_config_variable(
382382
"OPENCTI_SSL_VERIFY", ["opencti", "ssl_verify"], config, False, True
383383
)
384+
self.opencti_json_logging = get_config_variable(
385+
"OPENCTI_JSON_LOGGING", ["opencti", "json_logging"], config
386+
)
384387
# Load connector config
385388
self.connect_id = get_config_variable(
386389
"CONNECTOR_ID", ["connector", "id"], config
@@ -438,7 +441,10 @@ def __init__(self, config: Dict) -> None:
438441

439442
# Initialize configuration
440443
self.api = OpenCTIApiClient(
441-
self.opencti_url, self.opencti_token, self.log_level
444+
self.opencti_url,
445+
self.opencti_token,
446+
self.log_level,
447+
json_logging=self.opencti_json_logging,
442448
)
443449
# Register the connector in OpenCTI
444450
self.connector = OpenCTIConnector(

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ datefinder~=0.7
55
stix2~=2.1.0
66
pika~=1.2
77
sseclient~=0.0.27
8+
python_json_logger~=2.0.2
89
python-magic~=0.4.24; sys_platform == 'linux' or sys_platform == 'darwin'
910
python-magic-bin~=0.4.14; sys_platform == 'win32'

tests/cases/connectors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self, config_file_path: str, api_client: OpenCTIApiClient, data: Di
6060
os.environ["OPENCTI_URL"] = api_client.api_url
6161
os.environ["OPENCTI_TOKEN"] = api_client.api_token
6262
os.environ["OPENCTI_SSL_VERIFY"] = str(api_client.ssl_verify)
63+
os.environ["OPENCTI_JSON_LOGGING"] = "true"
6364

6465
config = (
6566
yaml.load(open(config_file_path), Loader=yaml.FullLoader)

0 commit comments

Comments
 (0)