add main.py; Dockerfile: build dependencies; TZ

This commit is contained in:
Daniel Langbein 2020-11-29 15:39:11 +01:00
parent 32d8158921
commit 5afe6af136
9 changed files with 109 additions and 23 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
/secret/*.txt /secret/*.txt
/data/*.xml /data/*.xml
src/__pycache__/ /src/__pycache__/
/plot/*.png

View File

@ -7,4 +7,7 @@
<orderEntry type="jdk" jdkName="Python 3.8 (xfconf-backup)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.8 (xfconf-backup)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PackageRequirementsSettings">
<option name="versionSpecifier" value="Greater or equal (&gt;=x.y.z)" />
</component>
</module> </module>

View File

@ -2,11 +2,39 @@ FROM python:3.8-alpine
WORKDIR /usr/src/ WORKDIR /usr/src/
COPY requirements.txt ./ RUN apk update && \
RUN pip3 install --no-cache-dir -r requirements.txt apk add \
tzdata \
make automake gcc g++ subversion python3-dev \
zlib-dev jpeg-dev freetype-dev lcms2-dev libwebp-dev tcl-dev tk-dev harfbuzz-dev \
fribidi-dev libimagequant-dev libxcb-dev && \
rm -rf /var/cache/apk/*
# source: https://serverfault.com/a/683651/537998
ENV TZ=Europe/Berlin
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
#COPY requirements.txt ./
#RUN pip3 install --no-cache-dir -r requirements.txt
# LDFLAGS required for "pip install pillow"
# otherwise this would be necessary:
## RUN ln -s /usr/lib/x86_64-linux-gnu/libz.so /lib/
## RUN ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /lib/
# source: https://github.com/python-pillow/Pillow/issues/3103#issuecomment-382634946
ENV LDFLAGS=-L/usr/lib/x86_64-linux-gnu/
RUN python3 -m pip install --no-cache-dir --upgrade pip
RUN python3 -m pip install --no-cache-dir --upgrade requests
RUN python3 -m pip install --no-cache-dir --upgrade setuptools
RUN python3 -m pip install --no-cache-dir --upgrade numpy
RUN python3 -m pip install --no-cache-dir --upgrade pillow
RUN python3 -m pip install --no-cache-dir --upgrade matplotlib
COPY ./src/ ./ COPY ./src/ ./
RUN chmod +x ./langfingaz/logMeetingData.py RUN chmod +x ./langfingaz/main.py
# unbuffered output option otherwise script sleeps before any output appears # unbuffered output option otherwise script sleeps before any output appears
CMD [ "python", "-u", "./langfingaz/logMeetingData.py" ] # python -u
ENTRYPOINT [ "python", "-u", "./langfingaz/main.py" ]
CMD [ "log-verbose" ]

View File

@ -2,9 +2,11 @@ version: '3.7'
services: services:
dk-gen: dk-gen:
build: . build: .
command: ["log"] # see main.py for available commandline arguments
environment: environment:
# pythonpath is required to import from self created modules (langfingaz) - PYTHONPATH=/usr/src/ # pythonpath is required to import from self created modules ("from langfingaz ...")
- PYTHONPATH=/usr/src/ - PYTHONUNBUFFERED=1
volumes: volumes:
- ./secret:/usr/secret - ./secret:/usr/secret
- ./data:/usr/data - ./data:/usr/data
- ./plot:/usr/plot

View File

@ -1 +1,2 @@
requests>=2.25.0 requests>=2.25.0
matplotlib>=3.3.3

View File

@ -1,5 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
import sys
import time import time
from pathlib import Path from pathlib import Path
@ -13,6 +14,8 @@ def sleepFiveMin(verbose=False):
if verbose: if verbose:
print(">> Sleeping for five minutes <<") print(">> Sleeping for five minutes <<")
sys.stdout.flush()
time.sleep(fiveMinutes) time.sleep(fiveMinutes)
@ -27,7 +30,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
meetings = parseMeetings.parseMeetingsData(meetingsStr) meetings = parseMeetings.parseMeetingsData(meetingsStr)
bbbStatus = parseMeetings.BbbStatus(meetings) bbbStatus = parseMeetings.BbbStatus(meetings)
bbbStatusStr = str(bbbStatus) bbbStatusStr = str(bbbStatus)
print(util.indentMultilineStr(bbbStatusStr)) print(util.indentMultilineStr(bbbStatusStr), flush=True)
sleepFiveMin(verbose=True) sleepFiveMin(verbose=True)
@ -35,7 +38,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
def v1(folder: Path = saveData.getDefaultFolder()): def v1(folder: Path = saveData.getDefaultFolder()):
while True: while True:
saveData.requestAndSaveMeetingData(folder) saveData.requestAndSaveMeetingData(folder)
print('.', end='') print('.', end='', flush=True)
sleepFiveMin() sleepFiveMin()

34
src/langfingaz/main.py Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/python3
from sys import argv
from langfingaz import plotMeetings
from langfingaz import logMeetingData
def main():
print("=== bbb-status ===")
print(">> given args: " + str(argv))
print()
usageStr = 'Usage:\n' + argv[0] + ' [log|log-verbose|plot]\n' + \
'\tlog: log BBB meeting data every 5 minutes;\n' + \
'\t prints one dot after each successfully saved file\n' + \
'\tlog-verbose: log BBB meeting every 5 minute and write current status to stdout\n' + \
'\tplot: saves a plot of the saved BBB meeting data\n'
if len(argv) != 2:
raise ValueError("Expected one commandline argument!")
if argv[1] == "log":
logMeetingData.v1()
elif argv[1] == "log-verbose":
logMeetingData.v2()
elif argv[1] == "plot":
plotMeetings.plotMeetings()
else:
print(usageStr)
exit(1)
if __name__ == '__main__':
main()

View File

@ -1,5 +1,6 @@
from pathlib import Path from pathlib import Path
from typing import List from typing import List
import numpy
import matplotlib.pyplot as plt # TODO import matplotlib.pyplot as plt # TODO
from datetime import datetime from datetime import datetime
@ -9,23 +10,28 @@ from langfingaz.parseMeetings import BbbStatus, Meeting
from langfingaz.util import fileUtil from langfingaz.util import fileUtil
def plotMeetings(folder: Path): def getDefaultPlotFolder() -> Path:
return fileUtil.getProjectBaseDir().joinpath("plot")
def plotMeetings(dataDir: Path = fileUtil.getProjectBaseDir().joinpath("data")):
bbbStati: List[BbbStatus] = [] bbbStati: List[BbbStatus] = []
for file in folder.iterdir(): for file in dataDir.iterdir():
if file.name.endswith(".xml"): if file.name.endswith(".xml"):
dataStr, t = loadData.loadData(file) dataStr, t = loadData.loadData(file)
meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr) meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr)
bbbStati.append(parseMeetings.BbbStatus(meetings, t)) bbbStati.append(parseMeetings.BbbStatus(meetings, t))
doPlotMeetings(bbbStati) image: Path = doPlotMeetings(bbbStati)
print("saved image at " + str(image))
def doPlotMeetings(bbbStati: List[BbbStatus]): def doPlotMeetings(bbbStati: List[BbbStatus]) -> Path:
time = [] # x-axis: time time = [] # x-axis: time
participants = [] # yAxis (1) participants = [] # yAxis (1)
videos = [] # yAxis (2) videos = [] # yAxis (2)
voices = [] # yAxis (3) voices = [] # yAxis (3)
for bbbStatus in bbbStati: for bbbStatus in bbbStati:
time.append(bbbStatus.pointOfTime) time.append(bbbStatus.pointOfTime)
@ -33,7 +39,6 @@ def doPlotMeetings(bbbStati: List[BbbStatus]):
videos.append(bbbStatus.videoCount) videos.append(bbbStatus.videoCount)
voices.append(bbbStatus.voiceParticipantCount) voices.append(bbbStatus.voiceParticipantCount)
# Note that even in the OO-style, we use `.pyplot.figure` to create the figure. # Note that even in the OO-style, we use `.pyplot.figure` to create the figure.
fig, ax = plt.subplots() # Create a figure and an axes. fig, ax = plt.subplots() # Create a figure and an axes.
ax.plot(time, participants, label='participants') # Plot some data on the axes. ax.plot(time, participants, label='participants') # Plot some data on the axes.
@ -44,9 +49,14 @@ def doPlotMeetings(bbbStati: List[BbbStatus]):
ax.set_title("BigBlueButton Statistics") # Add a title to the axes. ax.set_title("BigBlueButton Statistics") # Add a title to the axes.
ax.legend() # Add a legend. ax.legend() # Add a legend.
fig.savefig(fileUtil.setDatetimePrefix(fileUtil.getProjectBaseDir().joinpath("plot"), datetime.now())) image: Path = getDefaultPlotFolder().joinpath(
plt.show() "{}_until_{}".format(fileUtil.asString(time[0]), fileUtil.asString(time[-1]))
)
fig.savefig(image)
# plt.show()
return image
if __name__ == '__main__': if __name__ == '__main__':
plotMeetings(fileUtil.getProjectBaseDir().joinpath("data")) plotMeetings()

View File

@ -24,9 +24,13 @@ def __getDatetimePrefixLength() -> int:
return len("20200101_120030") # 1st January 2020, 12:00 and 30 seconds return len("20200101_120030") # 1st January 2020, 12:00 and 30 seconds
def asString(t: datetime) -> str:
return t.strftime('%Y%m%d_%H%M%S')
def setDatetimePrefix(file: Path, t: datetime) -> Path: def setDatetimePrefix(file: Path, t: datetime) -> Path:
# filename = file.name # filename = file.name
prefix = t.strftime('%Y%m%d_%H%M%S') prefix = asString(t)
filename = prefix + "_" + file.name filename = prefix + "_" + file.name
return file.parent.joinpath(filename) return file.parent.joinpath(filename)