zrcadlo https://github.com/atscan/atscan
lot of improvements; chart in pds detail
This commit is contained in:
rodič
6410cd4d6f
revize
0d778b6150
3
Makefile
3
Makefile
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 [${
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
})*/
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Načítá se…
Odkázat v novém úkolu