lot of improvements; chart in pds detail

This commit is contained in:
tree 2023-06-30 16:01:52 +00:00
rodič 6410cd4d6f
revize 0d778b6150
16 změnil soubory, kde provedl 1093 přidání a 13 odebrání

Zobrazit soubor

@ -33,6 +33,9 @@ install:
deno install --unstable -A -f -n ats ./cli/ats.js
deno install --unstable -A -f -n ats-repo ./cli/ats-repo.js
typesense-init:
deno run --unstable --allow-net --allow-read ./backend/typesense-init.js
format:
cd backend && deno fmt **.js
cd frontend && npm run format

Zobrazit soubor

@ -74,6 +74,16 @@ router
}
item.host = item.url.replace(/^https?:\/\//, "");
item.fed = findPDSFed(item);
const query = `
from(bucket: "ats-stats")
|> range(start: -1d)
|> filter(fn: (r) => r["_measurement"] == "pds_response_time")
|> filter(fn: (r) => r["pds"] == "${item.host}")
|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)`;
item.responseTimesDay = await ats.influxQuery.collectRows(query);
ctx.response.body = item;
perf(ctx);
})
@ -126,6 +136,7 @@ router
}
//console.log(JSON.stringify(query, null, 2), { sort, limit });
console.log(JSON.stringify(query));
const count = await ats.db.did.count(query);
for (
@ -184,6 +195,17 @@ router
ctx.response.body = out;
perf(ctx);
})
.get("/_metrics", async (ctx) => {
const metrics = {
pds_count: [await ats.db.pds.count(), "PDS count", "counter"],
did_count: [await ats.db.did.count(), "DID count", "counter"],
};
ctx.response.body = Object.keys(metrics).map((m) => {
const [data, help, type] = metrics[m];
return `# HELP ${m} ${help}\n# TYPE ${m} ${type}\n${m} ${data}\n`;
}).join("\n");
perf(ctx);
})
.get("/:id.svg", async (ctx) => {
if (!ctx.params.id.startsWith("did:")) {
return ctx.status = 404;

Zobrazit soubor

@ -2,6 +2,7 @@
import { parse, stringify } from "https://deno.land/std@0.184.0/yaml/mod.ts";
import { MongoClient } from "npm:mongodb";
import "https://deno.land/std@0.192.0/dotenv/load.ts";
import {InfluxDB} from 'npm:@influxdata/influxdb-client'
const BSKY_OFFICIAL_PDS = [
"https://bsky.social",
@ -17,6 +18,9 @@ export class ATScan {
async init() {
await this.ecosystemLoad();
const influxConfig = {url: Deno.env.get('INFLUXDB_HOST'), token: Deno.env.get('INFLUXDB_TOKEN')}
this.influx = new InfluxDB(influxConfig);
this.influxQuery = this.influx.getQueryApi(Deno.env.get('INFLUXDB_ORG'))
this.client = new MongoClient(Deno.env.get("MONGODB_URL"));
await this.client.connect();
console.log(`Connected to MongoDB: ${Deno.env.get("MONGODB_URL")}`);
@ -138,4 +142,20 @@ export class ATScan {
console.log("Starting daemon ..");
const ecosInt = setInterval(() => this.ecosystemLoad(), 30 * 1000);
}
async writeInflux (name, type, value, tags = []) {
const point = `${name},${tags.map(t => t.join('=')).join(', ')} value=${value} ${Date.now()}`;
const resp = await fetch(`${Deno.env.get('INFLUXDB_HOST')}/api/v2/write?org=${Deno.env.get('INFLUXDB_ORG')}&bucket=${Deno.env.get('INFLUXDB_BUCKET')}&precision=ms`, {
method: 'POST',
headers: {
Authorization: `Token ${Deno.env.get('INFLUXDB_TOKEN')}`
},
body: point
})
if (resp.status > 299) {
console.error('influx error: '+resp.status, Deno.env.get('INFLUXDB_TOKEN'))
console.error(await resp.json())
}
return true
}
}

Zobrazit soubor

@ -3,7 +3,8 @@ import { pooledMap } from "https://deno.land/std/async/mod.ts";
import { timeout } from "./lib/utils.js";
import "https://deno.land/std@0.192.0/dotenv/load.ts";
const wait = 60 * 5;
const WAIT = 1000 * 60 * 2;
const TIMEOUT = 5000;
async function crawl(ats) {
const arr = await ats.db.pds.find().toArray();
@ -54,7 +55,7 @@ async function crawl(ats) {
const url = `${i.url}/xrpc/com.atproto.server.describeServer`;
try {
[res, ms] = await timeout(
5000,
TIMEOUT,
fetch(url, {
headers: {
"User-Agent": "ATScan Crawler",
@ -81,6 +82,12 @@ async function crawl(ats) {
await ats.db.pds.updateOne({ url: i.url }, {
$set: dbSet,
});
if (ms && Number(ms) > 0) {
await ats.writeInflux("pds_response_time", "intField", Number(ms), [[
"pds",
host,
]]);
}
console.log(
`-> ${i.url} ${ms ? "[" + ms + "ms]" : ""} ${
err ? "error = " + err : ""
@ -102,8 +109,8 @@ if (Deno.args[0] === "daemon") {
await crawl(ats);
console.log(`Initial crawl done`);
ats.debug = false;
console.log(`Processing events [wait=${wait}s] ..`);
setInterval(() => crawl(ats), wait * 1000);
console.log(`Processing events [wait=${WAIT / 1000}s] ..`);
setInterval(() => crawl(ats), WAIT);
} else {
const ats = new ATScan({ debug: true });
await ats.init();

Zobrazit soubor

@ -1,23 +1,27 @@
import { ensureDir } from "https://deno.land/std@0.192.0/fs/ensure_dir.ts";
import { join } from "https://deno.land/std@0.192.0/path/posix.ts";
import { pooledMap } from "https://deno.land/std/async/mod.ts";
import * as fsize from "npm:filesize";
import { ATScan } from "./lib/atscan.js";
import { inspect } from "./lib/car.js";
import { timeout } from "./lib/utils.js";
import _ from "npm:lodash";
const filesize = fsize.filesize;
const DB_PATH = "./backend/db/repo";
await ensureDir(DB_PATH);
async function crawl(ats) {
let expiry = new Date();
expiry.setDate(expiry.getDate() - 1);
expiry.setDate(expiry.getDate() - 10);
const dids = await ats.db.did.find({
//'pds': { $in: [ 'https://test-pds.gwei.cz' ] },
$or: [{ "repo.time": { $lte: expiry } }, { "repo": { $exists: false } }],
}).limit(10000).toArray();
const results = pooledMap(4, _.shuffle(dids), async (didInfo) => {
const results = pooledMap(8, _.shuffle(dids), async (didInfo) => {
const did = didInfo.did;
const signingKey = didInfo.revs[didInfo.revs.length - 1].operation
.verificationMethods?.atproto;
@ -89,7 +93,7 @@ async function crawl(ats) {
console.log(
`[${did}@${pds}] displayName=${
JSON.stringify(repo.profile?.displayName)
}`,
} [${filesize(repo.size)}]`,
);
/*console.log(
`[${did}@${pds}] Done [${

85
backend/typesense/package-lock.json vygenerováno Normal file
Zobrazit soubor

@ -0,0 +1,85 @@
{
"name": "typesense",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "typesense",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"typesense": "^1.5.4"
}
},
"node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"peer": true,
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"dependencies": {
"follow-redirects": "^1.14.8"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/loglevel": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz",
"integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==",
"engines": {
"node": ">= 0.6.0"
},
"funding": {
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/loglevel"
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"peer": true
},
"node_modules/typesense": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/typesense/-/typesense-1.5.4.tgz",
"integrity": "sha512-51/lyTWbn4NmH4oe3dXv4xSi9eqZwOB7/hXnzyGl84pgFn2MdeeMKb4Lr7z8fUNFmS0TNl7rujaIHRmNR1f2ZA==",
"dependencies": {
"axios": "^0.26.0",
"loglevel": "^1.8.0"
},
"peerDependencies": {
"@babel/runtime": "^7.17.2"
}
}
}
}

Zobrazit soubor

@ -0,0 +1,14 @@
{
"name": "typesense",
"version": "1.0.0",
"description": "",
"main": "typesense-init.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"typesense": "^1.5.4"
}
}

Zobrazit soubor

@ -0,0 +1,24 @@
const Typesense = require('typesense')
let client = new Typesense.Client({
'nodes': [{
'host': 'localhost', // For Typesense Cloud use xxx.a1.typesense.net
'port': '8108', // For Typesense Cloud use 443
'protocol': 'http' // For Typesense Cloud use https
}],
'apiKey': 'Kaey9ahMo7xoob1haivaithe2Aighoo3azohl2Joo5Aemoh4aishoogugh3Oowim',
'connectionTimeoutSeconds': 2
})
/*const schema = {
name: 'dids',
fields: [
{ name: 'did', type: 'string' },
{ name: 'handles', type: 'string[]' },
]
}
client.collections().create(schema)
.then(function (data) {
console.log(data)
})*/

37
frontend/package-lock.json vygenerováno
Zobrazit soubor

@ -1,12 +1,12 @@
{
"name": "atscan-fe",
"version": "0.4.4-alpha",
"version": "0.5.0-alpha",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "atscan-fe",
"version": "0.4.4-alpha",
"version": "0.5.0-alpha",
"dependencies": {
"js-yaml": "^4.1.0"
},
@ -19,6 +19,7 @@
"@tailwindcss/forms": "^0.5.3",
"autoprefixer": "^10.4.14",
"date-fns": "^2.30.0",
"echarts": "^5.4.2",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.26.0",
@ -32,6 +33,7 @@
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.8.1",
"svelte": "^3.54.0",
"svelte-echarts": "^0.0.5",
"tailwindcss": "^3.3.2",
"vite": "^4.3.0"
}
@ -1372,6 +1374,16 @@
"node": ">=6.0.0"
}
},
"node_modules/echarts": {
"version": "5.4.2",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.2.tgz",
"integrity": "sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==",
"dev": true,
"dependencies": {
"tslib": "2.3.0",
"zrender": "5.4.3"
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.440",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz",
@ -3037,6 +3049,12 @@
"node": ">= 8"
}
},
"node_modules/svelte-echarts": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/svelte-echarts/-/svelte-echarts-0.0.5.tgz",
"integrity": "sha512-CPrl2t3M6LROkEetKOtcdoaUyHrc80W47EZGoj4bDWdVBDqiGRkqwjyYW7+KOkrpzJRJorHEgQidsBQ3d765uQ==",
"dev": true
},
"node_modules/svelte-eslint-parser": {
"version": "0.31.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.31.0.tgz",
@ -3206,6 +3224,12 @@
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"dev": true
},
"node_modules/tweetnacl": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
@ -3412,6 +3436,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zrender": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.4.3.tgz",
"integrity": "sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==",
"dev": true,
"dependencies": {
"tslib": "2.3.0"
}
}
}
}

Zobrazit soubor

@ -18,6 +18,7 @@
"@tailwindcss/forms": "^0.5.3",
"autoprefixer": "^10.4.14",
"date-fns": "^2.30.0",
"echarts": "^5.4.2",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.26.0",
@ -31,6 +32,7 @@
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.8.1",
"svelte": "^3.54.0",
"svelte-echarts": "^0.0.5",
"tailwindcss": "^3.3.2",
"vite": "^4.3.0"
},

Zobrazit soubor

@ -0,0 +1,73 @@
<script lang="ts" context="module">
import * as echarts from 'echarts';
export { echarts };
import * as darkTheme from '../theme-dark.json';
import * as lightTheme from '../theme-light.json';
export type EChartsOptions = echarts.EChartsOption;
export type EChartsTheme = string | object;
export type EChartsRenderer = 'canvas' | 'svg';
echarts.registerTheme('darkTheme', JSON.parse(JSON.stringify(darkTheme)));
echarts.registerTheme('lightTheme', JSON.parse(JSON.stringify(lightTheme)));
export type ChartOptions = {
theme?: EChartsTheme;
renderer?: EChartsRenderer;
options: EChartsOptions;
};
const DEFAULT_OPTIONS: Partial<ChartOptions> = {
theme: 'lightTheme',
renderer: 'canvas'
};
export function chartable(element: HTMLElement, echartOptions: ChartOptions) {
const { theme, renderer, options } = {
...DEFAULT_OPTIONS,
...echartOptions
};
const elemHtmlClasses = document.documentElement.classList;
const echartsInstance = echarts.init(
element,
elemHtmlClasses.contains('dark') ? 'darkTheme' : 'lightTheme',
{ renderer }
);
echartsInstance.setOption(options);
function handleResize() {
echartsInstance.resize();
}
window.addEventListener('resize', handleResize);
return {
destroy() {
echartsInstance.dispose();
window.removeEventListener('resize', handleResize);
},
update(newOptions: ChartOptions) {
echartsInstance.setOption({
...echartOptions.options,
...newOptions.options
});
}
};
}
</script>
<script lang="ts">
export let options: echarts.EChartsOption;
export let { theme, renderer } = DEFAULT_OPTIONS;
</script>
<div class="chart" use:chartable={{ renderer, theme, options }} />
<style>
.chart {
height: 100%;
width: 100%;
}
</style>

Zobrazit soubor

@ -1,8 +1,9 @@
<script>
import { CodeBlock, clipboard } from '@skeletonlabs/skeleton';
export let model = 'pds';
export let data;
export let model = 'pds';
export let hide = false;
const models = {
pds: { url: `${data.config.api}/pds/%`, key: 'host' },
@ -15,7 +16,9 @@
</script>
<h2 class="h2">Source</h2>
<CodeBlock code={JSON.stringify(data.item, null, 2)} language="json" />
{#if !hide}
<CodeBlock code={JSON.stringify(data.item, null, 2)} language="json" />
{/if}
<div>
<p>You can get this data as JSON by making a simple HTTP GET request to our API endpoint:</p>

Zobrazit soubor

@ -0,0 +1,363 @@
{
"color": ["#3fb1e3", "#6be6c1", "#626c91", "#a0a7e6", "#c4ebad", "#96dee8"],
"backgroundColor": "rgba(41,52,65,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#ffffff"
},
"subtextStyle": {
"color": "#dddddd"
}
},
"line": {
"itemStyle": {
"borderWidth": "4"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"radar": {
"itemStyle": {
"borderWidth": "4"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
},
"pie": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"scatter": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"parallel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"sankey": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"funnel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"gauge": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"candlestick": {
"itemStyle": {
"color": "#fc97af",
"color0": "transparent",
"borderColor": "#fc97af",
"borderColor0": "#87f7cf",
"borderWidth": "2"
}
},
"graph": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"lineStyle": {
"width": "1",
"color": "#ffffff"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true,
"color": [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2"
],
"label": {
"color": "#293441"
}
},
"map": {
"itemStyle": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#893448"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
},
"label": {
"color": "rgb(137,52,72)"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#893448"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
},
"label": {
"color": "rgb(137,52,72)"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#aaaaaa"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#52525b"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#aaaaaa"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#52525b"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#aaaaaa"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#52525b"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#aaaaaa"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#52525b"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#999999"
},
"emphasis": {
"iconStyle": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#87f7cf",
"width": 1
},
"itemStyle": {
"color": "#87f7cf",
"borderWidth": 1
},
"controlStyle": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#fc97af",
"borderColor": "#fc97af"
},
"label": {
"color": "#87f7cf"
},
"emphasis": {
"itemStyle": {
"color": "#f7f494"
},
"controlStyle": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
},
"label": {
"color": "#87f7cf"
}
}
},
"visualMap": {
"color": ["#fc97af", "#87f7cf"]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(114,204,255,1)",
"fillerColor": "rgba(114,204,255,0.2)",
"handleColor": "#72ccff",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"color": "#293441"
},
"emphasis": {
"label": {
"color": "#293441"
}
}
}
}

Zobrazit soubor

@ -0,0 +1,363 @@
{
"color": ["#3fb1e3", "#6be6c1", "#626c91", "#a0a7e6", "#c4ebad", "#96dee8"],
"backgroundColor": "rgba(41,52,65,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#333333"
},
"subtextStyle": {
"color": "#dddddd"
}
},
"line": {
"itemStyle": {
"borderWidth": "4"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"radar": {
"itemStyle": {
"borderWidth": "4"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
},
"pie": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"scatter": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"parallel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"sankey": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"funnel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"gauge": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"candlestick": {
"itemStyle": {
"color": "#fc97af",
"color0": "transparent",
"borderColor": "#fc97af",
"borderColor0": "#87f7cf",
"borderWidth": "2"
}
},
"graph": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"lineStyle": {
"width": "1",
"color": "#ffffff"
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true,
"color": [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2"
],
"label": {
"color": "#293441"
}
},
"map": {
"itemStyle": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#893448"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
},
"label": {
"color": "rgb(137,52,72)"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#893448"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
},
"label": {
"color": "rgb(137,52,72)"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#1e293b"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#cbd5e1"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#1e293b"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#cbd5e1"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#1e293b"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#cbd5e1"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#1e293b"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#cbd5e1"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#999999"
},
"emphasis": {
"iconStyle": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#1e293b"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#87f7cf",
"width": 1
},
"itemStyle": {
"color": "#87f7cf",
"borderWidth": 1
},
"controlStyle": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#fc97af",
"borderColor": "#fc97af"
},
"label": {
"color": "#87f7cf"
},
"emphasis": {
"itemStyle": {
"color": "#f7f494"
},
"controlStyle": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
},
"label": {
"color": "#87f7cf"
}
}
},
"visualMap": {
"color": ["#fc97af", "#87f7cf"]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(114,204,255,1)",
"fillerColor": "rgba(114,204,255,0.2)",
"handleColor": "#72ccff",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"color": "#293441"
},
"emphasis": {
"label": {
"color": "#293441"
}
}
}
}

Zobrazit soubor

@ -53,3 +53,8 @@ export function getDIDProfileUrl(fed, item) {
export function filesize(size) {
return _filesize(size);
}
export function isDarkMode(document) {
const elemHtmlClasses = document.documentElement.classList;
return elemHtmlClasses.contains('dark');
}

Zobrazit soubor

@ -1,9 +1,11 @@
<script>
import Breadcrumb from '$lib/components/Breadcrumb.svelte';
import DIDTable from '$lib/components/DIDTable.svelte';
import { formatNumber, dateDistance, getFlagEmoji } from '$lib/utils.js';
import { formatNumber, dateDistance, getFlagEmoji, isDarkMode } from '$lib/utils.js';
import SourceSection from '$lib/components/SourceSection.svelte';
import BasicPage from '$lib/components/BasicPage.svelte';
import Chart from '$lib/components/Chart.svelte';
import { onMount } from 'svelte';
export let data;
@ -87,6 +89,58 @@
link: `/pds?q=fed:${item.fed}`
});
}
$: chartResponseTimes = {};
let darkMode = null;
onMount(() => {
darkMode = isDarkMode(document);
chartResponseTimes = {
animationDuration: 500,
title: {
text: `${item.host} response times in last 24 hours`
},
tooltip: {
trigger: 'axis',
formatter: '{b}: {c} ms'
},
legend: {
data: [chartHost]
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: item.responseTimesDay?.map((r) => r._time) || []
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} ms'
}
},
series: [
{
name: chartHost,
type: 'line',
stack: 'ms',
data: item.responseTimesDay?.map((r) => r._value) || []
}
]
};
});
console.log(darkMode);
const chartHost = 'Central Europe (CZ)';
</script>
<BasicPage {data} title={item.host} {breadcrumb}>
@ -108,6 +162,11 @@
{/each}
</div>
<h2 class="h2">Response times</h2>
<div class="w-full h-64">
<Chart options={chartResponseTimes} />
</div>
<h2 class="h2">
<a href="/dids?q=pds:{item.host}">DIDs</a>
<span class="font-normal text-2xl">({formatNumber(data.dids.count)})</span>
@ -123,5 +182,5 @@
</div>
{/if}
<SourceSection {data} model="pds" />
<SourceSection {data} model="pds" hide="true" />
</BasicPage>