Compare commits
No commits in common. "cb310967cd99c4c3782aa3b77d7f86c22a5c7583" and "cef451cb176a3d0150c3e468de42ad76d43240b1" have entirely different histories.
cb310967cd
...
cef451cb17
@ -1,11 +1,11 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import asyncio
|
|
||||||
import click
|
import click
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from IPython import start_ipython
|
from IPython import start_ipython
|
||||||
from snek.shell import Shell
|
|
||||||
from snek.app import Application
|
from snek.app import Application
|
||||||
|
|
||||||
|
|
||||||
@ -14,15 +14,6 @@ def cli():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
|
||||||
def maintenance():
|
|
||||||
async def run():
|
|
||||||
app = Application(db_path="sqlite:///snek.db")
|
|
||||||
await app.services.container.maintenance()
|
|
||||||
await app.services.channel_message.maintenance()
|
|
||||||
asyncio.run(run())
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.option(
|
@click.option(
|
||||||
"--db_path", default="snek.db", help="Database to initialize if not exists."
|
"--db_path", default="snek.db", help="Database to initialize if not exists."
|
||||||
@ -77,7 +68,9 @@ def serve(port, host, db_path):
|
|||||||
help="Database path for the application",
|
help="Database path for the application",
|
||||||
)
|
)
|
||||||
def shell(db_path):
|
def shell(db_path):
|
||||||
Shell(db_path).run()
|
app = Application(db_path=f"sqlite:///{db_path}")
|
||||||
|
start_ipython(argv=[], user_ns={"app": app})
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
cli()
|
cli()
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from snek.service.user import UserService
|
|||||||
from snek.service.user_property import UserPropertyService
|
from snek.service.user_property import UserPropertyService
|
||||||
from snek.service.util import UtilService
|
from snek.service.util import UtilService
|
||||||
from snek.system.object import Object
|
from snek.system.object import Object
|
||||||
from snek.service.statistics import StatisticsService
|
|
||||||
|
|
||||||
@functools.cache
|
@functools.cache
|
||||||
def get_services(app):
|
def get_services(app):
|
||||||
@ -39,7 +39,6 @@ def get_services(app):
|
|||||||
"channel_attachment": ChannelAttachmentService(app=app),
|
"channel_attachment": ChannelAttachmentService(app=app),
|
||||||
"container": ContainerService(app=app),
|
"container": ContainerService(app=app),
|
||||||
"push": PushService(app=app),
|
"push": PushService(app=app),
|
||||||
"statistics": StatisticsService(app=app),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -5,23 +5,6 @@ from snek.system.template import whitelist_attributes
|
|||||||
class ChannelMessageService(BaseService):
|
class ChannelMessageService(BaseService):
|
||||||
mapper_name = "channel_message"
|
mapper_name = "channel_message"
|
||||||
|
|
||||||
async def maintenance(self):
|
|
||||||
async for message in self.find():
|
|
||||||
updated_at = message["updated_at"]
|
|
||||||
html = message["html"]
|
|
||||||
await self.save(message)
|
|
||||||
|
|
||||||
self.mapper.db['channel_message'].upsert(
|
|
||||||
{
|
|
||||||
"uid": message["uid"],
|
|
||||||
"updated_at": updated_at,
|
|
||||||
},
|
|
||||||
["uid"],
|
|
||||||
)
|
|
||||||
if html != message["html"]:
|
|
||||||
print("Reredefined message", message["uid"])
|
|
||||||
|
|
||||||
|
|
||||||
async def create(self, channel_uid, user_uid, message, is_final=True):
|
async def create(self, channel_uid, user_uid, message, is_final=True):
|
||||||
model = await self.new()
|
model = await self.new()
|
||||||
|
|
||||||
|
|||||||
@ -43,14 +43,6 @@ class ContainerService(BaseService):
|
|||||||
async def start(self, channel_uid):
|
async def start(self, channel_uid):
|
||||||
return await self.compose.start(await self.get_container_name(channel_uid))
|
return await self.compose.start(await self.get_container_name(channel_uid))
|
||||||
|
|
||||||
async def maintenance(self):
|
|
||||||
async for channel in self.services.channel.find():
|
|
||||||
if not await self.get(channel["uid"]):
|
|
||||||
print("Creating container for channel", channel["uid"])
|
|
||||||
result = await self.create(channel_uid=channel["uid"])
|
|
||||||
print(result)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_status(self, channel_uid):
|
async def get_status(self, channel_uid):
|
||||||
return await self.compose.get_instance_status(await self.get_container_name(channel_uid))
|
return await self.compose.get_instance_status(await self.get_container_name(channel_uid))
|
||||||
|
|
||||||
@ -68,11 +60,6 @@ class ContainerService(BaseService):
|
|||||||
volumes=None,
|
volumes=None,
|
||||||
):
|
):
|
||||||
name = await self.get_container_name(channel_uid)
|
name = await self.get_container_name(channel_uid)
|
||||||
|
|
||||||
test = await self.compose.get_instance(name)
|
|
||||||
if test:
|
|
||||||
return test
|
|
||||||
|
|
||||||
self.compose.create_instance(
|
self.compose.create_instance(
|
||||||
name,
|
name,
|
||||||
image,
|
image,
|
||||||
@ -87,7 +74,6 @@ class ContainerService(BaseService):
|
|||||||
+ "/home/ubuntu"
|
+ "/home/ubuntu"
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
return await self.compose.get_instance(name)
|
|
||||||
|
|
||||||
async def create2(
|
async def create2(
|
||||||
self, id, name, status, resources=None, user_uid=None, path=None, readonly=False
|
self, id, name, status, resources=None, user_uid=None, path=None, readonly=False
|
||||||
|
|||||||
@ -1,91 +0,0 @@
|
|||||||
from snek.system.service import BaseService
|
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
class StatisticsService(BaseService):
|
|
||||||
|
|
||||||
def database(self):
|
|
||||||
db_path = self.app.db_path.split("///")[-1]
|
|
||||||
print(db_path)
|
|
||||||
conn = sqlite3.connect(db_path)
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# Existing analysis code...
|
|
||||||
def get_table_columns(table_name):
|
|
||||||
cursor.execute(f"PRAGMA table_info({table_name})")
|
|
||||||
return cursor.fetchall()
|
|
||||||
|
|
||||||
tables = [
|
|
||||||
'http_access', 'user', 'channel', 'channel_member', 'broadcast',
|
|
||||||
'channel_message', 'notification', 'repository', 'test', 'drive',
|
|
||||||
'user_property', 'a', 'channel_attachment', 'push_registration'
|
|
||||||
]
|
|
||||||
|
|
||||||
for table in tables:
|
|
||||||
print(f"\n--- Statistics for table: {table} ---")
|
|
||||||
columns = get_table_columns(table)
|
|
||||||
cursor.execute(f"SELECT COUNT(*) FROM {table}")
|
|
||||||
total_rows = cursor.fetchone()[0]
|
|
||||||
print(f"Total rows: {total_rows}")
|
|
||||||
|
|
||||||
for col in columns:
|
|
||||||
cid, name, col_type, notnull, dflt_value, pk = col
|
|
||||||
col_type_upper = col_type.upper()
|
|
||||||
|
|
||||||
cursor.execute(f"SELECT COUNT(DISTINCT '{name}') FROM {table}")
|
|
||||||
distinct_count = cursor.fetchone()[0]
|
|
||||||
print(f"\nColumn: {name} ({col_type})")
|
|
||||||
print(f"Distinct values: {distinct_count}")
|
|
||||||
|
|
||||||
if 'INT' in col_type_upper or 'BIGINT' in col_type_upper or 'FLOAT' in col_type_upper:
|
|
||||||
cursor.execute(f"SELECT MIN('{name}'), MAX('{name}'), AVG('{name}') FROM {table} WHERE '{name}' IS NOT NULL")
|
|
||||||
min_val, max_val, avg_val = cursor.fetchone()
|
|
||||||
print(f"Min: {min_val}, Max: {max_val}, Avg: {avg_val}")
|
|
||||||
|
|
||||||
elif 'TEXT' in col_type_upper and ('date' in name.lower() or 'time' in name.lower() or 'created' in name.lower() or 'updated' in name.lower() or 'on' in name.lower()):
|
|
||||||
cursor.execute(f"SELECT MIN({name}), MAX({name}) FROM {table} WHERE {name} IS NOT NULL")
|
|
||||||
min_date, max_date = cursor.fetchone()
|
|
||||||
print(f"Earliest: {min_date}, Latest: {max_date}")
|
|
||||||
|
|
||||||
elif 'TEXT' in col_type_upper:
|
|
||||||
cursor.execute(f"SELECT LENGTH({name}) FROM {table} WHERE {name} IS NOT NULL")
|
|
||||||
lengths = [len_row[0] for len_row in cursor.fetchall()]
|
|
||||||
if lengths:
|
|
||||||
avg_length = sum(lengths) / len(lengths)
|
|
||||||
max_length = max(lengths)
|
|
||||||
min_length = min(lengths)
|
|
||||||
print(f"Avg length: {avg_length:.2f}, Max length: {max_length}, Min length: {min_length}")
|
|
||||||
else:
|
|
||||||
print("No data to compute length statistics.")
|
|
||||||
|
|
||||||
# New statistics functions
|
|
||||||
def get_time_series_stats(table_name, date_column):
|
|
||||||
cursor.execute(f"SELECT strftime('%Y-%m-%d', {date_column}) AS day, COUNT(*) FROM {table_name} GROUP BY day")
|
|
||||||
return cursor.fetchall()
|
|
||||||
|
|
||||||
def get_count_created(table_name, date_column):
|
|
||||||
cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
|
|
||||||
return cursor.fetchone()[0]
|
|
||||||
|
|
||||||
def get_channels_per_user():
|
|
||||||
cursor.execute("SELECT user_uid, COUNT(*) AS channel_count FROM channel_member GROUP BY user_uid ORDER BY channel_count DESC")
|
|
||||||
return cursor.fetchall()
|
|
||||||
|
|
||||||
def get_online_users():
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM user WHERE last_ping >= datetime('now', '-5 minutes')")
|
|
||||||
return cursor.fetchone()[0]
|
|
||||||
|
|
||||||
# Example usage of new functions
|
|
||||||
messages_per_day = get_time_series_stats('channel_message', 'created_at')
|
|
||||||
users_created = get_count_created('user', 'created_at')
|
|
||||||
channels_created = get_count_created('channel', 'created_at')
|
|
||||||
channels_per_user = get_channels_per_user()
|
|
||||||
online_users = get_online_users()
|
|
||||||
|
|
||||||
# Print or store these stats as needed
|
|
||||||
print("\nMessages per day:", messages_per_day)
|
|
||||||
print("Total users created:", users_created)
|
|
||||||
print("Total channels created:", channels_created)
|
|
||||||
print("Channels per user (top):", channels_per_user[:10])
|
|
||||||
print("Currently online users:", online_users)
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
from snek.app import Application
|
|
||||||
from IPython import start_ipython
|
|
||||||
|
|
||||||
class Shell:
|
|
||||||
def __init__(self,db_path):
|
|
||||||
self.app = Application(db_path=f"sqlite:///{db_path}")
|
|
||||||
|
|
||||||
async def maintenance(self):
|
|
||||||
await self.app.services.container.maintenance()
|
|
||||||
await self.app.services.channel_message.maintenance()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
ns = {
|
|
||||||
"app": self.app,
|
|
||||||
"maintenance": self.maintenance
|
|
||||||
}
|
|
||||||
start_ipython(argv=[], user_ns=ns)
|
|
||||||
@ -84,8 +84,6 @@ class ComposeFileManager:
|
|||||||
|
|
||||||
async def get_instance(self, name):
|
async def get_instance(self, name):
|
||||||
instance = self.compose.get("services", {}).get(name)
|
instance = self.compose.get("services", {}).get(name)
|
||||||
if not instance:
|
|
||||||
return None
|
|
||||||
instance = json.loads(json.dumps(instance,default=str))
|
instance = json.loads(json.dumps(instance,default=str))
|
||||||
instance['status'] = await self.get_instance_status(name)
|
instance['status'] = await self.get_instance_status(name)
|
||||||
return instance
|
return instance
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user