Skip to content

Commit

Permalink
Merge pull request #53 from unl0ck/fix/issue-52-exception
Browse files Browse the repository at this point in the history
  • Loading branch information
unl0ck authored Nov 12, 2024
2 parents 06f114f + af8b584 commit 182b6bc
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .bumpversion-dev.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.bumpversion]
current_version = "2.0.7"
current_version = "2.9.1"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"
Expand Down
8 changes: 8 additions & 0 deletions GridboxConnectorAddon-dev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
<!-- https://developers.home-assistant.io/docs/add-ons/presentation#keeping-a-changelog -->

## 2.10.0

### 🚀 Added

- Opentelemetry Class to collect exceptions

## 2.9.0

### 🔨 Fixed

- bump viessmann-connector to 1.5.1

## 2.8.5
Expand Down
8 changes: 6 additions & 2 deletions GridboxConnectorAddon-dev/Dockerfile.standalone
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile
FROM python:3.10-alpine
FROM python:3.10-slim

# Build arguments
ARG BUILD_DATE
Expand All @@ -17,9 +17,13 @@ LABEL \
org.opencontainers.image.revision=${BUILD_REF} \
org.opencontainers.image.version=${BUILD_VERSION}

RUN apt-get update && \
apt-get install -y gcc g++ && \
rm -rf /var/lib/apt/lists/*

# Copy root filesystem
COPY GridboxConnectorAddon-edge/GridboxConnector/ /build/GridboxConnector

RUN cd /build/GridboxConnector && pip install -r requirements.txt

ENTRYPOINT ["python3", "/build/GridboxConnector"]
ENTRYPOINT ["python3", "/build/GridboxConnector"]
21 changes: 20 additions & 1 deletion GridboxConnectorAddon-dev/GridboxConnector/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from ha_viessmann_gridbox_connector import HAViessmannGridboxConnector
import logging
from importlib.resources import files
from utils import SensitiveDataFilter
from utils import SensitiveDataFilter, get_bool_env
from telemetry import Telemetry
opens_file_path = '/data/options.json'
#logging.basicConfig(format='%(asctime)s %(filename)s:%(lineno)d %(levelname)s - %(message)s', level=logging.getLevelName(os.getenv('LOG_LEVEL', 'INFO')))
logger = logging.getLogger(__name__)
Expand All @@ -24,6 +25,20 @@ def load_gridbox_config():
data = json.load(json_file)
return data

def run_telemetry():
enable_telemetry = get_bool_env('ENABLE_TELEMETRY', False)
telemetry = None
if enable_telemetry:
#otel_server = os.getenv('TelemetryServer', "https://otel.helming.xyz")
#if otel_server == "":
otel_server = "https://otel.helming.xyz"
telemetry = Telemetry(otel_server, "homeassistant-addon-viessmann-gridbox")
telemetry.log_as_span("Telemetry enabled", level=logger.level)
return telemetry




def run_addon():
gridbox_config = load_gridbox_config()
options_file = ''
Expand All @@ -40,6 +55,7 @@ def run_addon():
mqtt_pw = os.getenv('MqttPw', "")
mqtt_server = os.getenv('MqttServer', "")
mqtt_port = os.getenv('MqttPort', "")

if not USER or not PASSWORD:
logger.error("Username or Password not set")
exit(1)
Expand All @@ -53,6 +69,8 @@ def run_addon():
mqtt_settings = Settings.MQTT(host=mqtt_server, username=mqtt_user, password=mqtt_pw, port=mqtt_port)
viessmann_gridbox_connector = HAViessmannGridboxConnector(mqtt_settings)
gridboxConnector = GridboxConnector(gridbox_config)


while True:
measurement = gridboxConnector.retrieve_live_data()
if len(measurement) > 0:
Expand All @@ -68,5 +86,6 @@ def run_addon():
time.sleep(WAIT)

if __name__ == '__main__':
telemetry = run_telemetry()
run_addon()
#run_test_log()
5 changes: 5 additions & 0 deletions GridboxConnectorAddon-dev/GridboxConnector/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
ha-mqtt-discoverable==0.13.1
requests==2.32.2
viessmann-gridbox-connector==1.5.1
opentelemetry-api
opentelemetry-sdk
opentelemetry-exporter-otlp-proto-grpc
opentelemetry-instrumentation-requests
opentelemetry-instrumentation-logging
92 changes: 92 additions & 0 deletions GridboxConnectorAddon-dev/GridboxConnector/telemetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import logging
import requests
import uuid
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes

from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler

class Telemetry:
def __init__(self, collector_endpoint, service_name):
self.service_instance_id = str(uuid.uuid4())
self.resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: service_name,
ResourceAttributes.SERVICE_INSTANCE_ID: self.service_instance_id
})

# Instrument the logging module
LoggingInstrumentor().instrument(set_logging_format=True, log_level=logging.DEBUG)
# Set up logging
logging.basicConfig(level=logging.DEBUG)

# Set up the tracer provider and exporter
trace.set_tracer_provider(TracerProvider(resource=self.resource))
self.tracer = trace.get_tracer(__name__)

# Set up the OTLP exporter
otlp_exporter = OTLPSpanExporter(endpoint=collector_endpoint, insecure=True)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Instrument the requests library
RequestsInstrumentor().instrument()

# Create and set the logger provider
logger_provider = LoggerProvider(resource=self.resource)
set_logger_provider(logger_provider)

exporter = OTLPLogExporter(endpoint=collector_endpoint, insecure=True)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
handler = LoggingHandler(level=logging.DEBUG, logger_provider=logger_provider)

# Attach OTLP handler to root logger
logging.getLogger().addHandler(handler)
self.logger = logging.getLogger("telemetry")

def log_as_span(self, message, level=logging.INFO):
with self.tracer.start_as_current_span("logging") as span:
if level == logging.DEBUG:
self.logger.debug(message)
elif level == logging.INFO:
self.logger.info(message)
elif level == logging.WARNING:
self.logger.warning(message)
elif level == logging.ERROR:
self.logger.error(message)
elif level == logging.CRITICAL:
self.logger.critical(message)
span.add_event("log_event", {"message": message, "level": level})

def make_request(self, url):
try:
with self.tracer.start_as_current_span("http_request") as span:
response = requests.get(url)
self.logger.info(f"Received response: {response.status_code}")
span.add_event("Received response", {"status_code": response.status_code, "body": response.text})
return response
except Exception as e:
self.logger.exception(f"Exception during request: {e}")
raise

def main():
collector_endpoint = "https://otel.helming.xyz"
service_name = "test_telemetry"
telemetry = Telemetry(collector_endpoint, service_name)
telemetry.log_as_span("This is a test log message", level=logging.INFO)
try:
response = telemetry.make_request("https://httpbin.org/get")
telemetry.log_as_span(f"Request successful with status code: {response.status_code}", level=logging.INFO)
except Exception as e:
telemetry.log_as_span(f"Request failed with exception: {e}", level=logging.ERROR)

if __name__ == "__main__":
main()
17 changes: 14 additions & 3 deletions GridboxConnectorAddon-dev/GridboxConnector/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import logging
import ast
import os
class SensitiveDataFilter(logging.Filter):
def filter(self, record):
message = record.getMessage()
Expand All @@ -19,8 +20,18 @@ def filter(self, record):
literal_msg['client_id'] = '***'
# Das modifizierte Dictionary zurück in einen String konvertieren
record.msg = json.dumps(literal_msg)
except json.JSONDecodeError:
except Exception as e:
# Wenn die Nachricht kein JSON ist, nichts tun
logging.error('Could not parse message as JSON')
logging.error(f"Error filtering sensitive data: {e}")
pass
return True
return True

def get_bool_env(var, default=False):
value = os.getenv(var, default)
if isinstance(value, str):
value = value.lower()
if value in ["1", "true"]:
return True
if value in ["0", "false"]:
return False
return bool(value)
2 changes: 1 addition & 1 deletion GridboxConnectorAddon-dev/cloudSettings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.9.0",
"version": "2.10.1",
"urls": {
"login": "https://gridx.eu.auth0.com/oauth/token",
"gateways": "https://api.gridx.de/gateways",
Expand Down
2 changes: 1 addition & 1 deletion GridboxConnectorAddon-dev/config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
name: Viessmann Gridbox Connector (dev)
version: "2.9.0"
version: "2.10.1"
slug: "gridbox_connector_dev"
description: Development version of Viessmann Gridbox Connector
url: "https://github.com/unl0ck/homeassistant-addon-viessmann-gridbox/tree/main/GridboxConnectorAddon-dev"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export MqttUser=$(bashio::config 'OverrideMqttUser')
export MqttPw=$(bashio::config 'OverrideMqttPw')
export MqttServer=$(bashio::config 'OverrideMqttServer')
export MqttPort=$(bashio::config 'OverrideMqttPort')
export TelemetryServer=$(bashio::config 'OverrideTelemetryUrl')

test "$MqttUser" = "null" && export MqttUser=$(bashio::services "mqtt" "username")
test "$MqttPw" = "null" && export MqttPw=$(bashio::services "mqtt" "password")
Expand All @@ -19,6 +20,7 @@ test "$MqttPort" = "null" && export MqttPort=$(bashio::services "mqtt" "port")
export USERNAME=$(bashio::config 'username')
export PASSWORD=$(bashio::config 'password')
export LOG_LEVEL=$(bashio::config 'log_level')
export ENABLE_TELEMETRY=$(bashio::config 'enable_telemetry')
ls -lash /data
cd /build/
ls -lash
Expand Down
2 changes: 1 addition & 1 deletion GridboxConnectorAddon-dev/rootfs/share/cloudSettings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.9.0",
"version": "2.10.1",
"urls": {
"login": "https://gridx.eu.auth0.com/oauth/token",
"gateways": "https://api.gridx.de/gateways",
Expand Down
16 changes: 16 additions & 0 deletions GridboxConnectorAddon-dev/translations/de.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
configuration:
username:
name: Username
description: gib hier deine E-Mail-Adresse ein
password:
name: Password
description: gib hier dein Passwort ein
wait_time:
name: Wait
description: Setze die Zeit in Sekunden, wie lange gewartet wird, bis neue Daten abgerufen werden
log_level:
name: Log Level
description: Setze das Log-Level
enable_telemetry:
name: Enable Telemetry
description: Aktiviere das Senden von Telemetriedaten an den Entwickler für Debugging oder Ausnahmehandhabung
6 changes: 6 additions & 0 deletions GridboxConnectorAddon-dev/translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ configuration:
wait_time:
name: Wait
description: Set time in seconds how long will wait until fetch new data
log_level:
name: Log Level
description: Set the log level
enable_telemetry:
name: Enable Telemetry
description: Enable sending telemetry data to the developer for debugging or exception handling
4 changes: 2 additions & 2 deletions GridboxConnectorAddon-edge/GridboxConnector/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ def filter(self, record):
literal_msg['client_id'] = '***'
# Das modifizierte Dictionary zurück in einen String konvertieren
record.msg = json.dumps(literal_msg)
except json.JSONDecodeError:
except Exception as e:
# Wenn die Nachricht kein JSON ist, nichts tun
logging.error('Could not parse message as JSON')
logging.error(f"Error filtering sensitive data: {e}")
pass
return True

Expand Down
4 changes: 2 additions & 2 deletions GridboxConnectorAddon/GridboxConnector/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def filter(self, record):
literal_msg['client_id'] = '***'
# Das modifizierte Dictionary zurück in einen String konvertieren
record.msg = json.dumps(literal_msg)
except json.JSONDecodeError:
except Exception as e:
# Wenn die Nachricht kein JSON ist, nichts tun
logging.error('Could not parse message as JSON')
logging.error(f"Error filtering sensitive data: {e}")
pass
return True

0 comments on commit 182b6bc

Please sign in to comment.