Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Add logging on api endpoints #296

Merged
Merged
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
40 changes: 32 additions & 8 deletions mytoyota/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Toyota Connected Services API."""

import logging
from datetime import date, datetime, timezone
from uuid import uuid4

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import
from mytoyota.const import (
VEHICLE_ASSOCIATION_ENDPOINT,
VEHICLE_GLOBAL_REMOTE_ELECTRIC_STATUS_ENDPOINT,
Expand All @@ -24,6 +26,8 @@
from mytoyota.models.endpoints.vehicle_guid import VehiclesResponseModel
from mytoyota.models.endpoints.vehicle_health import VehicleHealthResponseModel

_LOGGER: logging.Logger = logging.getLogger(__name__)


class Api:
"""API Class. Allows access to available endpoints to retrieve the raw data."""
Expand Down Expand Up @@ -72,7 +76,11 @@

async def get_vehicles_endpoint(self) -> VehiclesResponseModel:
"""Return list of vehicles registered with provider."""
return await self._request_and_parse(VehiclesResponseModel, "GET", VEHICLE_GUID_ENDPOINT)
parsed_response = await self._request_and_parse(

Check warning on line 79 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L79

Added line #L79 was not covered by tests
VehiclesResponseModel, "GET", VEHICLE_GUID_ENDPOINT
)
_LOGGER.debug(msg=f"Parsed 'VehiclesResponseModel': {parsed_response}")
return parsed_response

Check warning on line 83 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L82-L83

Added lines #L82 - L83 were not covered by tests

async def get_location_endpoint(self, vin: str) -> LocationResponseModel:
"""Get the last known location of your car. Only updates when car is parked.
Expand All @@ -87,9 +95,11 @@
-------
LocationResponseModel: A pydantic model for the location response
"""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 98 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L98

Added line #L98 was not covered by tests
LocationResponseModel, "GET", VEHICLE_LOCATION_ENDPOINT, vin=vin
)
_LOGGER.debug(msg=f"Parsed 'LocationResponseModel': {parsed_response}")
return parsed_response

Check warning on line 102 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L101-L102

Added lines #L101 - L102 were not covered by tests

async def get_vehicle_health_status_endpoint(self, vin: str) -> VehicleHealthResponseModel:
r"""Get the latest health status.
Expand All @@ -105,18 +115,22 @@
-------
VehicleHealthResponseModel: A pydantic model for the vehicle health response
"""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 118 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L118

Added line #L118 was not covered by tests
VehicleHealthResponseModel, "GET", VEHICLE_HEALTH_STATUS_ENDPOINT, vin=vin
)
_LOGGER.debug(msg=f"Parsed 'VehicleHealthResponseModel': {parsed_response}")
return parsed_response

Check warning on line 122 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L121-L122

Added lines #L121 - L122 were not covered by tests

async def get_remote_status_endpoint(self, vin: str) -> RemoteStatusResponseModel:
"""Get information about the vehicle."""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 126 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L126

Added line #L126 was not covered by tests
RemoteStatusResponseModel,
"GET",
VEHICLE_GLOBAL_REMOTE_STATUS_ENDPOINT,
vin=vin,
)
_LOGGER.debug(msg=f"Parsed 'RemoteStatusResponseModel': {parsed_response}")
return parsed_response

Check warning on line 133 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L132-L133

Added lines #L132 - L133 were not covered by tests

async def get_vehicle_electric_status_endpoint(self, vin: str) -> ElectricResponseModel:
r"""Get the latest electric status.
Expand All @@ -132,12 +146,14 @@
-------
ElectricResponseModel: A pydantic model for the electric response
"""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 149 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L149

Added line #L149 was not covered by tests
ElectricResponseModel,
"GET",
VEHICLE_GLOBAL_REMOTE_ELECTRIC_STATUS_ENDPOINT,
vin=vin,
)
_LOGGER.debug(msg=f"Parsed 'ElectricResponseModel': {parsed_response}")
return parsed_response

Check warning on line 156 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L155-L156

Added lines #L155 - L156 were not covered by tests

async def get_telemetry_endpoint(self, vin: str) -> TelemetryResponseModel:
"""Get the latest telemetry status.
Expand All @@ -152,9 +168,11 @@
-------
TelemetryResponseModel: A pydantic model for the telemetry response
"""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 171 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L171

Added line #L171 was not covered by tests
TelemetryResponseModel, "GET", VEHICLE_TELEMETRY_ENDPOINT, vin=vin
)
_LOGGER.debug(msg=f"Parsed 'TelemetryResponseModel': {parsed_response}")
return parsed_response

Check warning on line 175 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L174-L175

Added lines #L174 - L175 were not covered by tests

async def get_notification_endpoint(self, vin: str) -> NotificationResponseModel:
"""Get all available notifications for the vehicle.
Expand All @@ -171,12 +189,14 @@
-------
NotificationResponseModel: A pydantic model for the notification response
"""
return await self._request_and_parse(
parsed_response = await self._request_and_parse(

Check warning on line 192 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L192

Added line #L192 was not covered by tests
NotificationResponseModel,
"GET",
VEHICLE_NOTIFICATION_HISTORY_ENDPOINT,
vin=vin,
)
_LOGGER.debug(msg=f"Parsed 'NotificationResponseModel': {parsed_response}")
return parsed_response

Check warning on line 199 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L198-L199

Added lines #L198 - L199 were not covered by tests

async def get_trips_endpoint( # noqa: PLR0913
self,
Expand Down Expand Up @@ -217,4 +237,8 @@
limit=limit,
offset=offset,
)
return await self._request_and_parse(TripsResponseModel, "GET", endpoint, vin=vin)
parsed_response = await self._request_and_parse(

Check warning on line 240 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L240

Added line #L240 was not covered by tests
TripsResponseModel, "GET", endpoint, vin=vin
)
_LOGGER.debug(msg=f"Parsed 'TripsResponseModel': {parsed_response}")
return parsed_response

Check warning on line 244 in mytoyota/api.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/api.py#L243-L244

Added lines #L243 - L244 were not covered by tests
3 changes: 2 additions & 1 deletion mytoyota/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
import logging
from typing import List, Optional

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import
from mytoyota.api import Api
from mytoyota.models.vehicle import Vehicle

from .controller import Controller
from .exceptions import ToyotaInvalidUsernameError

_LOGGER: logging.Logger = logging.getLogger(__package__)
_LOGGER: logging.Logger = logging.getLogger(__name__)


class MyT:
Expand Down
5 changes: 3 additions & 2 deletions mytoyota/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
import httpx
import jwt

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import
from mytoyota.const import (
ACCESS_TOKEN_URL,
API_BASE_URL,
AUTHENTICATE_URL,
AUTHORIZE_URL,
)
from mytoyota.exceptions import ToyotaApiError, ToyotaInternalError, ToyotaLoginError
from mytoyota.utils.logs import format_httpx_response
from mytoyota.utils.logging.log_utils import format_httpx_response

_LOGGER: logging.Logger = logging.getLogger(__package__)
_LOGGER: logging.Logger = logging.getLogger(__name__)

CACHE_FILENAME: Path = Path.home() / ".cache" / "toyota_credentials_cache_contains_secrets"

Expand Down
5 changes: 3 additions & 2 deletions mytoyota/models/vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from arrow import Arrow

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import
from mytoyota.api import Api
from mytoyota.models.dashboard import Dashboard
from mytoyota.models.endpoints.vehicle_guid import VehicleGuidModel
Expand All @@ -20,9 +21,9 @@
from mytoyota.models.summary import Summary, SummaryType
from mytoyota.models.trips import Trip
from mytoyota.utils.helpers import add_with_none
from mytoyota.utils.logs import censor_all
from mytoyota.utils.logging.log_utils import censor_all

_LOGGER: logging.Logger = logging.getLogger(__package__)
_LOGGER: logging.Logger = logging.getLogger(__name__)


class Vehicle:
Expand Down
3 changes: 2 additions & 1 deletion mytoyota/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import arrow
from arrow import Arrow

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import

Check warning on line 7 in mytoyota/statistics.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/statistics.py#L7

Added line #L7 was not covered by tests
from mytoyota.const import (
BUCKET,
DATA,
Expand All @@ -29,7 +30,7 @@
convert_to_mpg,
)

_LOGGER: logging.Logger = logging.getLogger(__package__)
_LOGGER: logging.Logger = logging.getLogger(__name__)

Check warning on line 33 in mytoyota/statistics.py

View check run for this annotation

Codecov / codecov/patch

mytoyota/statistics.py#L33

Added line #L33 was not covered by tests


class Statistics:
Expand Down
4 changes: 3 additions & 1 deletion mytoyota/utils/conversions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Conversion utilities used."""
import logging

