Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions openbb_terminal/base_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any, List, Literal, Optional

from dotenv import load_dotenv
from posthog import Posthog
from rich.console import Console

from openbb_terminal.core.config.paths import (
Expand All @@ -16,6 +17,11 @@

menus = Literal["", "featflags", "settings"]

openbb_posthog = Posthog(
"phc_8fP8xXi0ptWTlGAXOcMQnSFsul4lmLoxnwp9EiXQstO",
host="https://app.posthog.com",
)


def handle_error(name: str, default: Any, menu: menus = ""):
"""Handles the error by returning the default value and printing an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ def mock_password(text: str) -> str:

@staticmethod
def mock_home_directory(text: str) -> str:
user_home_directory = str(HOME_DIRECTORY)
text_mocked = text.replace(user_home_directory, "MOCKING_USER_PATH")
user_home_directory = str(HOME_DIRECTORY.as_posix())
text_mocked = text.replace("\\\\", "/").replace(
user_home_directory, "MOCKING_USER_PATH"
)

return text_mocked

Expand Down
2 changes: 2 additions & 0 deletions openbb_terminal/core/models/profile_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from pydantic.dataclasses import dataclass

from openbb_terminal.base_helpers import openbb_posthog
from openbb_terminal.core.models import BaseModel


Expand Down Expand Up @@ -34,6 +35,7 @@ def load_user_info(self, session: dict, email: str, remember: bool):
self.email = email
self.username = self.email[: self.email.find("@")]
self.remember = remember
openbb_posthog.identify(self.uuid, {"email": self.email})

def get_uuid(self) -> str:
"""Get uuid.
Expand Down
1 change: 1 addition & 0 deletions openbb_terminal/core/models/system_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class SystemModel(BaseModel):
VERSION = "3.0.0rc2"

# Logging section
LOGGING_APP_ID: str = "REPLACE_ME"
LOGGING_APP_NAME: str = "gst"
LOGGING_AWS_ACCESS_KEY_ID: str = "REPLACE_ME"
LOGGING_AWS_SECRET_ACCESS_KEY: str = "REPLACE_ME"
Expand Down
7 changes: 6 additions & 1 deletion openbb_terminal/core/plots/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,12 @@ def send_figure(

json_data = json.loads(fig.to_json())

json_data.update({"theme": get_current_user().preferences.CHART_STYLE})
json_data.update(
{
"user_id": get_current_system().LOGGING_APP_ID,
"theme": get_current_user().preferences.CHART_STYLE,
}
)

self.outgoing.append(
json.dumps(
Expand Down
20 changes: 20 additions & 0 deletions openbb_terminal/core/plots/plotly.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_8fP8xXi0ptWTlGAXOcMQnSFsul4lmLoxnwp9EiXQstO',{api_host:'https://app.posthog.com'});
window.posthog.onFeatureFlags(function () {
if (!window.posthog.isFeatureEnabled('record-pywry')) {
window.posthog.stopSessionRecording()
}
})
posthog.register({'$geoip_disable': true});
</script>
</head>

<body>
Expand Down Expand Up @@ -202,6 +212,8 @@
globals.cmd_src = "";
if (typeof OpenBBMain != "undefined" && window.plotly_figure) {
clearInterval(interval);
let user_id = window.plotly_figure.user_id;
posthog.identify(user_id);
const date = new Date();
const formattedDate = new Intl.DateTimeFormat("en-GB", {
dateStyle: "full",
Expand Down Expand Up @@ -245,6 +257,14 @@
});
}

if (globals.cmd_src != "") {
posthog.capture("chart", {
command: globals.cmd_src,
title: window.plotly_figure.layout.title.text,
date: formattedDate,
});
}

document
.querySelector('meta[name="color-scheme"]')
.setAttribute(
Expand Down
127 changes: 124 additions & 3 deletions openbb_terminal/loggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
__docformat__ = "numpy"

# IMPORTATION STANDARD
import atexit
import json
import logging
import re
import sys
import time
import uuid
from pathlib import Path
from typing import Optional
from platform import platform, python_version
from typing import Any, Dict, Optional

# IMPORTATION THIRDPARTY
try:
Expand All @@ -18,6 +22,7 @@
WITH_GIT = True

# IMPORTATION INTERNAL
from openbb_terminal.base_helpers import openbb_posthog
from openbb_terminal.core.log.generation.directories import get_log_dir
from openbb_terminal.core.log.generation.formatter_with_exceptions import (
FormatterWithExceptions,
Expand All @@ -31,8 +36,14 @@
LogSettings,
Settings,
)
from openbb_terminal.core.log.generation.user_logger import get_user_uuid
from openbb_terminal.core.session.current_system import get_current_system
from openbb_terminal.core.log.generation.user_logger import (
NO_USER_PLACEHOLDER,
get_user_uuid,
)
from openbb_terminal.core.session.current_system import (
get_current_system,
set_current_system,
)

logger = logging.getLogger(__name__)
current_system = get_current_system()
Expand Down Expand Up @@ -85,6 +96,107 @@ def get_commit_hash(use_env=True) -> str:
return commit_hash


class PosthogHandler(logging.Handler):
"""Posthog Handler"""

def __init__(self, settings: Settings):
super().__init__()
self.settings = settings
self.app_settings = settings.app_settings
self.logged_in = False
atexit.register(openbb_posthog.shutdown)

def emit(self, record: logging.LogRecord):
try:
self.send(record=record)
except Exception:
self.handleError(record)

def log_to_dict(self, log_info: str) -> dict:
"""Log to dict"""
log_regex = r"(KEYS|PREFERENCES|SYSTEM|CMD|QUEUE): (.*)"
log_dict = {}

for log in re.findall(log_regex, log_info):
log_dict[log[0]] = json.loads(log[1])

sdk_regex = r"({\"INPUT\":.*})"
sdk_dict = re.findall(sdk_regex, log_info)
if sdk_dict:
log_dict["SDK"] = json.loads(sdk_dict[0])

return log_dict

def send(self, record: logging.LogRecord):
"""Send log record to Posthog"""

app_settings = self.app_settings

level_name = logging.getLevelName(record.levelno)
log_line = FormatterWithExceptions.filter_log_line(text=record.getMessage())

log_extra = self.extract_log_extra(record=record)
log_extra.update(dict(level=level_name, message=log_line))
event_name = f"log_{level_name.lower()}"

if log_dict := self.log_to_dict(log_info=log_line):
event_name = f"log_{list(log_dict.keys())[0].lower()}"

log_extra = {**log_extra, **log_dict}
log_extra.pop("message", None)

if re.match(r"^(START|END|INPUT:)", log_line):
return

if not self.logged_in and get_user_uuid() != NO_USER_PLACEHOLDER:
self.logged_in = True
openbb_posthog.alias(get_user_uuid(), app_settings.identifier)

log_extra.update({"$geoip_disable": True})

openbb_posthog.capture(
app_settings.identifier,
event_name,
properties=log_extra,
)

def extract_log_extra(self, record: logging.LogRecord) -> Dict[str, Any]:
"""Extract log extra from record"""

log_extra = {
"appName": self.app_settings.name,
"appId": self.app_settings.identifier,
"sessionId": self.app_settings.session_id,
"commitHash": self.app_settings.commit_hash,
"platform": platform(),
"pythonVersion": python_version(),
"terminalVersion": current_system.VERSION,
}

if get_user_uuid() != NO_USER_PLACEHOLDER:
log_extra["userId"] = get_user_uuid()

if hasattr(record, "extra"):
log_extra = {**log_extra, **record.extra}

if record.exc_info:
log_extra["exception"] = {
"type": str(record.exc_info[0]),
"value": str(record.exc_info[1]),
"traceback": self.format(record),
}

return log_extra


def add_posthog_handler(settings: Settings):
app_settings = settings.app_settings
handler = PosthogHandler(settings=settings)
formatter = FormatterWithExceptions(app_settings=app_settings)
handler.setFormatter(formatter)
logging.getLogger().addHandler(handler)


def add_stdout_handler(settings: Settings):
app_settings = settings.app_settings
handler = logging.StreamHandler(sys.stdout)
Expand Down Expand Up @@ -150,6 +262,12 @@ def setup_handlers(settings: Settings):
FormatterWithExceptions.LOGFORMAT.replace("|", "-"),
)

if (
not any([current_system.TEST_MODE, current_system.LOGGING_SUPPRESS])
and current_system.LOG_COLLECT
):
add_posthog_handler(settings=settings)


def setup_logging(
app_name: Optional[str] = None,
Expand All @@ -165,6 +283,9 @@ def setup_logging(
session_id = get_session_id()
user_id = get_user_uuid()

current_system.LOGGING_APP_ID = identifier
set_current_system(current_system)

# AWSSettings
aws_access_key_id = current_system.LOGGING_AWS_ACCESS_KEY_ID
aws_secret_access_key = current_system.LOGGING_AWS_SECRET_ACCESS_KEY
Expand Down
7 changes: 3 additions & 4 deletions openbb_terminal/parent_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,9 @@ def log_queue(self) -> None:
if self.queue:
joined_queue = self.COMMAND_SEPARATOR.join(self.queue)
if not self.contains_keys(joined_queue):
queue = {"path": self.PATH, "queue": joined_queue}
logger.info(
"QUEUE: {'path': '%s', 'queue': '%s'}",
self.PATH,
joined_queue,
"QUEUE: %s ", json.dumps(queue, default=str, ensure_ascii=False)
)

def log_cmd_and_queue(
Expand All @@ -328,7 +327,7 @@ def log_cmd_and_queue(
"other_args": other_args_str,
"input": the_input,
}
logger.info("CMD: %s", json.dumps(cmd))
logger.info("CMD: %s ", json.dumps(cmd))

if the_input not in self.KEYS_MENU:
self.log_queue()
Expand Down