_LOGGER: logging.Logger = logging.getLogger(__package__)
import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import

_LOGGER: logging.Logger = logging.getLogger(__name__)


def convert_to_miles(kilometers: float) -> float:
Expand Down
33 changes: 33 additions & 0 deletions mytoyota/utils/logging/log_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: 1
disable_existing_loggers: False

formatters:
simple:
format: "%(asctime)s %(levelname)s %(message)s"
datefmt: "%Y-%m-%d %H:%M:%S"

handlers:
file:
class: "logging.FileHandler"
formatter: "simple"
filename: ".log"
mode: "w"
filters:
- "logfilter"

filters:
logfilter:
(): mytoyota.utils.logging.log_filters.RedactingFilter
patterns:
- 'access_token\":\s*\"([^\"]*)'
- 'id_token\":\s*\"([^\"]*)'
- 'subscriberGuid\":\s*\"([^\"]*)'
- 'contractId\":\s*\"([^\"]*)'
- 'vin\":\s*\"([^\"]*)'
- 'euiccid\":\s*\"([^\"]*)'
- "guid':\\s*'([^']*)"

root:
level: "DEBUG"
handlers:
- "file"
24 changes: 24 additions & 0 deletions mytoyota/utils/logging/log_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Module with filter log filter classes."""
import logging
import re


class RedactingFilter(logging.Filter):
"""Helper class to filter logs by given pattern via 'logging.Filter'."""

def __init__(self, patterns):
"""Initialise RedactingFilter class."""
super(RedactingFilter, self).__init__()
self._patterns = patterns

def filter(self, record):
"""Modify the log record to mask sensitive data."""
record.msg = self.mask_sensitive_data(record.msg)
return True

def mask_sensitive_data(self, msg):
"""Mask sensitive data in logs by given patterns."""
for pattern in self._patterns:
compiled_pattern = re.compile(pattern)
msg = compiled_pattern.sub("****", msg)
return msg
File renamed without changes.
13 changes: 13 additions & 0 deletions mytoyota/utils/logging/logging_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Load a central config for logging."""
import logging
import logging.config
from pathlib import Path

import yaml

BASE_DIR = Path(__file__).parent

with open(file=BASE_DIR / "log_config.yaml", mode="r", encoding="utf-8") as config:
config_dict = yaml.safe_load(config)

logging.config.dictConfig(config_dict)
3 changes: 3 additions & 0 deletions simple_client_example.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"""Simple test of new API Changes."""
import asyncio
import json
import logging
import pprint
from datetime import date, timedelta

import mytoyota.utils.logging.logging_config # noqa # pylint: disable=unused-import
from mytoyota.client import MyT
from mytoyota.models.summary import SummaryType

pp = pprint.PrettyPrinter(indent=4)
logger = logging.getLogger(__name__)

# Set your username and password in a file on top level called "credentials.json" in the format:
# {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_utils/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest
from httpx import Request, Response

from mytoyota.utils.logs import (
from mytoyota.utils.logging.log_utils import (
censor_all,
censor_string,
censor_value,
Expand Down