docs: add website more language: de, fr, ja, zh-Hans

This commit is contained in:
moonrailgun 2024-10-05 17:52:02 +08:00
parent f5933ec054
commit 7bda5420c5
88 changed files with 4547 additions and 7 deletions

View File

@ -10,24 +10,24 @@ Learn more about sentry in [sentry.io](https://sentry.io/)
Click `Settings` => `Integrations` => `Create New Integration`
![](./assets/sentry1.png)
![](/img/docs/sentry/sentry1.png)
Create a `Internal Integration` application
![](./assets/sentry2.png)
![](/img/docs/sentry/sentry2.png)
Input name `Tianji` and put in webhook url into form.
![](./assets/sentry3.png)
![](/img/docs/sentry/sentry3.png)
Don't forget enable `Alert Rule Action`
![](./assets/sentry4.png)
![](/img/docs/sentry/sentry4.png)
Then, add issue read `permission`, and webhook add `issue` and `error`
![](./assets/sentry5.png)
![](/img/docs/sentry/sentry5.png)
Finally, you can create a alert rule, and you can see `Tianji` in notification section dropdown list
![](./assets/sentry6.png)
![](/img/docs/sentry/sentry6.png)

View File

@ -34,7 +34,7 @@ const config: Config = {
// to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
locales: ['en', 'fr', 'de', 'ja', 'zh-Hans'],
},
presets: [
@ -110,6 +110,10 @@ const config: Config = {
label: 'GitHub',
position: 'right',
},
{
type: 'localeDropdown',
position: 'right',
},
],
},
footer: {

309
website/i18n/de/code.json Normal file
View File

@ -0,0 +1,309 @@
{
"theme.ErrorPageContent.title": {
"message": "Die Seite ist abgestürzt.",
"description": "The title of the fallback page when the page crashed"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "Zurück nach oben scrollen",
"description": "The ARIA label for the back to top button"
},
"theme.blog.archive.title": {
"message": "Archiv",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "Archiv",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.paginator.navAriaLabel": {
"message": "Navigation der Blog-Listenseite",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "Neuere Einträge",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "Ältere Einträge",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "Blog Post Seiten Navigation",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "Neuer Post",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "Älterer Post",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.tags.tagsPageLink": {
"message": "Alle Tags anzeigen",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "Umschalten zwischen dunkler und heller Ansicht (momentan {mode})",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "dunkler Modus",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "heller Modus",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "Breadcrumbs",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription.plurals": {
"message": "1 Eintrag|{count} Einträge",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "Dokumentation Seiten",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "Zurück",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "Weiter",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "Ein doc getaggt|{count} docs getaggt",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "{nDocsTagged} mit \"{tagName}\"",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "Version: {versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "Das ist die unveröffentlichte Dokumentation für {siteTitle} {versionLabel}.",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "Das ist die Dokumentation für {siteTitle} {versionLabel} und wird nicht weiter gewartet.",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "Für die aktuellste Dokumentation bitte auf {latestVersionLink} ({versionLabel}) gehen.",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "letzte Version",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "Diese Seite bearbeiten",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "Direkter Link zur {heading}",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": " am {date}",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": " von {user}",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "Letztes Update{atDate}{byUser}",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "Versionen",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.NotFound.title": {
"message": "Seite nicht gefunden",
"description": "The title of the 404 page"
},
"theme.tags.tagsListLabel": {
"message": "Tags:",
"description": "The label alongside a tag list"
},
"theme.admonition.caution": {
"message": "vorsicht",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.admonition.danger": {
"message": "gefahr",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "info",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.note": {
"message": "hinweis",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "tipp",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.warning": {
"message": "warnung",
"description": "The default label used for the Warning admonition (:::warning)"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "Schließen",
"description": "The ARIA label for close button of announcement bar"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "Navigation der letzten Beiträge im Blog",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "Kopiert",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "In die Zwischenablage kopieren",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "Kopieren",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "Toggle word wrap",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.expandCategoryAriaLabel": {
"message": "Expand sidebar category '{label}'",
"description": "The ARIA label to expand the sidebar category"
},
"theme.DocSidebarItem.collapseCategoryAriaLabel": {
"message": "Collapse sidebar category '{label}'",
"description": "The ARIA label to collapse the sidebar category"
},
"theme.NavBar.navAriaLabel": {
"message": "Main",
"description": "The ARIA label for the main navigation"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "Sprachen",
"description": "The label for the mobile language switcher dropdown"
},
"theme.NotFound.p1": {
"message": "Wir konnten nicht finden, wonach Sie gesucht haben.",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "Bitte kontaktieren Sie den Besitzer der Seite, die Sie mit der ursprünglichen URL verlinkt hat, und teilen Sie ihm mit, dass der Link nicht mehr funktioniert.",
"description": "The 2nd paragraph of the 404 page"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "Auf dieser Seite",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.blog.post.readMore": {
"message": "Mehr lesen",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.readMoreLabel": {
"message": "Mehr lesen über {title}",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readingTime.plurals": {
"message": "Eine Minute Lesezeit|{readingTime} Minuten Lesezeit",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.breadcrumbs.home": {
"message": "Home page",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "Seitenleiste einklappen",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "Seitenleiste einklappen",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.navAriaLabel": {
"message": "Docs sidebar",
"description": "The ARIA label for the sidebar navigation"
},
"theme.docs.sidebar.closeSidebarButtonAriaLabel": {
"message": "Close navigation bar",
"description": "The ARIA label for close button of mobile sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← Zurück zum Hauptmenü",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
"message": "Toggle navigation bar",
"description": "The ARIA label for hamburger menu button of mobile navigation"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "Seitenleiste ausklappen",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "Seitenleiste ausklappen",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.blog.post.plurals": {
"message": "Ein Post|{count} Posts",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "{nPosts} getaggt mit \"{tagName}\"",
"description": "The title of the page for a blog tag"
},
"theme.blog.author.pageTitle": {
"message": "{authorName} - {nPosts}",
"description": "The title of the page for a blog author"
},
"theme.blog.authorsList.pageTitle": {
"message": "Authors",
"description": "The title of the authors page"
},
"theme.blog.authorsList.viewAll": {
"message": "View All Authors",
"description": "The label of the link targeting the blog authors page"
},
"theme.contentVisibility.unlistedBanner.title": {
"message": "Unlisted page",
"description": "The unlisted content banner title"
},
"theme.contentVisibility.unlistedBanner.message": {
"message": "This page is unlisted. Search engines will not index it, and only users having a direct link can access it.",
"description": "The unlisted content banner message"
},
"theme.contentVisibility.draftBanner.title": {
"message": "Draft page",
"description": "The draft content banner title"
},
"theme.contentVisibility.draftBanner.message": {
"message": "This page is a draft. It will only be visible in dev and be excluded from the production build.",
"description": "The draft content banner message"
},
"theme.ErrorPageContent.tryAgain": {
"message": "Nochmal versuchen",
"description": "The label of the button to try again rendering when the React error boundary captures an error"
},
"theme.common.skipToMainContent": {
"message": "Zum Hauptinhalt springen",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsPageTitle": {
"message": "Tags",
"description": "The title of the tag list page"
}
}

View File

@ -0,0 +1,14 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

View File

@ -0,0 +1,46 @@
{
"version.label": {
"message": "Next",
"description": "The label for version current"
},
"sidebar.tutorialSidebar.category.Install": {
"message": "Installieren",
"description": "The label for category Install in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Kubernetes": {
"message": "Kubernetes",
"description": "The label for category Kubernetes in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Website": {
"message": "Webseite",
"description": "The label for category Website in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Framework": {
"message": "Rahmen",
"description": "The label for category Framework in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Monitor": {
"message": "Monitor",
"description": "The label for category Monitor in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Notification": {
"message": "Benachrichtigung",
"description": "The label for category Notification in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Server Status": {
"message": "Serverstatus",
"description": "The label for category Server Status in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Telemetry": {
"message": "Telemetrie",
"description": "The label for category Telemetry in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Feed": {
"message": "Futter",
"description": "The label for category Feed in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Develop": {
"message": "Entwickeln",
"description": "The label for category Develop in sidebar tutorialSidebar"
}
}

View File

@ -0,0 +1,38 @@
---
sidebar_position: 1
_i18n_hash: f20c701ad093f995d1aad2b2b37ae5ec
---
# Vorbereitung zur Entwicklung
## Datenbank vorbereiten, die Docker verwendet
```bash
docker run --name tianji-pg -e POSTGRES_DB=tianji -e POSTGRES_USER=tianji -e POSTGRES_PASSWORD=tianji -d postgres:15.4-alpine
```
## .env-Datei vorbereiten
```bash
cp .env.example src/server/.env
```
Konfiguriere `DATABASE_URL` mit `postgresql://tianji:tianji@localhost:5432/tianji?schema=public`
So sieht es aus:
```ini
DATABASE_URL="postgresql://tianji:tianji@localhost:5432/tianji?schema=public"
ALLOW_OPENAPI=true
```
## Datenbankstruktur vorbereiten
Jetzt kannst du auf die Datenbank zugreifen und folgendes ausführen:
```bash
cd src/server && pnpm db:migrate:apply
```
## Standardkonto
Das Standardkonto ist `admin`/`admin`

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: c65e22ae3d729a07b0b23f525a89b8ca
---
# Umgebung
Hier ist die Umgebung, die du in Docker konfigurieren kannst
| Name | Standardwert | Beschreibung |
| ---- | ---- | ----- |
| JWT_SECRET | - | Ein zufälliger String, der zur Berechnung des geheimen Schlüssels verwendet wird |
| ALLOW_REGISTER | false | Ob die Registrierung von Benutzerkonten erlaubt ist |
| ALLOW_OPENAPI | false | Ob die OpenAPI erlaubt ist, die Daten abrufen oder posten kann, ähnlich wie du mit der Benutzeroberfläche |
| SANDBOX_MEMORY_LIMIT | 16 | Benutzerdefinierte Skriptüberwachungssandbox-Speicherbegrenzung, die kontrolliert, dass Überwachungsskripte nicht zu viel Speicher verwenden (Einheit MB, der Mindestwert ist 8) |
| MAPBOX_TOKEN | - | MapBox-Token zur Verwendung von AMap, um die Standardbesucherkarte zu ersetzen |
| AMAP_TOKEN | - | AMap-Token zur Verwendung von AMap, um die Standardbesucherkarte zu ersetzen |
| CUSTOM_TRACKER_SCRIPT_NAME | - | Ändern des Standardnamens des `tracker.js`-Skripts für Adblock |
| DISABLE_ANONYMOUS_TELEMETRY | false | Deaktiviert das Senden von Telemetrieberichten an die offizielle Tianji-Website, wir werden die Nutzung mit einem Minimum an Anonymität an die offizielle Tianji-Website melden. |
| DISABLE_AUTO_CLEAR | false | Deaktiviert das automatische Löschen von Daten. |

View File

@ -0,0 +1,33 @@
---
sidebar_position: 1
_i18n_hash: c24c34a1a9df2ee5bd25253195dcba08
---
# Integration mit Sentry
:::info
Erfahren Sie mehr über Sentry auf [sentry.io](https://sentry.io/)
:::
Klicken Sie auf `Einstellungen` => `Integrationen` => `Neue Integration erstellen`
![](/img/docs/sentry/sentry1.png)
Erstellen Sie eine `Interne Integration` Anwendung
![](/img/docs/sentry/sentry2.png)
Geben Sie den Namen `Tianji` ein und fügen Sie die Webhook-URL in das Formular ein.
![](/img/docs/sentry/sentry3.png)
Vergessen Sie nicht, `Alert Rule Action` zu aktivieren
![](/img/docs/sentry/sentry4.png)
Fügen Sie dann die Berechtigung `Issue lesen` hinzu und fügen Sie `issue` und `error` zum Webhook hinzu
![](/img/docs/sentry/sentry5.png)
Schließlich können Sie eine Alert-Regel erstellen und `Tianji` in der Dropdown-Liste der Benachrichtigungsabschnitte sehen
![](/img/docs/sentry/sentry6.png)

View File

@ -0,0 +1,31 @@
---
sidebar_position: 1
_i18n_hash: c95e9693eac4df676574d4eb8357881d
---
# Installation mit Helm
Helm ist ein Tool, das die Installation und Verwaltung von Kubernetes-Anwendungen vereinfacht. Mit Helm können Sie Tianji in Kubernetes einfach und schnell nutzen.
## Repo hinzufügen
Zunächst sollten Sie das msgbyte Charts-Repository zu Ihrer Helm-Repo-Liste hinzufügen.
```bash
helm repo add msgbyte https://msgbyte.github.io/charts
```
Jetzt können Sie Tianji mit dem Befehl `helm search` suchen.
```bash
helm search repo tianji
```
## Installation
Installieren Sie dann einfach mit einem Befehl:
```bash
helm install tianji msgbyte/tianji
```
Dies bringt Ihnen eine PostgreSQL-Datenbank und Tianji.

View File

@ -0,0 +1,106 @@
---
sidebar_position: 1
_i18n_hash: 3cd3648cd037fe21e115e135f0c9fa5b
---
# Installation ohne Docker
Die Verwendung von Docker zur Installation von `Tianji` ist der beste Weg, da Sie sich keine Gedanken über Umgebungsprobleme machen müssen.
Wenn Ihr Server jedoch keine Dockerisierung unterstützt, können Sie versuchen, die Installation manuell durchzuführen.
## Voraussetzungen
Sie benötigen:
- [Node.js](https://nodejs.org/en/download/) 18.12+ / 20.4+
- [pnpm](https://pnpm.io/) 9.x (9.7.1 besser)
- [Git](https://git-scm.com/downloads)
- [postgresql](https://www.postgresql.org/)
- [pm2](https://pm2.keymetrics.io/) - Zur Ausführung von Tianji im Hintergrund
- [apprise](https://github.com/caronc/apprise) - optional, falls Sie es für Benachrichtigungen benötigen
## Code klonen und bauen
```bash
git clone https://github.com/msgbyte/tianji.git
cd tianji
pnpm install
pnpm build
```
## Umgebungsdatei vorbereiten
Erstellen Sie eine `.env`-Datei in `src/server`
```ini
DATABASE_URL="postgresql://user:pass@127.0.0.1:5432/tianji?schema=public"
JWT_SECRET="ersetzen-durch-einen-zufälligen-string"
```
Stellen Sie sicher, dass Ihre Datenbank-URL korrekt ist, und denken Sie daran, die Datenbank vorher zu erstellen.
Weitere Umgebungsvariablen finden Sie in diesem Dokument [environment](../environment.md)
> Wenn möglich, stellen Sie sicher, dass Ihre Kodierung en_US.utf8 ist, zum Beispiel: `createdb -E UTF8 -l en_US.utf8 tianji`
## Server starten
```bash
npm install pm2 -g && pm2 install pm2-logrotate
# Datenbankmigration initialisieren
cd src/server
pnpm db:migrate:apply
# Server starten
pm2 start ./dist/src/server/main.js --name tianji
```
Standardmäßig wird `Tianji` auf http://localhost:12345 ausgeführt.
## Code auf eine neue Version aktualisieren
```bash
# Neue Version/Tags auschecken
cd tianji
git fetch --tags
git checkout -q <version>
# Abhängigkeiten aktualisieren
pnpm install
# Projekt bauen
pnpm build
# Datenbankmigrationen ausführen
cd src/server
pnpm db:migrate:apply
# Server neu starten
pm2 restart tianji
```
# Häufig gestellte Fragen
## Installation von `isolated-vm` fehlgeschlagen
Wenn Sie Python 3.12 verwenden, wird möglicherweise ein Fehler wie dieser gemeldet:
```
ModuleNotFoundError: No module named 'distutils'
```
Dies liegt daran, dass Python 3.12 `distutils` aus dem integrierten Modul entfernt hat. Jetzt gibt es eine gute Lösung dafür.
Sie können das Problem beheben, indem Sie Ihre Python-Version von 3.12 auf 3.9 wechseln.
### Wie man es in mit brew verwaltetem Python behebt
```bash
brew install python@3.9
rm /opt/homebrew/bin/python3
ln -sf /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.9
```
Danach können Sie die Version mit `python3 --version` überprüfen.

View File

@ -0,0 +1,46 @@
---
sidebar_position: 1
_i18n_hash: 252240b2a37c8c4784462e75b56d5243
---
# Einführung
## Was ist Tianji?
Eine kurze Zusammenfassung:
**Tianji** = **Website-Analytik** + **Uptime-Monitor** + **Serverstatus**
### Warum heißt es Tianji?
Tianji (天机, Aussprache Tiān Jī) bedeutet auf Chinesisch **himmlische Gelegenheit** oder **Strategie**.
Die Zeichen 天 (Tiān) und 机 (Jī) können jeweils mit "Himmel" und "Maschine" oder "Mechanismus" übersetzt werden. In Kombination könnte es sich auf einen strategischen oder gelegenheitsbedingten Plan oder eine Gelegenheit beziehen, die von einer höheren Macht oder einer himmlischen Kraft inszeniert scheint.
## Motivation
Bei unseren Beobachtungen von Websites müssen wir oft mehrere Anwendungen gleichzeitig verwenden. Zum Beispiel benötigen wir Analysewerkzeuge wie `GA`/`umami`, um pv/uv und die Besucherzahlen jeder Seite zu überprüfen, einen Uptime-Monitor, um die Netzwerkqualität und Verbindung des Servers zu überprüfen, und wir müssen Prometheus verwenden, um den vom Server gemeldeten Status zu erhalten, um die Qualität des Servers zu überprüfen. Darüber hinaus benötigen wir oft ein Telemetriesystem, um uns bei der Entwicklung einer Anwendung, die Open-Source-Bereitstellung ermöglicht, die einfachsten Informationen über die Bereitstellungssituationen anderer zu sammeln.
Ich denke, diese Tools sollten demselben Zweck dienen, gibt es also eine Anwendung, die diese häufigen Bedürfnisse auf leichte Weise integrieren kann? Schließlich benötigen wir die meiste Zeit nicht sehr professionelle und tiefe Funktionen. Aber um umfassende Überwachung zu erreichen, müssen ich so viele Dienste installieren.
Es ist gut, sich auf eine Sache zu spezialisieren, wenn wir Experten in verwandten Fähigkeiten sind, benötigen wir solche spezialisierten Tools. Aber für die meisten Benutzer mit leichten Anforderungen wird eine **All-in-One**-Anwendung bequemer und einfacher zu bedienen sein.
## Installation
Die Installation von Tianji mit Docker ist sehr einfach. Stellen Sie einfach sicher, dass Sie Docker und das Docker-Compose-Plugin installiert haben.
Führen Sie dann diese Befehle überall aus:
```bash
wget https://raw.githubusercontent.com/msgbyte/tianji/master/docker-compose.yml
docker compose up -d
```
> Das Standardkonto ist **admin**/**admin**, bitte ändern Sie das Passwort so schnell wie möglich.
## Community
Treten Sie unserer lebendigen Community bei, um sich mit anderen Benutzern zu verbinden, Erfahrungen auszutauschen und über die neuesten Funktionen und Entwicklungen auf dem Laufenden zu bleiben. Zusammenarbeiten, Fragen stellen und zum Wachstum der Tianji-Community beitragen.
- [GitHub](https://github.com/msgbyte/tianji)
- [Discord](https://discord.gg/8Vv47wAEej)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/tianji)

View File

@ -0,0 +1,80 @@
---
sidebar_position: 1
_i18n_hash: b3805dea583e9b96a5bf32e57ff9c130
---
# Benutzerdefiniertes Skript
Im Vergleich zu traditionellen Überwachungsdiensten unterstützt **Tianji** benutzerdefinierte Skripte, um mehr angepasste Szenarien zu ermöglichen.
Im Wesentlichen können Sie es sich als eine eingeschränkte, speichersichere JavaScript-Laufzeit vorstellen, die eine Zahl akzeptiert, um auf Ihrem Diagramm anzuzeigen. Das häufigste Szenario ist die Zeit, die für Netzwerkanfragen benötigt wird, um auf eine URL zuzugreifen. Natürlich kann es auch andere Dinge sein, wie Ihr OpenAI-Guthaben, Ihre GitHub-Sterne und alle Informationen, die in Zahlen ausgedrückt werden können.
Wenn dieses Skript -1 zurückgibt, bedeutet dies, dass diese Arbeit fehlgeschlagen ist, und versucht, eine Benachrichtigung an Sie zu senden, genau wie bei normaler Überwachung.
Wenn Sie die Trends der Änderungen einer Zahl anzeigen möchten, kann das Öffnen des Trendmodus Ihnen helfen, subtile Änderungen in der Zahl besser zu entdecken.
Hier sind einige Beispiele:
## Beispiele
### Anzahl der verfügbaren Tailchat-Dienste vom Health-Endpunkt abrufen
```js
const res = await request({
url: 'https://<tailchat-server-api>/health'
})
if(!res || !res.data || !res.data.services) {
return -1
}
return res.data.services.length
```
### GitHub-Sterne zählen
```js
const res = await request({
url: 'https://api.github.com/repos/msgbyte/tianji'
})
return res.data.stargazers_count ?? -1
```
Ersetzen Sie `msgbyte/tianji` durch den Namen Ihres eigenen Repositories.
### Docker-Pull-Zähler
```js
const res = await request({
url: "https://hub.docker.com/v2/repositories/moonrailgun/tianji/"
});
return res.data.pull_count;
```
Ersetzen Sie `moonrailgun/tianji` durch den Namen Ihres eigenen Images.
### Beispiel für Textvergleich
```js
const start = Date.now();
const res = await request({
url: "https://example.com/"
});
const usage = Date.now() - start;
const matched = /maintain/.test(String(res.data));
if(matched) {
return -1;
}
return usage;
```
Die Rückgabe von `-1` bedeutet, dass etwas schiefgelaufen ist. In diesem Fall bedeutet dies, dass der HTML-Body den Text `maintain` enthält.
### oder mehr
Es ist sehr willkommen, Ihr Skript auf dieser Seite einzureichen. Tianji wird von der Open-Source-Community angetrieben.

View File

@ -0,0 +1,45 @@
---
sidebar_position: 5
_i18n_hash: 4ea8ae049c2d4b09f2847744ac37545f
---
# Webhook
Wenn Sie eine flexiblere Benachrichtigungsmethode benötigen, können Sie versuchen, benutzerdefinierte Webhooks zu verwenden, um Ihre Nachrichten zu benachrichtigen. Auf diese Weise können Sie die Benachrichtigungen von Tianji in jedes System integrieren.
### Beispielergebnis
Das Tianji-System sendet eine POST-Anfrage mit dem folgenden Beispielinhalt.
```json
{
"notification": {
"workspaceId": "xxxxxxxxxxx",
"name": "Neue Benachrichtigung",
"type": "webhook",
"payload": {
"webhookUrl": "example.com"
}
},
"title": "Benachrichtigungstest für neue Benachrichtigung",
"content": "Tianji: Einblicke in alles\\nDies ist ein Benachrichtigungstest von der neuen Benachrichtigung\\n[Bild]",
"raw": [
{
"type": "title",
"level": 2,
"content": "Tianji: Einblicke in alles"
},
{
"type": "text",
"content": "Dies ist ein Benachrichtigungstest von der neuen Benachrichtigung"
},
{
"type": "newline"
},
{
"type": "image",
"url": "https://tianji.msgbyte.com/img/social-card.png"
}
],
"time": "2024-06-19T15:41:09.390Z"
}
```

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: 7ce5eca3bf7af802db48c3db37d996f5
---
# Server-Statusseite
Sie können eine Server-Statusseite für Benutzer erstellen, um den Status Ihres Servers der Öffentlichkeit anzuzeigen, die es anderen zeigen möchte.
## Konfigurieren einer benutzerdefinierten Domain
Sie können Ihre Statusseite in Ihrer eigenen Domain konfigurieren, zum Beispiel: `status.example.com`
Legen Sie dies in der Seitenkonfiguration fest und erstellen Sie einen `CNAME`-Eintrag in Ihrem DNS-Dashboard.
```
CNAME status.example.com tianji.example.com
```
Danach können Sie die benutzerdefinierte Domain `status.example.com` besuchen, um auf Ihre Seite zuzugreifen.

View File

@ -0,0 +1,68 @@
---
sidebar_position: 1
_i18n_hash: 848acc7fae249b1c435a363e4693a5c7
---
# Server Status Reporter
Sie können den Status Ihres Servers einfach mit dem Tianji Reporter melden.
Sie können es von [https://github.com/msgbyte/tianji/releases](https://github.com/msgbyte/tianji/releases) herunterladen.
## Verwendung
```
Verwendung von tianji-reporter:
--interval int
Geben Sie das INTERVAL in Sekunden ein (Standard: 5)
--mode http
Der Sendemodus der Berichtsdaten, Sie können wählen: `http` oder `udp`, Standard ist `http` (Standard: "http")
--name string
Der Identifikationsname für diesen Rechner
--url string
Die HTTP-URL von Tianji, z.B.: https://tianji.msgbyte.com
--vnstat
Verwenden Sie vnstat für die Datenverkehrsstatistik, nur Linux
--workspace string
Die Arbeitsbereichs-ID für Tianji, dies sollte eine UUID sein
```
**url** und **workspace** sind erforderlich, sie bedeuten, zu welchem Host und welchem Arbeitsbereich Sie Ihren Dienst melden werden.
Standardmäßig wird der Name eines Serverknotens mit dem Hostnamen identisch sein, sodass Sie Ihren Namen mit `--name` anpassen können, um den Server zu identifizieren.
## Automatisiertes Installationsskript
Sie können Ihr automatisiertes Installationsskript in `Tianji` -> `Server` -> `Hinzufügen` -> `Automatisch` Tab erhalten.
Es wird automatisch den Reporter herunterladen und einen Linux-Dienst auf Ihrem Rechner erstellen. Daher sind Root-Berechtigungen erforderlich.
### Deinstallation
Wenn Sie den Reporter-Dienst deinstallieren möchten, können Sie diesen Befehl verwenden:
```bash
curl -o- https://tianji.exmaple.com/serverStatus/xxxxxxxxxxxxxxxxxxx/install.sh?url=https://tianji.example.com | bash -s uninstall
```
Der Hauptunterschied besteht darin, `-s uninstall` nach Ihrem Installationsbefehl anzuhängen.
## Q&A
### Wie überprüfe ich die Protokolle des Tianji Reporter-Dienstes?
Wenn Sie mit dem automatisierten Installationsskript installiert haben, wird Tianji Ihnen einen Dienst namens `tianji-reporter` auf Ihrem Linux-Rechner installieren.
Sie können diesen Befehl verwenden, um die Protokolle des Tianji Reporter zu überprüfen:
```bash
journalctl -fu tianji-reporter.service
```
### Mein Rechner wird im Server-Tab nicht gefunden, obwohl der Bericht erfolgreich war
Vielleicht befindet sich Ihr Tianji hinter einem Reverse-Proxy, z.B. `nginx`.
Stellen Sie sicher, dass Ihr Reverse-Proxy WebSocket-Unterstützung hinzufügt.
## Warum ist mein Rechner immer offline?
Bitte überprüfen Sie die Serverzeit.

View File

@ -0,0 +1,14 @@
---
sidebar_position: 99
_i18n_hash: 6bc67c1ed8a9a26ff57ad81aa4fa0b16
---
# Besonderer Dank
## Open-Source-Projekte
Tianji ist sehr von diesen Projekten inspiriert, danke für eure Beiträge zur Open-Source-Community.
Ich liebe diese Projekte auch. Einen Gruß an diese ausgezeichneten Projekte!
- [umami](https://github.com/umami-software/umami)
- [uptime kuma](https://github.com/louislam/uptime-kuma)

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: c61b6c9968c295ffdfdc1a484f853504
---
# Einführung
## Hintergrund
Als Content-Ersteller veröffentlichen wir unsere Artikel häufig auf verschiedenen Drittanbieter-Plattformen. Für diejenigen von uns, die ernsthaft mit ihrem Content umgehen, ist die Veröffentlichung jedoch erst der Anfang. Wir müssen die Leserzahlen unserer Artikel im Laufe der Zeit kontinuierlich überwachen. Leider sind unsere Datenerfassungsmöglichkeiten auf das beschränkt, was jede Plattform bietet, was stark von den eigenen Fähigkeiten der Plattform abhängt. Darüber hinaus sind die Leser- und Besucherdaten bei der Verteilung desselben Inhalts auf verschiedenen Plattformen völlig isoliert.
Als Entwickler erstelle ich viele Softwareanwendungen. Sobald ich diese jedoch veröffentliche, verliere ich oft die Kontrolle darüber. Zum Beispiel habe ich nach der Veröffentlichung eines Befehlszeilenprogramms keine Möglichkeit zu wissen, wie Benutzer damit interagieren oder gar wie viele Benutzer meine Anwendung nutzen. In ähnlicher Weise konnte ich bei der Entwicklung einer Open-Source-Anwendung in der Vergangenheit nur durch GitHub-Sterne das Interesse einschätzen, wobei ich im Dunkeln darüber blieb, wie sie tatsächlich genutzt wurde.
Daher benötigen wir eine einfache Lösung, die minimale Informationen sammelt und dabei persönliche Privatsphäre und andere Einschränkungen respektiert. Diese Lösung ist Telemetrie.
## Telemetrie
In der Computertechnik ist Telemetrie eine gängige Technologie, die die minimale und anonyme Meldung von Informationen beinhaltet, um Datenschutzbedenken zu berücksichtigen und gleichzeitig die grundlegenden Analysebedürfnisse von Content-Erstellern zu erfüllen.
Zum Beispiel sammelt das Next.js-Framework von React Informationen mithilfe von Telemetrie: [API-Referenz: Next.js CLI | Next.js (nextjs.org)](https://nextjs.org/docs/app/api-reference/next-cli#telemetry)
Alternativ ist es durch Einbetten eines 1px großen, leeren transparenten Pixelbilds in einen Artikel möglich, Besucherdaten auf Websites zu sammeln, über die wir keine Kontrolle haben. Moderne Browser und die meisten Websites blockieren das Einfügen benutzerdefinierter Skripte aufgrund potenzieller Sicherheitsrisiken. Ein Bild erscheint jedoch im Vergleich viel harmloser. Fast alle Websites erlauben das Laden von Bildern von Drittanbietern, wodurch Telemetrie möglich wird.
## Welche Informationen können wir über ein Bild sammeln?
Überraschenderweise ermöglicht die Erhaltung einer einzelnen Bildanfrage die Sammlung mehr Informationen, als man erwarten könnte.
Durch die Analyse von Netzwerkanfragen können wir die IP-Adresse des Benutzers, die Besuchszeit, den Referrer und den Gerätetyp erhalten. Dies ermöglicht es uns, Verkehrsmuster zu analysieren, wie z.B. Spitzenzeiten der Leserzahlen und Trends, demografische Verteilung und die Granularität des Verkehrs über verschiedene Plattformen. Diese Informationen sind besonders wertvoll für Marketing- und Promotionsaktivitäten.
![](/img/telemetry/1.png)
## Wie können wir Telemetrie implementieren?
Telemetrie ist eine unkomplizierte Technologie, die im Wesentlichen einen Endpunkt benötigt, um Internetanfragen zu empfangen. Aufgrund ihrer Einfachheit gibt es wenige dedizierte Tools für diesen Zweck. Viele betrachten möglicherweise Analysen als unwichtig oder werden durch die anfänglichen Hürden abgeschreckt. Dennoch ist der Bedarf an solchen Funktionen offensichtlich.
Die Entwicklung einer Telemetrie-Lösung ist einfach. Sie müssen lediglich ein Projekt erstellen, eine Route einrichten, Informationen aus dem Anfragekörper sammeln und ein leeres Bild zurückgeben.
Hier ist ein Beispiel mit Node.js:
```jsx
router.get(
'/telemetry.gif',
async (req, res) => {
const ip = req.ip;
const referer = req.header['referer'];
const userAgent = req.headers['user-agent'];
// Speichern Sie es in Ihrer Datenbank
const blankGifBuffer = Buffer.from(
'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'base64'
);
res.header('Content-Type', 'image/gif').send(blankGifBuffer);
}
);
```
Wenn Sie keine eigene Lösung entwickeln möchten, empfehle ich Tianji. Als Open-Source-Projekt, das **Website-Analytik**, **Uptime-Überwachung** und **Server-Status** anbietet, hat Tianji kürzlich eine Telemetrie-Funktion eingeführt, um Content-Erstellern bei der Meldung von Telemetrie zu helfen und so eine bessere Datenerfassung zu ermöglichen. Vor allem bedeutet Open-Source, dass Sie die Kontrolle über Ihre Daten haben und den Verkehr von mehreren Plattformen an einem Ort aggregieren können, wodurch die Fragmentierung beim Betrachten derselben Informationen an verschiedenen Orten vermieden wird.
![](/img/telemetry/2.png)
GitHub: [https://github.com/msgbyte/tianji](https://github.com/msgbyte/tianji)
Offizielle Website: [https://tianji.msgbyte.com/](https://tianji.msgbyte.com/)

View File

@ -0,0 +1,29 @@
---
sidebar_position: 2
_i18n_hash: ca2b25a29f0f1a82407be367a1d03553
---
# Parameter
Hier sind einige Beispiele, wie man das Telemetrie-Image verwenden und konfigurieren kann.
Alle Parameter sind optional und verbessern die Nutzung in verschiedenen Umgebungen.
| Name | Beschreibung |
| -------- | --------- |
| url | Standardmäßig wird die Referrer-URL verwendet, die automatisch vom Browser generiert wird. In einigen Websites ist es jedoch nicht erlaubt, diesen Header mitzuführen, daher musst du sie selbst bereitstellen. Wenn Tianji die URL nirgendwo erhalten kann, wird das System dies ignorieren und diesen Besuch nicht aufzeichnen. |
| name | Definiert den Namen des Telemetrie-Ereignisses, der verwendet werden kann, um verschiedene Ereignisse in derselben Telemetrie-Aufzeichnung zu unterscheiden. |
| title | **[Nur für Badges]**, Definiert den Badge-Titel |
| start | **[Nur für Badges]**, Definiert die Startanzahl für den Badge |
| fullNum | **[Nur für Badges]**, Definiert, ob die vollständige Zahl angezeigt wird, standardmäßig werden abgekürzte Ziffern verwendet (z.B. `12345` und `12.3k`) |
## Verwendung
Es ist einfach, Parameter in der URL mitzuführen.
Zum Beispiel:
```
https://tianji.example.com/telemetry/<workspaceId>/<telemetryId>/badge.svg?name=myEvent&url=https://google.com&title=My+Counter&start=100000&fullNum=true
```
Wenn du damit nicht vertraut bist, kannst du die Wiki-Seite dazu überprüfen: [https://en.wikipedia.org/wiki/Query_string](https://en.wikipedia.org/wiki/Query_string)

View File

@ -0,0 +1,25 @@
---
sidebar_position: 1
_i18n_hash: 3e7ad33b9d88240c2ee01504fb17ed2d
---
# Verwendung in Docusaurus
In `docusaurus.config.js`:
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
scripts: [
{
src: 'https://<your domain>/tracker.js',
async: true,
defer: true,
'data-website-id': '<your-website-id>',
},
],
};
module.exports = config;
```

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: bcb6522b66b64594f82548e296f77934
---
# Tracker-Skript
## Installation
Um Website-Ereignisse zu verfolgen, musst du nur ein einfaches Skript (< 2 KB) in deine Website einbinden.
Das Skript sieht wie folgt aus:
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx"></script>
```
Du kannst diesen Skriptcode aus deiner **Tianji**-Websiteliste abrufen.
## Ereignisbericht
**Tianji** bietet eine einfache Möglichkeit, Benutzerklickereignisse zu melden. Es hilft dir, zu verfolgen, welche Aktionen Benutzer mögen und häufig verwenden.
Dies ist eine sehr häufige Methode in der Website-Analyse. Du kannst sie schnell mit **Tianji** nutzen.
Nachdem du den Skriptcode in deine Website eingebunden hast, musst du nur ein `data-tianji-event` in das DOM-Attribut einfügen.
Zum Beispiel:
```html
<button data-tianji-event="submit-login-form">Login</button>
```
Jetzt, wenn ein Benutzer auf diese Schaltfläche klickt, erhält dein Dashboard ein neues Ereignis.
## Standard-Skriptnamen ändern
> Diese Funktion ist ab v1.7.4 verfügbar.
Du kannst die Umgebungsvariable `CUSTOM_TRACKER_SCRIPT_NAME` beim Starten verwenden.
Zum Beispiel:
```
CUSTOM_TRACKER_SCRIPT_NAME="my-tracker.js"
```
Dann kannst du auf dein Tracker-Skript über `"https://<your-self-hosted-domain>/my-tracker.js"` zugreifen.
Dies hilft dir, einige Werbeblocker zu umgehen.
Du benötigst nicht die `.js`-Endung. Es kann ein beliebiger Pfad sein, du kannst sogar `CUSTOM_TRACKER_SCRIPT_NAME="this/is/very/long/path"` verwenden.
## Nur bestimmte Domains verfolgen
Im Allgemeinen meldet der Tracker alle Ereignisse, unabhängig davon, wo deine Website läuft. Manchmal müssen wir jedoch Ereignisse wie `localhost` ignorieren.
Tianji bietet ein Attribut für das Tracker-Skript, um dies zu tun.
Du kannst `data-domains` in dein Skript einfügen. Der Wert sollte deine Stammdomains sein, die verfolgt werden sollen. Verwende `,` um mehrere Domains zu trennen.
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx" data-domains="website.com,www.website.com"></script>
```
Dann kannst du nur die Ereignisse von diesen Domains sehen.

View File

@ -0,0 +1,46 @@
{
"link.title.Docs": {
"message": "Dokumente",
"description": "The title of the footer links column with title=Docs in the footer"
},
"link.title.Community": {
"message": "Gemeinschaft",
"description": "The title of the footer links column with title=Community in the footer"
},
"link.title.More": {
"message": "Mehr",
"description": "The title of the footer links column with title=More in the footer"
},
"link.item.label.Tutorial": {
"message": "Anleitung",
"description": "The label of footer link with label=Tutorial linking to /docs/intro"
},
"link.item.label.Stack Overflow": {
"message": "Stack Overflow",
"description": "The label of footer link with label=Stack Overflow linking to https://stackoverflow.com/questions/tagged/tianji"
},
"link.item.label.Discord": {
"message": "Discord",
"description": "The label of footer link with label=Discord linking to https://discord.gg/8Vv47wAEej"
},
"link.item.label.Twitter": {
"message": "Twitter",
"description": "The label of footer link with label=Twitter linking to https://twitter.com/moonrailgun"
},
"link.item.label.Changelog": {
"message": "Änderungsprotokoll",
"description": "The label of footer link with label=Changelog linking to /changelog"
},
"link.item.label.API": {
"message": "API",
"description": "The label of footer link with label=API linking to /api"
},
"link.item.label.GitHub": {
"message": "GitHub",
"description": "The label of footer link with label=GitHub linking to https://github.com/msgbyte/tianji"
},
"copyright": {
"message": "Copyright © 2024 Tianji, Inc. Built with Msgbyte.",
"description": "The footer copyright"
}
}

View File

@ -0,0 +1,38 @@
{
"title": {
"message": "Tianji",
"description": "The title in the navbar"
},
"logo.alt": {
"message": "Tianji Logo",
"description": "The alt text of navbar logo"
},
"item.label.Docs": {
"message": "Dokumente",
"description": "Navbar item with label Docs"
},
"item.label.Pricing": {
"message": "Preisgestaltung",
"description": "Navbar item with label Pricing"
},
"item.label.Changelog": {
"message": "Änderungsprotokoll",
"description": "Navbar item with label Changelog"
},
"item.label.API": {
"message": "API",
"description": "Navbar item with label API"
},
"item.label.Demo": {
"message": "Demo",
"description": "Navbar item with label Demo"
},
"item.label.Discord": {
"message": "Discord",
"description": "Navbar item with label Discord"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

309
website/i18n/fr/code.json Normal file
View File

@ -0,0 +1,309 @@
{
"theme.ErrorPageContent.title": {
"message": "Cette page a planté.",
"description": "The title of the fallback page when the page crashed"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "Retour au début de la page",
"description": "The ARIA label for the back to top button"
},
"theme.blog.archive.title": {
"message": "Archive",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "Archive",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.paginator.navAriaLabel": {
"message": "Pagination de la liste des articles du blog",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "Nouvelles entrées",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "Anciennes entrées",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "Pagination des articles du blog",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "Article plus récent",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "Article plus ancien",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.tags.tagsPageLink": {
"message": "Voir tous les tags",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "Basculer entre le mode sombre et clair (actuellement {mode})",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "mode sombre",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "mode clair",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "Fil d'Ariane",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription.plurals": {
"message": "1 élément|{count} éléments",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "Pages de documentation",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "Précédent",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "Suivant",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "Un document tagué|{count} documents tagués",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "{nDocsTagged} avec \"{tagName}\"",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "Version: {versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "Ceci est la documentation de la prochaine version {versionLabel} de {siteTitle}.",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "Ceci est la documentation de {siteTitle} {versionLabel}, qui n'est plus activement maintenue.",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "Pour une documentation à jour, consultez la {latestVersionLink} ({versionLabel}).",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "dernière version",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "Éditer cette page",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "Lien direct vers {heading}",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": " le {date}",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": " par {user}",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "Dernière mise à jour{atDate}{byUser}",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "Versions",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.NotFound.title": {
"message": "Page introuvable",
"description": "The title of the 404 page"
},
"theme.tags.tagsListLabel": {
"message": "Tags :",
"description": "The label alongside a tag list"
},
"theme.admonition.caution": {
"message": "attention",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.admonition.danger": {
"message": "danger",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "info",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.note": {
"message": "remarque",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "astuce",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.warning": {
"message": "attention",
"description": "The default label used for the Warning admonition (:::warning)"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "Fermer",
"description": "The ARIA label for close button of announcement bar"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "Navigation article de blog récent",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "Copié",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "Copier le code",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "Copier",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "Activer/désactiver le retour à la ligne",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.expandCategoryAriaLabel": {
"message": "Développer la catégorie '{label}' de la barre latérale",
"description": "The ARIA label to expand the sidebar category"
},
"theme.DocSidebarItem.collapseCategoryAriaLabel": {
"message": "Réduire la catégorie '{label}' de la barre latérale",
"description": "The ARIA label to collapse the sidebar category"
},
"theme.NavBar.navAriaLabel": {
"message": "Main",
"description": "The ARIA label for the main navigation"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "Langues",
"description": "The label for the mobile language switcher dropdown"
},
"theme.NotFound.p1": {
"message": "Nous n'avons pas trouvé ce que vous recherchez.",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "Veuillez contacter le propriétaire du site qui vous a lié à l'URL d'origine et leur faire savoir que leur lien est cassé.",
"description": "The 2nd paragraph of the 404 page"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "Sur cette page",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.blog.post.readMore": {
"message": "Lire plus",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.readMoreLabel": {
"message": "En savoir plus sur {title}",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readingTime.plurals": {
"message": "Une minute de lecture|{readingTime} minutes de lecture",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.breadcrumbs.home": {
"message": "Page d'accueil",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "Réduire le menu latéral",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "Réduire le menu latéral",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.navAriaLabel": {
"message": "Docs sidebar",
"description": "The ARIA label for the sidebar navigation"
},
"theme.docs.sidebar.closeSidebarButtonAriaLabel": {
"message": "Fermer la barre de navigation",
"description": "The ARIA label for close button of mobile sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← Retour au menu principal",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
"message": "Ouvrir/fermer la barre de navigation",
"description": "The ARIA label for hamburger menu button of mobile navigation"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "Déplier le menu latéral",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "Déplier le menu latéral",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.blog.post.plurals": {
"message": "Un article|{count} articles",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "{nPosts} tagués avec « {tagName} »",
"description": "The title of the page for a blog tag"
},
"theme.blog.author.pageTitle": {
"message": "{authorName} - {nPosts}",
"description": "The title of the page for a blog author"
},
"theme.blog.authorsList.pageTitle": {
"message": "Authors",
"description": "The title of the authors page"
},
"theme.blog.authorsList.viewAll": {
"message": "View All Authors",
"description": "The label of the link targeting the blog authors page"
},
"theme.contentVisibility.unlistedBanner.title": {
"message": "Page non répertoriée",
"description": "The unlisted content banner title"
},
"theme.contentVisibility.unlistedBanner.message": {
"message": "Cette page n'est pas répertoriée. Les moteurs de recherche ne l'indexeront pas, et seuls les utilisateurs ayant un lien direct peuvent y accéder.",
"description": "The unlisted content banner message"
},
"theme.contentVisibility.draftBanner.title": {
"message": "Draft page",
"description": "The draft content banner title"
},
"theme.contentVisibility.draftBanner.message": {
"message": "This page is a draft. It will only be visible in dev and be excluded from the production build.",
"description": "The draft content banner message"
},
"theme.ErrorPageContent.tryAgain": {
"message": "Réessayer",
"description": "The label of the button to try again rendering when the React error boundary captures an error"
},
"theme.common.skipToMainContent": {
"message": "Aller au contenu principal",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsPageTitle": {
"message": "Tags",
"description": "The title of the tag list page"
}
}

View File

@ -0,0 +1,14 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

View File

@ -0,0 +1,46 @@
{
"version.label": {
"message": "Next",
"description": "The label for version current"
},
"sidebar.tutorialSidebar.category.Install": {
"message": "Installer",
"description": "The label for category Install in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Kubernetes": {
"message": "Kubernetes",
"description": "The label for category Kubernetes in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Website": {
"message": "Site Web",
"description": "The label for category Website in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Framework": {
"message": "Cadre",
"description": "The label for category Framework in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Monitor": {
"message": "Moniteur",
"description": "The label for category Monitor in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Notification": {
"message": "Notification",
"description": "The label for category Notification in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Server Status": {
"message": "État du serveur",
"description": "The label for category Server Status in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Telemetry": {
"message": "Télémétrie",
"description": "The label for category Telemetry in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Feed": {
"message": "Alimentation",
"description": "The label for category Feed in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Develop": {
"message": "Développer",
"description": "The label for category Develop in sidebar tutorialSidebar"
}
}

View File

@ -0,0 +1,38 @@
---
sidebar_position: 1
_i18n_hash: f20c701ad093f995d1aad2b2b37ae5ec
---
# Préparation au développement
## Préparer la base de données utilisant Docker
```bash
docker run --name tianji-pg -e POSTGRES_DB=tianji -e POSTGRES_USER=tianji -e POSTGRES_PASSWORD=tianji -d postgres:15.4-alpine
```
## Préparer le fichier .env
```bash
cp .env.example src/server/.env
```
Configurez `DATABASE_URL` avec `postgresql://tianji:tianji@localhost:5432/tianji?schema=public`
Comme ceci :
```ini
DATABASE_URL="postgresql://tianji:tianji@localhost:5432/tianji?schema=public"
ALLOW_OPENAPI=true
```
## Préparer la structure de la base de données
Vous pouvez maintenant accéder à la base de données, et vous pouvez visiter
```bash
cd src/server && pnpm db:migrate:apply
```
## Compte par défaut
Le compte par défaut est `admin`/`admin`

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: c65e22ae3d729a07b0b23f525a89b8ca
---
# Environnement
Voici l'environnement que vous pouvez configurer dans Docker
| Nom | Valeur par défaut | Description |
| ---- | ---- | ----- |
| JWT_SECRET | - | Une chaîne aléatoire utilisée pour calculer la clé secrète |
| ALLOW_REGISTER | false | Indique si les utilisateurs peuvent s'inscrire |
| ALLOW_OPENAPI | false | Indique si l'API ouverte est autorisée à récupérer ou à poster des données comme vous avec l'interface utilisateur |
| SANDBOX_MEMORY_LIMIT | 16 | Limite de mémoire du bac à sable pour le script de surveillance personnalisé, permet de contrôler que le script de surveillance n'utilise pas trop de mémoire (unité MB, la valeur minimale est 8) |
| MAPBOX_TOKEN | - | Token MapBox pour utiliser AMap à la place de la carte des visiteurs par défaut |
| AMAP_TOKEN | - | Token AMap pour utiliser AMap à la place de la carte des visiteurs par défaut |
| CUSTOM_TRACKER_SCRIPT_NAME | - | Modifie le nom du script `tracker.js` par défaut pour le blocage des publicités |
| DISABLE_ANONYMOUS_TELEMETRY | false | Désactive l'envoi de rapports de télémétrie à Tianji officiel, nous enverrons des rapports d'utilisation au site officiel de Tianji avec un minimum d'anonymat. |
| DISABLE_AUTO_CLEAR | false | Désactive la suppression automatique des données. |

View File

@ -0,0 +1,33 @@
---
sidebar_position: 1
_i18n_hash: c24c34a1a9df2ee5bd25253195dcba08
---
# Intégration avec Sentry
:::info
En savoir plus sur Sentry sur [sentry.io](https://sentry.io/)
:::
Cliquez sur `Paramètres` => `Intégrations` => `Créer une nouvelle intégration`
![](/img/docs/sentry/sentry1.png)
Créez une application `Intégration interne`
![](/img/docs/sentry/sentry2.png)
Entrez le nom `Tianji` et insérez l'URL du webhook dans le formulaire.
![](/img/docs/sentry/sentry3.png)
N'oubliez pas d'activer `Action de règle d'alerte`
![](/img/docs/sentry/sentry4.png)
Ensuite, ajoutez la `permission` de lecture des problèmes, et ajoutez `problème` et `erreur` au webhook
![](/img/docs/sentry/sentry5.png)
Enfin, vous pouvez créer une règle d'alerte, et vous verrez `Tianji` dans la liste déroulante des notifications
![](/img/docs/sentry/sentry6.png)

View File

@ -0,0 +1,31 @@
---
sidebar_position: 1
_i18n_hash: c95e9693eac4df676574d4eb8357881d
---
# Installation avec Helm
Helm est un outil qui facilite l'installation et la gestion des applications Kubernetes. Avec Helm, vous pouvez facilement et rapidement profiter de tianji sur Kubernetes.
## Ajouter le dépôt
Tout d'abord, vous devez ajouter le registre de charts msgbyte à la liste des dépôts Helm.
```bash
helm repo add msgbyte https://msgbyte.github.io/charts
```
Vous pouvez maintenant rechercher tianji avec la commande `helm search`.
```bash
helm search repo tianji
```
## Installer
Ensuite, n'hésitez pas à installer avec une seule commande :
```bash
helm install tianji msgbyte/tianji
```
Cela vous apportera une base de données pg et tianji.

View File

@ -0,0 +1,106 @@
---
sidebar_position: 1
_i18n_hash: 3cd3648cd037fe21e115e135f0c9fa5b
---
# Installation sans Docker
L'utilisation de Docker pour installer `Tianji` est la meilleure méthode car vous n'avez pas à vous soucier des problèmes d'environnement.
Cependant, si votre serveur ne prend pas en charge Docker, vous pouvez essayer d'installer manuellement.
## Prérequis
Vous avez besoin de :
- [Node.js](https://nodejs.org/en/download/) 18.12+ / 20.4+
- [pnpm](https://pnpm.io/) 9.x (9.7.1 recommandé)
- [Git](https://git-scm.com/downloads)
- [postgresql](https://www.postgresql.org/)
- [pm2](https://pm2.keymetrics.io/) - Pour exécuter Tianji en arrière-plan
- [apprise](https://github.com/caronc/apprise) - optionnel, si vous en avez besoin pour les notifications
## Cloner le code et construire
```bash
git clone https://github.com/msgbyte/tianji.git
cd tianji
pnpm install
pnpm build
```
## Préparer le fichier d'environnement
Créez un fichier `.env` dans `src/server`
```ini
DATABASE_URL="postgresql://user:pass@127.0.0.1:5432/tianji?schema=public"
JWT_SECRET="remplacez-moi-par-une-chaîne-aléatoire"
```
Assurez-vous que votre URL de base de données est correcte et n'oubliez pas de créer la base de données avant.
Pour plus d'environnements, consultez ce document [environment](../environment.md)
> Si possible, assurez-vous que votre encodage est en_US.utf8, par exemple : `createdb -E UTF8 -l en_US.utf8 tianji`
## Exécuter le serveur
```bash
npm install pm2 -g && pm2 install pm2-logrotate
# Initialiser la migration de la base de données
cd src/server
pnpm db:migrate:apply
# Démarrer le serveur
pm2 start ./dist/src/server/main.js --name tianji
```
Par défaut, `Tianji` fonctionnera sur http://localhost:12345
## Mettre à jour le code vers une nouvelle version
```bash
# Extraire les nouvelles versions/tags
cd tianji
git fetch --tags
git checkout -q <version>
# Mettre à jour les dépendances
pnpm install
# Construire le projet
pnpm build
# Exécuter les migrations de la base de données
cd src/server
pnpm db:migrate:apply
# Redémarrer le serveur
pm2 restart tianji
```
# Questions fréquemment posées
## Échec de l'installation de `isolated-vm`
Si vous utilisez Python 3.12, cela signalera une erreur comme celle-ci :
```
ModuleNotFoundError: No module named 'distutils'
```
Cela est dû au fait que Python 3.12 a supprimé `distutils` du module intégré. Maintenant, nous avons une bonne solution pour cela.
Vous pouvez résoudre ce problème en passant votre version de Python de 3.12 à 3.9.
### Comment le résoudre avec Python contrôlé par brew
```bash
brew install python@3.9
rm /opt/homebrew/bin/python3
ln -sf /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.9
```
Ensuite, vous pouvez vérifier la version avec `python3 --version`

View File

@ -0,0 +1,46 @@
---
sidebar_position: 1
_i18n_hash: 252240b2a37c8c4784462e75b56d5243
---
# Introduction
## Qu'est-ce que Tianji
Une phrase pour résumer :
**Tianji** = **Analyse du site Web** + **Surveillance de l'uptime** + **État du serveur**
### Pourquoi s'appelle-t-il Tianji ?
Tianji (天机, prononciation Tiān Jī) en chinois qui signifie **Opportunité céleste** ou **Stratégie**
Les caractères 天 (Tiān) et 机 (Jī) peuvent être traduits respectivement par "ciel" et "machine" ou "mécanisme". Lorsqu'ils sont combinés, cela peut faire référence à un plan stratégique ou opportuniste ou à une opportunité qui semble être orchestrée par une puissance supérieure ou une force céleste.
## Motivation
Lors de nos observations du site Web, nous avons souvent besoin d'utiliser plusieurs applications ensemble. Par exemple, nous avons besoin d'outils d'analyse comme `GA`/`umami` pour vérifier les pv/uv et le nombre de visites sur chaque page, nous avons besoin d'un moniteur d'uptime pour vérifier la qualité du réseau et la connectivité du serveur, et nous avons besoin d'utiliser prometheus pour obtenir l'état signalé par le serveur pour vérifier la qualité du serveur. De plus, si nous développons une application qui permet le déploiement open source, nous avons souvent besoin d'un système de télémétrie pour nous aider à collecter les informations les plus simples sur les situations de déploiement des autres.
Je pense que ces outils devraient servir le même objectif, alors existe-t-il une application qui peut intégrer ces besoins courants de manière légère ? Après tout, la plupart du temps, nous n'avons pas besoin de fonctions très professionnelles et approfondies. Mais pour réaliser une surveillance complète, je dois installer autant de services.
Il est bon de se spécialiser dans une chose, si nous sommes des experts en capacités connexes, nous avons besoin de tels outils spécialisés. Mais pour la plupart des utilisateurs qui n'ont que des besoins légers, une application **All-in-One** sera plus pratique et plus facile à utiliser.
## Installation
L'installation de Tianji avec Docker est très simple. Assurez-vous simplement d'avoir installé docker et le plugin docker-compose
puis, exécutez ces commandes n'importe où :
```bash
wget https://raw.githubusercontent.com/msgbyte/tianji/master/docker-compose.yml
docker compose up -d
```
> Le compte par défaut est **admin**/**admin**, veuillez changer le mot de passe dès que possible.
## Communauté
Rejoignez notre communauté florissante pour vous connecter avec d'autres utilisateurs, partager des expériences et rester informé des dernières fonctionnalités et développements. Collaborez, posez des questions et contribuez à la croissance de la communauté Tianji.
- [GitHub](https://github.com/msgbyte/tianji)
- [Discord](https://discord.gg/8Vv47wAEej)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/tianji)

View File

@ -0,0 +1,80 @@
---
sidebar_position: 1
_i18n_hash: b3805dea583e9b96a5bf32e57ff9c130
---
# Script personnalisé
Comparé aux services de surveillance traditionnels, **Tianji** prend en charge les scripts personnalisés pour soutenir des scénarios plus personnalisés.
Essentiellement, vous pouvez le comprendre comme un environnement d'exécution JavaScript restreint et sécurisé en mémoire qui accepte un nombre à afficher sur votre graphique. Le scénario le plus courant est le temps nécessaire pour les requêtes réseau pour accéder à une URL. Bien sûr, il peut également s'agir d'autres choses, comme votre solde OpenAI, votre nombre d'étoiles GitHub, et toutes les informations qui peuvent être exprimées en nombres.
Si ce script renvoie -1, cela signifie que le travail a échoué et qu'une notification vous sera envoyée, tout comme une surveillance normale.
Si vous souhaitez voir la tendance des changements d'un nombre, l'activation du mode de tendance peut vous aider à mieux détecter les changements subtils dans le nombre.
Voici quelques exemples :
## Exemples
### Obtenir le nombre de services disponibles Tailchat à partir du point de terminaison de santé
```js
const res = await request({
url: 'https://<tailchat-server-api>/health'
})
if(!res || !res.data || !res.data.services) {
return -1
}
return res.data.services.length
```
### Obtenir le nombre d'étoiles GitHub
```js
const res = await request({
url: 'https://api.github.com/repos/msgbyte/tianji'
})
return res.data.stargazers_count ?? -1
```
Remplacez `msgbyte/tianji` par le nom de votre propre dépôt.
### Obtenir le nombre de pulls Docker
```js
const res = await request({
url: "https://hub.docker.com/v2/repositories/moonrailgun/tianji/"
});
return res.data.pull_count;
```
Remplacez `moonrailgun/tianji` par le nom de votre propre image.
### Exemple pour correspondre à du texte
```js
const start = Date.now();
const res = await request({
url: "https://example.com/"
});
const usage = Date.now() - start;
const matched = /maintain/.test(String(res.data));
if(matched) {
return -1;
}
return usage;
```
Renvoie `-1` signifie qu'il y a un problème. Dans ce cas, cela signifie que le corps HTML contient le texte `maintain`.
### Ou plus
Très très bienvenu de soumettre votre script sur cette page. Tianji est propulsé par la communauté open source.

View File

@ -0,0 +1,45 @@
---
sidebar_position: 5
_i18n_hash: 4ea8ae049c2d4b09f2847744ac37545f
---
# Webhook
Si vous avez besoin d'une méthode de notification plus flexible, vous pouvez essayer d'utiliser des webhooks personnalisés pour notifier vos messages. De cette manière, vous pouvez intégrer les notifications de Tianji dans n'importe quel système.
### Exemple de Résultat
Le système Tianji enverra une requête POST avec le contenu d'exemple ci-dessous.
```json
{
"notification": {
"workspaceId": "xxxxxxxxxxx",
"name": "Nouvelle Notification",
"type": "webhook",
"payload": {
"webhookUrl": "example.com"
}
},
"title": "Test de Notification de Nouvelle Notification",
"content": "Tianji : Insight into everything\\nCeci est un test de notification de Nouvelle Notification\\n[image]",
"raw": [
{
"type": "title",
"level": 2,
"content": "Tianji : Insight into everything"
},
{
"type": "text",
"content": "Ceci est un test de notification de Nouvelle Notification"
},
{
"type": "newline"
},
{
"type": "image",
"url": "https://tianji.msgbyte.com/img/social-card.png"
}
],
"time": "2024-06-19T15:41:09.390Z"
}
```

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: 7ce5eca3bf7af802db48c3db37d996f5
---
# Page d'état du serveur
Vous pouvez créer une page d'état du serveur pour montrer l'état de votre serveur au public.
## Configurer un domaine personnalisé
Vous pouvez configurer votre page d'état sur votre propre domaine, par exemple : `status.example.com`
Configurez-le dans les paramètres de la page et créez un enregistrement `CNAME` dans votre tableau de bord DNS.
```
CNAME status.example.com tianji.example.com
```
Ensuite, vous pouvez visiter `status.example.com` pour accéder à votre page.

View File

@ -0,0 +1,68 @@
---
sidebar_position: 1
_i18n_hash: 848acc7fae249b1c435a363e4693a5c7
---
# Rapporteur d'état du serveur
vous pouvez facilement signaler l'état de votre serveur avec le rapporteur Tianji
vous pouvez télécharger depuis [https://github.com/msgbyte/tianji/releases](https://github.com/msgbyte/tianji/releases)
## Utilisation
```
Usage de tianji-reporter:
--interval int
Entrez l'INTERVALLE, en secondes (par défaut 5)
--mode http
Le mode d'envoi des données de rapport, vous pouvez choisir : `http` ou `udp`, par défaut est `http` (par défaut "http")
--name string
Le nom d'identification pour cette machine
--url string
L'URL http de Tianji, par exemple : https://tianji.msgbyte.com
--vnstat
Utiliser vnstat pour les statistiques de trafic, uniquement pour Linux
--workspace string
L'ID de l'espace de travail pour Tianji, cela devrait être un UUID
```
Les **url** et **workspace** sont requis, cela signifie que vous allez signaler votre service à quel hôte et quel espace de travail.
Par défaut, le nom d'un nœud de serveur sera le même que le nom d'hôte, vous pouvez donc personnaliser votre nom avec `--name` qui peut vous aider à identifier le serveur.
## Script d'installation automatique
Vous pouvez obtenir votre script d'installation automatique dans `Tianji` -> `Serveurs` -> `Ajouter` -> `Auto` onglet
il téléchargera automatiquement le rapporteur et créera un service Linux sur votre machine. Il nécessite donc des permissions root.
### Désinstaller
si vous souhaitez désinstaller le service de rapporteur, vous pouvez utiliser cette commande comme :
```bash
curl -o- https://tianji.exmaple.com/serverStatus/xxxxxxxxxxxxxxxxxxx/install.sh?url=https://tianji.example.com | bash -s uninstall
```
le changement principal consiste à ajouter `-s uninstall` après votre commande d'installation.
## Q&R
### Comment vérifier les journaux du service de rapporteur Tianji ?
Si vous avez installé avec le script d'installation automatique, Tianji vous aidera à installer un service nommé `tianji-reporter` sur votre machine Linux.
Vous pouvez utiliser cette commande pour vérifier les journaux du rapporteur Tianji :
```bash
journalctl -fu tianji-reporter.service
```
### Votre machine n'est pas trouvée dans l'onglet des serveurs même si le rapport indique succès
Peut-être que votre Tianji est derrière un proxy inverse, par exemple `nginx`.
Veuillez vous assurer que votre proxy inverse ajoute la prise en charge des websockets
## Pourquoi ma machine est toujours hors ligne ?
Veuillez vérifier l'heure de votre serveur.

View File

@ -0,0 +1,14 @@
---
sidebar_position: 99
_i18n_hash: 6bc67c1ed8a9a26ff57ad81aa4fa0b16
---
# Remerciements spéciaux
## Projet open source
Tianji est très inspiré par ces projets, merci pour vos contributions à la communauté open source.
J'aime également ces projets. Hommage à ces excellents projets !
- [umami](https://github.com/umami-software/umami)
- [uptime kuma](https://github.com/louislam/uptime-kuma)

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: c61b6c9968c295ffdfdc1a484f853504
---
# Introduction
## Contexte
En tant que créateurs de contenu, nous publions souvent nos articles sur diverses plateformes tierces. Cependant, pour ceux d'entre nous qui prennent leur contenu au sérieux, la publication n'est que le début. Nous devons surveiller en permanence l'audience de nos articles au fil du temps. Malheureusement, nos capacités de collecte de données sont limitées à ce que chaque plateforme offre, ce qui dépend fortement des capacités propres de la plateforme. De plus, lorsque nous distribuons le même contenu sur différentes plateformes, les données d'audience et de visite sont complètement isolées.
En tant que développeur, je crée de nombreuses applications logicielles. Cependant, une fois que je les ai publiées, je perds souvent le contrôle sur elles. Par exemple, après avoir publié un programme en ligne de commande, je n'ai aucun moyen de savoir comment les utilisateurs interagissent avec lui ou même combien d'utilisateurs utilisent mon application. De même, lors du développement d'une application open-source, par le passé, je ne pouvais mesurer l'intérêt que par le biais des étoiles GitHub, me laissant dans l'ignorance de l'utilisation réelle.
Par conséquent, nous avons besoin d'une solution simple qui collecte des informations minimales, respectant la confidentialité des individus et d'autres restrictions. Cette solution est la télémétrie.
## Télémétrie
Dans le domaine de l'informatique, la télémétrie est une technologie courante qui consiste à signaler de manière minimale et anonyme des informations pour répondre aux préoccupations en matière de confidentialité tout en répondant aux besoins analytiques de base des créateurs de contenu.
Par exemple, le framework React Next.js collecte des informations à l'aide de la télémétrie : [Référence API : Next.js CLI | Next.js (nextjs.org)](https://nextjs.org/docs/app/api-reference/next-cli#telemetry)
Alternativement, en intégrant une image transparente de 1px de taille dans un article, il est possible de collecter des données de visiteurs sur des sites web que nous ne contrôlons pas. Les navigateurs modernes et la plupart des sites web bloquent l'insertion de scripts personnalisés en raison des risques de sécurité potentiels. Cependant, une image semble beaucoup plus inoffensive par comparaison. Presque tous les sites web permettent le chargement d'images tierces, rendant la télémétrie possible.
## Quelles informations pouvons-nous collecter via une image ?
Étonnamment, recevoir une seule requête d'image nous permet de collecter plus d'informations que l'on pourrait s'y attendre.
En analysant les requêtes réseau, nous pouvons obtenir l'adresse IP de l'utilisateur, l'heure de la visite, le référent et le type d'appareil. Cela nous permet d'analyser les modèles de trafic, tels que les heures de pointe de l'audience et les tendances, la distribution démographique et la granularité du trafic sur différentes plateformes. Ces informations sont particulièrement précieuses pour les activités marketing et promotionnelles.
![](/img/telemetry/1.png)
## Comment pouvons-nous mettre en œuvre la télémétrie ?
La télémétrie est une technologie simple qui nécessite essentiellement un point de terminaison pour recevoir des requêtes Internet. En raison de sa simplicité, il existe peu d'outils dédiés à cet effet. Beaucoup peuvent ne pas considérer l'analytique comme importante, ou ils pourraient être découragés par les obstacles initiaux. Cependant, la demande de cette fonctionnalité est claire.
Développer une solution de télémétrie est simple. Il suffit de créer un projet, de configurer une route, de collecter des informations à partir du corps de la requête et de renvoyer une image vide.
Voici un exemple en utilisant Node.js :
```jsx
router.get(
'/telemetry.gif',
async (req, res) => {
const ip = req.ip;
const referer = req.header['referer'];
const userAgent = req.headers['user-agent'];
// Stocker dans votre base de données
const blankGifBuffer = Buffer.from(
'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'base64'
);
res.header('Content-Type', 'image/gif').send(blankGifBuffer);
}
);
```
Si vous préférez ne pas développer votre propre solution, je recommande Tianji. En tant que projet open-source offrant **Analytique Web**, **Surveillance de l'Uptime** et **État du Serveur**, Tianji a récemment introduit une fonctionnalité de télémétrie pour aider les créateurs de contenu à signaler la télémétrie, facilitant ainsi une meilleure collecte de données. Plus important encore, étant open-source, vous avez le contrôle sur vos données et pouvez agréger le trafic de plusieurs plateformes en un seul endroit, évitant ainsi la fragmentation de l'affichage des mêmes informations à différents endroits.
![](/img/telemetry/2.png)
GitHub : [https://github.com/msgbyte/tianji](https://github.com/msgbyte/tianji)
Site officiel : [https://tianji.msgbyte.com/](https://tianji.msgbyte.com/)

View File

@ -0,0 +1,29 @@
---
sidebar_position: 2
_i18n_hash: ca2b25a29f0f1a82407be367a1d03553
---
# Paramètres
Voici un exemple d'utilisation et de configuration avec l'image de télémétrie.
Tout est optionnel. Cela améliorera votre utilisation dans différents contextes.
| nom | description |
| -------- | --------- |
| url | Par défaut, l'URL de référence générée automatiquement par le navigateur sera utilisée, mais certains sites web n'autorisent pas ce type de header. Vous devez donc le fournir vous-même. Si Tianji ne peut obtenir l'URL nulle part, le système l'ignorera et ne consignera pas cette visite. |
| name | Définit le nom de l'événement de télémétrie, ce qui permet de distinguer différents événements dans le même enregistrement de télémétrie. |
| title | **[BADGE UNIQUEMENT]**, définit le titre du badge |
| start | **[BADGE UNIQUEMENT]**, définit le nombre de départ du badge |
| fullNum | **[BADGE UNIQUEMENT]**, définit si le badge affichera le nombre complet, par défaut, il utilise des chiffres abrégés (par exemple : `12345` et `12.3k`) |
## Comment utiliser
Il est facile de transmettre des paramètres dans l'URL.
Par exemple :
```
https://tianji.example.com/telemetry/<workspaceId>/<telemetryId>/badge.svg?name=myEvent&url=https://google.com&title=My+Counter&start=100000&fullNum=true
```
Si vous n'êtes pas familier avec cela, vous pouvez consulter la page wiki à ce sujet : [https://en.wikipedia.org/wiki/Query_string](https://en.wikipedia.org/wiki/Query_string)

View File

@ -0,0 +1,25 @@
---
sidebar_position: 1
_i18n_hash: 3e7ad33b9d88240c2ee01504fb17ed2d
---
# Utilisation dans Docusaurus
Dans `docusaurus.config.js` :
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
scripts: [
{
src: 'https://<your domain>/tracker.js',
async: true,
defer: true,
'data-website-id': '<your-website-id>',
},
],
};
module.exports = config;
```

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: bcb6522b66b64594f82548e296f77934
---
# Script de suivi
## Installation
Pour suivre les événements du site web, il vous suffit d'injecter un simple script (< 2 Ko) dans votre site web.
Le script ressemble à ceci :
```html
<script async defer src="https://<votre-domaine-auto-hébergé>/tracker.js" data-website-id="xxxxxxxxxxxxx"></script>
```
Vous pouvez obtenir ce code de script à partir de la liste des sites web de **Tianji**.
## Rapport d'événement
**Tianji** propose un moyen simple de signaler les événements de clic de l'utilisateur, ce qui facilite le suivi des actions que les utilisateurs apprécient et utilisent fréquemment.
Il s'agit d'une méthode très courante dans l'analyse des sites web. Vous pouvez l'obtenir rapidement en utilisant **Tianji**.
Après avoir injecté le code du script dans votre site web, il vous suffit d'ajouter un `data-tianji-event` dans l'attribut DOM.
Par exemple :
```html
<button data-tianji-event="submit-login-form">Connexion</button>
```
Maintenant, lorsque l'utilisateur clique sur ce bouton, votre tableau de bord recevra un nouvel événement.
## Modifier le nom du script par défaut
> Cette fonctionnalité est disponible à partir de la version 1.7.4
Vous pouvez utiliser l'environnement `CUSTOM_TRACKER_SCRIPT_NAME` lorsque vous le démarrez.
Par exemple :
```
CUSTOM_TRACKER_SCRIPT_NAME="my-tracker.js"
```
Ensuite, vous pouvez accéder à votre script de suivi avec `"https://<votre-domaine-auto-hébergé>/my-tracker.js"`.
Cela permet d'éviter certains bloqueurs de publicité.
Vous n'avez pas besoin du suffixe `.js`. Il peut s'agir de n'importe quel chemin de votre choix, même vous pouvez l'utiliser comme `CUSTOM_TRACKER_SCRIPT_NAME="this/is/very/long/path"`.
## Suivi des domaines spécifiés uniquement
En général, le suivi signalera tous les événements où que votre site soit en cours d'exécution. Mais parfois, nous devons ignorer des événements comme `localhost`.
Tianji fournit un attribut du script de suivi pour cela.
Vous pouvez ajouter `data-domains` à votre script. La valeur doit être vos domaines racines à suivre. Utilisez `,` pour séparer plusieurs domaines.
```html
<script async defer src="https://<votre-domaine-auto-hébergé>/tracker.js" data-website-id="xxxxxxxxxxxxx" data-domains="website.com,www.website.com"></script>
```
Ensuite, vous ne verrez que les événements provenant de ces domaines.

View File

@ -0,0 +1,46 @@
{
"link.title.Docs": {
"message": "Docs",
"description": "The title of the footer links column with title=Docs in the footer"
},
"link.title.Community": {
"message": "Communauté",
"description": "The title of the footer links column with title=Community in the footer"
},
"link.title.More": {
"message": "Plus",
"description": "The title of the footer links column with title=More in the footer"
},
"link.item.label.Tutorial": {
"message": "Tutoriel",
"description": "The label of footer link with label=Tutorial linking to /docs/intro"
},
"link.item.label.Stack Overflow": {
"message": "Stack Overflow",
"description": "The label of footer link with label=Stack Overflow linking to https://stackoverflow.com/questions/tagged/tianji"
},
"link.item.label.Discord": {
"message": "Discord",
"description": "The label of footer link with label=Discord linking to https://discord.gg/8Vv47wAEej"
},
"link.item.label.Twitter": {
"message": "Twitter",
"description": "The label of footer link with label=Twitter linking to https://twitter.com/moonrailgun"
},
"link.item.label.Changelog": {
"message": "Journal des modifications",
"description": "The label of footer link with label=Changelog linking to /changelog"
},
"link.item.label.API": {
"message": "API",
"description": "The label of footer link with label=API linking to /api"
},
"link.item.label.GitHub": {
"message": "GitHub",
"description": "The label of footer link with label=GitHub linking to https://github.com/msgbyte/tianji"
},
"copyright": {
"message": "Copyright © 2024 Tianji, Inc. Built with Msgbyte.",
"description": "The footer copyright"
}
}

View File

@ -0,0 +1,38 @@
{
"title": {
"message": "Tianji",
"description": "The title in the navbar"
},
"logo.alt": {
"message": "Tianji Logo",
"description": "The alt text of navbar logo"
},
"item.label.Docs": {
"message": "Docs",
"description": "Navbar item with label Docs"
},
"item.label.Pricing": {
"message": "Tarification",
"description": "Navbar item with label Pricing"
},
"item.label.Changelog": {
"message": "Journal des modifications",
"description": "Navbar item with label Changelog"
},
"item.label.API": {
"message": "API",
"description": "Navbar item with label API"
},
"item.label.Demo": {
"message": "Démo",
"description": "Navbar item with label Demo"
},
"item.label.Discord": {
"message": "Discord",
"description": "Navbar item with label Discord"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

309
website/i18n/ja/code.json Normal file
View File

@ -0,0 +1,309 @@
{
"theme.ErrorPageContent.title": {
"message": "エラーが発生しました",
"description": "The title of the fallback page when the page crashed"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "先頭へ戻る",
"description": "The ARIA label for the back to top button"
},
"theme.blog.archive.title": {
"message": "アーカイブ",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "アーカイブ",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.paginator.navAriaLabel": {
"message": "ブログ記事一覧のナビゲーション",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "新しい記事",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "過去の記事",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "ブログ記事のナビゲーション",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "新しい記事",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "過去の記事",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.tags.tagsPageLink": {
"message": "全てのタグを見る",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "ダークモードを切り替える(現在は{mode})",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "ダークモード",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "ライトモード",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "パンくずリストのナビゲーション",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription.plurals": {
"message": "{count}項目",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "ドキュメントページ",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "前へ",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "次へ",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "{count}記事",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "「{tagName}」タグのついた{nDocsTagged}",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "バージョン: {versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "これはリリース前のバージョン{versionLabel}の{siteTitle}のドキュメントです。",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "これはバージョン{versionLabel}の{siteTitle}のドキュメントで現在はメンテナンスされていません",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "最新のドキュメントは{latestVersionLink} ({versionLabel}) を見てください",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "最新バージョン",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "このページを編集",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "{heading} への直接リンク",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": "{date}に",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": "{user}が",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "{atDate}{byUser}最終更新",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "他のバージョン",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.NotFound.title": {
"message": "ページが見つかりません",
"description": "The title of the 404 page"
},
"theme.tags.tagsListLabel": {
"message": "タグ:",
"description": "The label alongside a tag list"
},
"theme.admonition.caution": {
"message": "注意",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.admonition.danger": {
"message": "危険",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "備考",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.note": {
"message": "注記",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "ヒント",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.warning": {
"message": "警告",
"description": "The default label used for the Warning admonition (:::warning)"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "閉じる",
"description": "The ARIA label for close button of announcement bar"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "最近のブログ記事のナビゲーション",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "コピーしました",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "クリップボードにコードをコピー",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "コピー",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "折り返し",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.expandCategoryAriaLabel": {
"message": "'{label}'の目次を開く",
"description": "The ARIA label to expand the sidebar category"
},
"theme.DocSidebarItem.collapseCategoryAriaLabel": {
"message": "'{label}'の目次を隠す",
"description": "The ARIA label to collapse the sidebar category"
},
"theme.NavBar.navAriaLabel": {
"message": "ナビゲーション",
"description": "The ARIA label for the main navigation"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "他の言語",
"description": "The label for the mobile language switcher dropdown"
},
"theme.NotFound.p1": {
"message": "お探しのページが見つかりませんでした",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "このページにリンクしているサイトの所有者にリンクが壊れていることを伝えてください",
"description": "The 2nd paragraph of the 404 page"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "このページの見出し",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.blog.post.readMore": {
"message": "もっと見る",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.readMoreLabel": {
"message": "{title}についてもっと見る",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readingTime.plurals": {
"message": "約{readingTime}分",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.breadcrumbs.home": {
"message": "ホームページ",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "サイドバーを隠す",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "サイドバーを隠す",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.navAriaLabel": {
"message": "ドキュメントのサイドバー",
"description": "The ARIA label for the sidebar navigation"
},
"theme.docs.sidebar.closeSidebarButtonAriaLabel": {
"message": "ナビゲーションバーを閉じる",
"description": "The ARIA label for close button of mobile sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← メインメニューに戻る",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
"message": "ナビゲーションバーを開く",
"description": "The ARIA label for hamburger menu button of mobile navigation"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "サイドバーを開く",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "サイドバーを開く",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.blog.post.plurals": {
"message": "{count}件",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "「{tagName}」タグの記事が{nPosts}件あります",
"description": "The title of the page for a blog tag"
},
"theme.blog.author.pageTitle": {
"message": "{authorName} - {nPosts}",
"description": "The title of the page for a blog author"
},
"theme.blog.authorsList.pageTitle": {
"message": "Authors",
"description": "The title of the authors page"
},
"theme.blog.authorsList.viewAll": {
"message": "View All Authors",
"description": "The label of the link targeting the blog authors page"
},
"theme.contentVisibility.unlistedBanner.title": {
"message": "非公開のページ",
"description": "The unlisted content banner title"
},
"theme.contentVisibility.unlistedBanner.message": {
"message": "このページは非公開です。 検索対象外となり、このページのリンクに直接アクセスできるユーザーのみに公開されます。",
"description": "The unlisted content banner message"
},
"theme.contentVisibility.draftBanner.title": {
"message": "Draft page",
"description": "The draft content banner title"
},
"theme.contentVisibility.draftBanner.message": {
"message": "This page is a draft. It will only be visible in dev and be excluded from the production build.",
"description": "The draft content banner message"
},
"theme.ErrorPageContent.tryAgain": {
"message": "もう一度試してください",
"description": "The label of the button to try again rendering when the React error boundary captures an error"
},
"theme.common.skipToMainContent": {
"message": "メインコンテンツまでスキップ",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsPageTitle": {
"message": "タグ",
"description": "The title of the tag list page"
}
}

View File

@ -0,0 +1,14 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

View File

@ -0,0 +1,46 @@
{
"version.label": {
"message": "Next",
"description": "The label for version current"
},
"sidebar.tutorialSidebar.category.Install": {
"message": "インストール",
"description": "The label for category Install in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Kubernetes": {
"message": "Kubernetes",
"description": "The label for category Kubernetes in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Website": {
"message": "ウェブサイト",
"description": "The label for category Website in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Framework": {
"message": "フレームワーク",
"description": "The label for category Framework in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Monitor": {
"message": "モニター",
"description": "The label for category Monitor in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Notification": {
"message": "通知",
"description": "The label for category Notification in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Server Status": {
"message": "サーバーステータス",
"description": "The label for category Server Status in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Telemetry": {
"message": "テレメトリ",
"description": "The label for category Telemetry in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Feed": {
"message": "フィード",
"description": "The label for category Feed in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Develop": {
"message": "開発",
"description": "The label for category Develop in sidebar tutorialSidebar"
}
}

View File

@ -0,0 +1,38 @@
---
sidebar_position: 1
_i18n_hash: f20c701ad093f995d1aad2b2b37ae5ec
---
# 開発の準備
## Dockerを使用したデータベースの準備
```bash
docker run --name tianji-pg -e POSTGRES_DB=tianji -e POSTGRES_USER=tianji -e POSTGRES_PASSWORD=tianji -d postgres:15.4-alpine
```
## .envファイルの準備
```bash
cp .env.example src/server/.env
```
`DATABASE_URL`を`postgresql://tianji:tianji@localhost:5432/tianji?schema=public`に設定します。
以下のようになります:
```ini
DATABASE_URL="postgresql://tianji:tianji@localhost:5432/tianji?schema=public"
ALLOW_OPENAPI=true
```
## データベース構造の準備
データベースにアクセスできるようになりました。以下のコマンドを実行してください:
```bash
cd src/server && pnpm db:migrate:apply
```
## デフォルトアカウント
デフォルトアカウントは`admin`/`admin`です。

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: c65e22ae3d729a07b0b23f525a89b8ca
---
# 環境
以下はDockerで設定できる環境変数です。
| 名前 | デフォルト値 | 説明 |
| ---- | ---- | ----- |
| JWT_SECRET | - | シークレットキーの計算に使用されるランダムな文字列 |
| ALLOW_REGISTER | false | ユーザーがアカウントを登録できるかどうか |
| ALLOW_OPENAPI | false | UIを使用してデータを取得または投稿できるOpenAPIを許可するかどうか |
| SANDBOX_MEMORY_LIMIT | 16 | カスタムスクリプトモニターのサンドボックスメモリ制限単位MB、最小値は8 |
| MAPBOX_TOKEN | - | デフォルトの訪問者マップを置き換えるためのMapBoxトークン |
| AMAP_TOKEN | - | デフォルトの訪問者マップを置き換えるためのAMapトークン |
| CUSTOM_TRACKER_SCRIPT_NAME | - | 広告ブロック用にデフォルトの`tracker.js`スクリプト名を変更 |
| DISABLE_ANONYMOUS_TELEMETRY | false | テレメトリレポートの送信を無効にし、最小限の匿名性で使用状況を公式サイトに報告 |
| DISABLE_AUTO_CLEAR | false | 自動データクリアを無効にする |

View File

@ -0,0 +1,33 @@
---
sidebar_position: 1
_i18n_hash: c24c34a1a9df2ee5bd25253195dcba08
---
# Sentryとの統合
:::info
Sentryの詳細については、[sentry.io](https://sentry.io/)をご覧ください。
:::
`設定` => `統合` => `新しい統合を作成`をクリックします。
![](/img/docs/sentry/sentry1.png)
`内部統合`アプリケーションを作成します。
![](/img/docs/sentry/sentry2.png)
名前に`Tianji`を入力し、Webhook URLをフォームに入力します。
![](/img/docs/sentry/sentry3.png)
`アラートルールアクション`を有効にするのを忘れないでください。
![](/img/docs/sentry/sentry4.png)
次に、問題読み取り`権限`を追加し、Webhookに`問題`と`エラー`を追加します。
![](/img/docs/sentry/sentry5.png)
最後に、アラートルールを作成すると、通知セクションのドロップダウンリストに`Tianji`が表示されます。
![](/img/docs/sentry/sentry6.png)

View File

@ -0,0 +1,31 @@
---
sidebar_position: 1
_i18n_hash: c95e9693eac4df676574d4eb8357881d
---
# Helmでのインストール
Helmは、Kubernetesアプリケーションのインストールと管理を合理化するツールです。Helmを使用すると、Kubernetesでtianjiを簡単かつ迅速に利用できます。
## リポジトリの追加
まず、msgbyteのチャートレジストリをHelmのリポジトリリストに追加する必要があります。
```bash
helm repo add msgbyte https://msgbyte.github.io/charts
```
これで、`helm search`コマンドでtianjiを検索できます。
```bash
helm search repo tianji
```
## インストール
その後、以下のコマンドで簡単にインストールできます:
```bash
helm install tianji msgbyte/tianji
```
これにより、PostgreSQLデータベースとtianjiが提供されます。

View File

@ -0,0 +1,106 @@
---
sidebar_position: 1
_i18n_hash: 3cd3648cd037fe21e115e135f0c9fa5b
---
# 非Docker環境でのインストール
Dockerを使用して`Tianji`をインストールするのが最善の方法で、環境問題を考慮する必要がありません。
しかし、サーバーがDockerをサポートしていない場合は、手動でインストールすることができます。
## 要件
以下が必要です:
- [Node.js](https://nodejs.org/en/download/) 18.12+ / 20.4+
- [pnpm](https://pnpm.io/) 9.x9.7.1が推奨)
- [Git](https://git-scm.com/downloads)
- [postgresql](https://www.postgresql.org/)
- [pm2](https://pm2.keymetrics.io/) - Tianjiをバックグラウンドで実行するため
- [apprise](https://github.com/caronc/apprise) - オプション、通知が必要な場合
## コードのクローンとビルド
```bash
git clone https://github.com/msgbyte/tianji.git
cd tianji
pnpm install
pnpm build
```
## 環境ファイルの準備
`src/server`に`.env`ファイルを作成します。
```ini
DATABASE_URL="postgresql://user:pass@127.0.0.1:5432/tianji?schema=public"
JWT_SECRET="replace-me-with-a-random-string"
```
データベースのURLが正しいことを確認し、データベースを事前に作成しておくことを忘れないでください。
詳細な環境設定については、このドキュメントを参照してください [environment](../environment.md)
> 可能であれば、エンコーディングがen_US.utf8であることを確認することをお勧めします。例`createdb -E UTF8 -l en_US.utf8 tianji`
## サーバーの実行
```bash
npm install pm2 -g && pm2 install pm2-logrotate
# データベースのマイグレーションを初期化
cd src/server
pnpm db:migrate:apply
# サーバーの起動
pm2 start ./dist/src/server/main.js --name tianji
```
デフォルトで、`Tianji`はhttp://localhost:12345で実行されます。
## 新しいバージョンへのコードの更新
```bash
# 新しいリリース/タグをチェックアウト
cd tianji
git fetch --tags
git checkout -q <version>
# 依存関係の更新
pnpm install
# プロジェクトのビルド
pnpm build
# データベースのマイグレーションを実行
cd src/server
pnpm db:migrate:apply
# サーバーの再起動
pm2 restart tianji
```
# よくある質問
## `isolated-vm`のインストールに失敗する
Python 3.12を使用している場合、以下のようなエラーが発生することがあります:
```
ModuleNotFoundError: No module named 'distutils'
```
これは、Python 3.12が`distutils`を組み込みモジュールから削除したためです。現在、これに対する良い解決策があります。
Pythonのバージョンを3.12から3.9に切り替えることで解決できます。
### brewで制御されたPythonでの解決方法
```bash
brew install python@3.9
rm /opt/homebrew/bin/python3
ln -sf /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.9
```
その後、`python3 --version`でバージョンを確認できます。

View File

@ -0,0 +1,46 @@
---
sidebar_position: 1
_i18n_hash: 252240b2a37c8c4784462e75b56d5243
---
# はじめに
## Tianjiとは
一言でまとめると:
**Tianji** = **ウェブサイト分析** + **稼働率モニター** + **サーバーステータス**
### なぜTianjiという名前なのか
Tianji天機、発音 Tiān Jīは中国語で**天の機会**または**戦略**を意味します。
「天」Tiānと「機」はそれぞれ「天」と「機械」または「メカニズム」と訳されます。組み合わせると、高い力や天の力によって導かれるような戦略的または機会的な計画や機会を指すかもしれません。
## 動機
ウェブサイトの観察中、私たちはしばしば複数のアプリケーションを一緒に使用する必要があります。例えば、pv/uvや各ページへの訪問数を確認するために`GA`/`umami`のような分析ツールが必要です。サーバーのネットワーク品質と接続性を確認するために稼働率モニターが必要です。また、サーバーから報告されるステータスを取得してサーバーの品質を確認するためにprometheusを使用する必要があります。さらに、オープンソースで展開できるアプリケーションを開発する場合、他の人の展開状況に関する最も基本的な情報を収集するためにテレメトリシステムが必要になることがよくあります。
これらのツールは同じ目的を果たすべきだと思います。それでは、これらの一般的なニーズを軽量な方法で統合できるアプリケーションはあるのでしょうか?ほとんどの場合、非常に専門的で深い機能は必要ありません。しかし、包括的な監視を実現するためには、これほど多くのサービスをインストールする必要があります。
一つのことに特化するのは良いことです。関連する能力において専門家である場合、そのような専門的なツールが必要です。しかし、軽量なニーズしか持たないほとんどのユーザーにとって、**オールインワン**アプリケーションの方が便利で使いやすいでしょう。
## インストール
Dockerを使ってTianjiをインストールするのは非常に簡単です。dockerとdocker-composeプラグインがインストールされていることを確認してください。
そして、どこでもこれらのコマンドを実行してください:
```bash
wget https://raw.githubusercontent.com/msgbyte/tianji/master/docker-compose.yml
docker compose up -d
```
> デフォルトのアカウントは**admin**/**admin**です。パスワードはすぐに変更してください。
## コミュニティ
仲間のユーザーとつながり、経験を共有し、最新の機能や開発について知るために、私たちの活気あるコミュニティに参加してください。協力し、質問し、Tianjiコミュニティの成長に貢献しましょう。
- [GitHub](https://github.com/msgbyte/tianji)
- [Discord](https://discord.gg/8Vv47wAEej)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/tianji)

View File

@ -0,0 +1,80 @@
---
sidebar_position: 1
_i18n_hash: b3805dea583e9b96a5bf32e57ff9c130
---
# カスタムスクリプト
従来の監視サービスと比較して、**Tianji** はカスタムスクリプトをサポートし、より多くのカスタマイズされたシナリオをサポートします。
本質的に、それは制限されたメモリセーフなJavaScriptランタイムとして理解できます。これは、チャートに表示する数値を受け入れます。最も一般的なシナリオは、URLにアクセスするためのネットワークリクエストに必要な時間です。もちろん、OpenAIの残高やGitHubのスター数など、数値で表現できる他のものもあります。
このスクリプトが-1を返す場合、それはこの作業が失敗したことを意味し、通常の監視と同様に通知を送信しようとします。
数値の変化の傾向を見たい場合、トレンドモードを開くことで、数値の微妙な変化をよりよく発見できます。
以下にいくつかの例を示します:
## 例
### Tailchatの利用可能なサービス数をヘルスエンドポイントから取得
```js
const res = await request({
url: 'https://<tailchat-server-api>/health'
})
if(!res || !res.data || !res.data.services) {
return -1
}
return res.data.services.length
```
### GitHubのスター数を取得
```js
const res = await request({
url: 'https://api.github.com/repos/msgbyte/tianji'
})
return res.data.stargazers_count ?? -1
```
`msgbyte/tianji` を自分のリポジトリ名に置き換えてください。
### Dockerのプル数を取得
```js
const res = await request({
url: "https://hub.docker.com/v2/repositories/moonrailgun/tianji/"
});
return res.data.pull_count;
```
`moonrailgun/tianji` を自分のイメージ名に置き換えてください。
### テキストマッチの例
```js
const start = Date.now();
const res = await request({
url: "https://example.com/"
});
const usage = Date.now() - start;
const matched = /maintain/.test(String(res.data));
if(matched) {
return -1;
}
return usage;
```
`-1` を返すことは何かが間違っていることを意味します。この場合、HTML本文に `maintain` というテキストが含まれていることを意味します。
### またはそれ以上
このページにスクリプトを提出することを非常に歓迎します。Tianjiはオープンソースコミュニティによって推進されています。

View File

@ -0,0 +1,45 @@
---
sidebar_position: 5
_i18n_hash: 4ea8ae049c2d4b09f2847744ac37545f
---
# Webhook
より柔軟な通知方法が必要な場合は、カスタムWebhookを使用してメッセージを通知することができます。この方法で、天機の通知を任意のシステムに統合することができます。
### 例
天機システムは、以下の例のような内容でPOSTリクエストを送信します。
```json
{
"notification": {
"workspaceId": "xxxxxxxxxxx",
"name": "新しい通知",
"type": "webhook",
"payload": {
"webhookUrl": "example.com"
}
},
"title": "新しい通知のテスト",
"content": "天機: すべての洞察\\nこれは新しい通知からの通知テストです\\n[image]",
"raw": [
{
"type": "title",
"level": 2,
"content": "天機: すべての洞察"
},
{
"type": "text",
"content": "これは新しい通知からの通知テストです"
},
{
"type": "newline"
},
{
"type": "image",
"url": "https://tianji.msgbyte.com/img/social-card.png"
}
],
"time": "2024-06-19T15:41:09.390Z"
}
```

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: 7ce5eca3bf7af802db48c3db37d996f5
---
# サーバーステータスページ
ユーザーがサーバーのステータスを公開したい場合、サーバーステータスページを作成できます。
## カスタムドメインの設定
ステータスページを独自のドメインで設定できます。例えば、`status.example.com` のように設定します。
ページ設定で設定し、DNSダッシュボードで `CNAME` レコードを作成します。
```
CNAME status.example.com tianji.example.com
```
その後、カスタムドメイン `status.example.com` でページにアクセスできます。

View File

@ -0,0 +1,68 @@
---
sidebar_position: 1
_i18n_hash: 848acc7fae249b1c435a363e4693a5c7
---
# サーバーステータスレポーター
tianjiレポーターを使用して、サーバーのステータスを簡単に報告できます。
[https://github.com/msgbyte/tianji/releases](https://github.com/msgbyte/tianji/releases) からダウンロードできます。
## 使用方法
```
tianji-reporter の使用方法:
--interval int
間隔を秒単位で入力します (デフォルト 5)
--mode http
レポートデータの送信モードを選択します: `http` または `udp`、デフォルトは `http` (デフォルト "http")
--name string
このマシンの識別名
--url string
tianjiのhttp URL、例: https://tianji.msgbyte.com
--vnstat
トラフィック統計にvnstatを使用します、Linuxのみ
--workspace string
tianjiのワークスペースID、これはUUIDである必要があります
```
**url** と **workspace** は必須です。これは、サービスをどのホストとワークスペースに報告するかを意味します。
デフォルトでは、サーバーノード名はホスト名と同じになります。したがって、`--name` を使用してサーバーを識別できるようにカスタマイズできます。
## 自動インストールスクリプト
`Tianji` -> `Servers` -> `Add` -> `Auto` タブで自動インストールスクリプトを取得できます。
レポーターを自動的にダウンロードし、Linuxサービスをマシンに作成します。したがって、root権限が必要です。
### アンインストール
レポーターサービスをアンインストールしたい場合は、次のコマンドを使用できます:
```bash
curl -o- https://tianji.exmaple.com/serverStatus/xxxxxxxxxxxxxxxxxxx/install.sh?url=https://tianji.example.com | bash -s uninstall
```
主な変更点は、インストールコマンドの後に `-s uninstall` を追加することです。
## Q&A
### tianjiレポーターサービスのログを確認するにはどうすればいいですか
自動インストールスクリプトでインストールした場合、tianjiは `tianji-reporter` という名前のサービスをLinuxマシンにインストールします。
次のコマンドを使用してtianjiレポーターのログを確認できます:
```bash
journalctl -fu tianji-reporter.service
```
### レポートが成功しているのにサーバータブにマシンが表示されない
tianjiが `nginx` などのリバースプロキシの背後にある可能性があります。
リバースプロキシがWebSocketをサポートしていることを確認してください。
## なぜマシンが常にオフラインなのですか?
サーバーの日時を確認してください。

View File

@ -0,0 +1,14 @@
---
sidebar_position: 99
_i18n_hash: 6bc67c1ed8a9a26ff57ad81aa4fa0b16
---
# 特別な感謝
## オープンソースプロジェクト
Tianjiはこれらのプロジェクトから大きなインスピレーションを受けています。オープンソースコミュニティへの貢献に感謝します。
私もこれらのプロジェクトが大好きです。これらの優れたプロジェクトに敬礼!
- [umami](https://github.com/umami-software/umami)
- [uptime kuma](https://github.com/louislam/uptime-kuma)

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: c61b6c9968c295ffdfdc1a484f853504
---
# はじめに
## 背景
コンテンツクリエイターとして、私たちはしばしば様々なサードパーティプラットフォームに記事を公開します。しかし、コンテンツに真剣に取り組んでいる私たちにとって、公開は始まりに過ぎません。私たちは、時間の経過とともに記事の読者数を継続的に監視する必要があります。残念ながら、私たちのデータ収集能力は各プラットフォームが提供するものに限定されており、それはプラットフォーム自身の能力に大きく依存しています。さらに、同じコンテンツを異なるプラットフォームに配信する場合、読者数や訪問データは完全に分離されています。
開発者として、私は多くのソフトウェアアプリケーションを作成します。しかし、これらのアプリケーションをリリースした後、私はしばしばそれらを制御できなくなります。例えば、コマンドラインプログラムをリリースした後、ユーザーがそれをどのように操作しているのか、さらには私のアプリケーションを使用しているユーザーが何人いるのかを知る方法がありません。同様に、オープンソースアプリケーションを開発する場合、過去にはGitHubのスターを通じてしか関心を測定できず、実際の使用状況については不明のままでした。
したがって、私たちは個人のプライバシーやその他の制限を尊重しながら、最小限の情報を収集するシンプルなソリューションを必要としています。このソリューションがテレメトリです。
## テレメトリ
コンピューティングの分野では、テレメトリは、プライバシーの懸念に対応しながら、コンテンツクリエイターの基本的な分析ニーズを満たすために、最小限かつ匿名の情報報告を行う一般的な技術です。
例えば、ReactのNext.jsフレームワークはテレメトリを使用して情報を収集します[APIリファレンス: Next.js CLI | Next.js (nextjs.org)](https://nextjs.org/docs/app/api-reference/next-cli#telemetry)
または、記事に1pxサイズの空白の透明なピクセル画像を埋め込むことで、制御できないウェブサイトの訪問者データを収集することが可能です。現代のブラウザとほとんどのウェブサイトは、セキュリティリスクの可能性からカスタムスクリプトの挿入をブロックします。しかし、画像は比較的無害に見えます。ほとんどすべてのウェブサイトはサードパーティの画像の読み込みを許可しており、テレメトリは実行可能です。
## 画像を通じてどのような情報を収集できるのか?
驚くべきことに、1つの画像リクエストを受け取ることで、予想以上の情報を収集することができます。
ネットワークリクエストを分析することで、ユーザーのIPアドレス、訪問時間、リファラー、デバイスタイプを取得することができます。これにより、ピーク読者数の時間やトレンド、人口統計分布、異なるプラットフォーム間のトラフィックの粒度など、トラフィックパターンを分析することができます。この情報は、マーケティングやプロモーション活動に特に価値があります。
![](/img/telemetry/1.png)
## テレメトリをどのように実装できるのか?
テレメトリは、基本的にインターネットリクエストを受け取るエンドポイントが必要なシンプルな技術です。そのシンプルさから、この目的のための専用ツールはほとんどありません。多くの人は分析を重要視していないか、初期の障壁によって妨げられるかもしれません。しかし、そのような機能の需要は明らかです。
テレメトリソリューションの開発は簡単です。プロジェクトを作成し、ルートを設定し、リクエストボディから情報を収集し、空白の画像を返すだけです。
Node.jsを使用した例を以下に示します
```jsx
router.get(
'/telemetry.gif',
async (req, res) => {
const ip = req.ip;
const referer = req.header['referer'];
const userAgent = req.headers['user-agent'];
// データベースに保存する
const blankGifBuffer = Buffer.from(
'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'base64'
);
res.header('Content-Type', 'image/gif').send(blankGifBuffer);
}
);
```
独自のソリューションを開発したくない場合は、Tianjiをお勧めします。**ウェブサイト分析**、**稼働時間監視**、**サーバーステータス**を提供するオープンソースプロジェクトとして、Tianjiは最近テレメトリ機能を導入し、コンテンツクリエイターがテレメトリを報告するのを支援し、より良いデータ収集を促進します。最も重要なのは、オープンソースであるため、データを制御でき、複数のプラットフォームからのトラフィックを1か所で集約でき、異なる場所で同じ情報を見ることによる断片化を避けることができます。
![](/img/telemetry/2.png)
GitHub: [https://github.com/msgbyte/tianji](https://github.com/msgbyte/tianji)
公式ウェブサイト: [https://tianji.msgbyte.com/](https://tianji.msgbyte.com/)

View File

@ -0,0 +1,29 @@
---
sidebar_position: 2
_i18n_hash: ca2b25a29f0f1a82407be367a1d03553
---
# パラメータ
ここでは、テレメトリイメージを使用して設定する方法の例を示します。
すべてオプションです。異なる場所での使用を改善します。
| 名前 | 説明 |
| -------- | --------- |
| url | デフォルトでは、ブラウザによって自動生成されるリファラーURLを取得しますが、一部のウェブサイトではこのヘッダーを持ち込むことが許可されていません。そのため、自分で持ち込む必要があります。天機がどこにもURLを取得できない場合、システムは無視し、この訪問を記録しません。 |
| name | テレメトリイベント名を定義します。同じテレメトリレコード内の異なるイベントを区別するために使用できます。 |
| title | **[バッジのみ]**、バッジのタイトルを定義します。 |
| start | **[バッジのみ]**、バッジの開始カウント数を定義します。 |
| fullNum | **[バッジのみ]**、バッジが完全な数値を表示するかどうかを定義します。デフォルトでは省略形の桁数です(例:`12345` と `12.3k`)。 |
## 使用方法
URLにパラメータを簡単に持ち込むことができます。
例えば:
```
https://tianji.example.com/telemetry/<workspaceId>/<telemetryId>/badge.svg?name=myEvent&url=https://google.com&title=My+Counter&start=100000&fullNum=true
```
これに慣れていない場合は、このページに関するWikiページを確認できます[https://en.wikipedia.org/wiki/Query_string](https://en.wikipedia.org/wiki/Query_string)

View File

@ -0,0 +1,25 @@
---
sidebar_position: 1
_i18n_hash: 3e7ad33b9d88240c2ee01504fb17ed2d
---
# Docusaurusでの使用
`docusaurus.config.js` で:
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
scripts: [
{
src: 'https://<your domain>/tracker.js',
async: true,
defer: true,
'data-website-id': '<your-website-id>',
},
],
};
module.exports = config;
```

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: bcb6522b66b64594f82548e296f77934
---
# トラッカースクリプト
## インストール
ウェブサイトのイベントを追跡するには、シンプルなスクリプト(< 2 KBをウェブサイトに挿入するだけです
スクリプトは以下のようになります:
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx"></script>
```
このスクリプトコードは、**Tianji** のウェブサイトリストから取得できます。
## イベントの報告
**Tianji** は、ユーザーのクリックイベントを報告する簡単な方法を提供しています。これにより、ユーザーが好むアクションや頻繁に使用するアクションを追跡するのが容易になります。
これはウェブサイト分析で非常に一般的な方法です。**Tianji** を使用してすぐに取得できます。
スクリプトコードをウェブサイトに挿入した後、DOM属性に `data-tianji-event` を追加するだけです。
例えば:
```html
<button data-tianji-event="submit-login-form">Login</button>
```
これで、ユーザーがこのボタンをクリックすると、ダッシュボードに新しいイベントが届きます。
## デフォルトのスクリプト名を変更する
> この機能は v1.7.4 以降で利用可能です。
起動時に環境変数 `CUSTOM_TRACKER_SCRIPT_NAME` を使用できます。
例えば:
```
CUSTOM_TRACKER_SCRIPT_NAME="my-tracker.js"
```
その後、トラッカースクリプトに `"https://<your-self-hosted-domain>/my-tracker.js"` でアクセスできます。
これは、一部の広告ブロッカーを回避するのに役立ちます。
`.js` 拡張子は必要ありません。任意のパスを選択できます。例えば、`CUSTOM_TRACKER_SCRIPT_NAME="this/is/very/long/path"` のように使用することもできます。
## 特定のドメインのみを追跡する
一般的に、トラッカーはサイトが実行されている場所ですべてのイベントを報告します。しかし、時には `localhost` のようなイベントを無視する必要があります。
Tianji は、トラッカースクリプトの属性を提供してそれを行います。
スクリプトに `data-domains` を追加できます。値は追跡するルートドメインである必要があります。複数のドメインを区切るには `,` を使用します。
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx" data-domains="website.com,www.website.com"></script>
```
これにより、これらのドメインからのイベントのみを確認できます。

View File

@ -0,0 +1,46 @@
{
"link.title.Docs": {
"message": "ドキュメント",
"description": "The title of the footer links column with title=Docs in the footer"
},
"link.title.Community": {
"message": "コミュニティ",
"description": "The title of the footer links column with title=Community in the footer"
},
"link.title.More": {
"message": "もっと",
"description": "The title of the footer links column with title=More in the footer"
},
"link.item.label.Tutorial": {
"message": "チュートリアル",
"description": "The label of footer link with label=Tutorial linking to /docs/intro"
},
"link.item.label.Stack Overflow": {
"message": "Stack Overflow",
"description": "The label of footer link with label=Stack Overflow linking to https://stackoverflow.com/questions/tagged/tianji"
},
"link.item.label.Discord": {
"message": "Discord",
"description": "The label of footer link with label=Discord linking to https://discord.gg/8Vv47wAEej"
},
"link.item.label.Twitter": {
"message": "Twitter",
"description": "The label of footer link with label=Twitter linking to https://twitter.com/moonrailgun"
},
"link.item.label.Changelog": {
"message": "変更履歴",
"description": "The label of footer link with label=Changelog linking to /changelog"
},
"link.item.label.API": {
"message": "API",
"description": "The label of footer link with label=API linking to /api"
},
"link.item.label.GitHub": {
"message": "GitHub",
"description": "The label of footer link with label=GitHub linking to https://github.com/msgbyte/tianji"
},
"copyright": {
"message": "Copyright © 2024 Tianji, Inc. Built with Msgbyte.",
"description": "The footer copyright"
}
}

View File

@ -0,0 +1,38 @@
{
"title": {
"message": "Tianji",
"description": "The title in the navbar"
},
"logo.alt": {
"message": "Tianji Logo",
"description": "The alt text of navbar logo"
},
"item.label.Docs": {
"message": "ドキュメント",
"description": "Navbar item with label Docs"
},
"item.label.Pricing": {
"message": "価格設定",
"description": "Navbar item with label Pricing"
},
"item.label.Changelog": {
"message": "変更履歴",
"description": "Navbar item with label Changelog"
},
"item.label.API": {
"message": "API",
"description": "Navbar item with label API"
},
"item.label.Demo": {
"message": "デモ",
"description": "Navbar item with label Demo"
},
"item.label.Discord": {
"message": "Discord",
"description": "Navbar item with label Discord"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

View File

@ -0,0 +1,309 @@
{
"theme.ErrorPageContent.title": {
"message": "页面已崩溃。",
"description": "The title of the fallback page when the page crashed"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "回到顶部",
"description": "The ARIA label for the back to top button"
},
"theme.blog.archive.title": {
"message": "历史博文",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "历史博文",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.paginator.navAriaLabel": {
"message": "博文列表分页导航",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "较新的博文",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "较旧的博文",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "博文分页导航",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "较新一篇",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "较旧一篇",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.tags.tagsPageLink": {
"message": "查看所有标签",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "切换浅色/暗黑模式(当前为{mode}",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "暗黑模式",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "浅色模式",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "页面路径",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription.plurals": {
"message": "{count} 个项目",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "文件选项卡",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "上一页",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "下一页",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "{count} 篇文档带有标签",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "{nDocsTagged}「{tagName}」",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "版本:{versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版尚未发行的文档。",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版的文档,现已不再积极维护。",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "最新的文档请参阅 {latestVersionLink} ({versionLabel})。",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "最新版本",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "编辑此页",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "{heading}的直接链接",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": "于 {date} ",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": "由 {user} ",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "最后{byUser}{atDate}更新",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "选择版本",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.NotFound.title": {
"message": "找不到页面",
"description": "The title of the 404 page"
},
"theme.tags.tagsListLabel": {
"message": "标签:",
"description": "The label alongside a tag list"
},
"theme.admonition.caution": {
"message": "警告",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.admonition.danger": {
"message": "危险",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "信息",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.note": {
"message": "备注",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "提示",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.warning": {
"message": "注意",
"description": "The default label used for the Warning admonition (:::warning)"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "关闭",
"description": "The ARIA label for close button of announcement bar"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "最近博文导航",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "复制成功",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "复制代码到剪贴板",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "复制",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "切换自动换行",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.expandCategoryAriaLabel": {
"message": "展开侧边栏分类 '{label}'",
"description": "The ARIA label to expand the sidebar category"
},
"theme.DocSidebarItem.collapseCategoryAriaLabel": {
"message": "折叠侧边栏分类 '{label}'",
"description": "The ARIA label to collapse the sidebar category"
},
"theme.NavBar.navAriaLabel": {
"message": "主导航",
"description": "The ARIA label for the main navigation"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "选择语言",
"description": "The label for the mobile language switcher dropdown"
},
"theme.NotFound.p1": {
"message": "我们找不到您要找的页面。",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。",
"description": "The 2nd paragraph of the 404 page"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "本页总览",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.blog.post.readMore": {
"message": "阅读更多",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.readMoreLabel": {
"message": "阅读 {title} 的全文",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readingTime.plurals": {
"message": "阅读需 {readingTime} 分钟",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.breadcrumbs.home": {
"message": "主页面",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.navAriaLabel": {
"message": "文档侧边栏",
"description": "The ARIA label for the sidebar navigation"
},
"theme.docs.sidebar.closeSidebarButtonAriaLabel": {
"message": "关闭导航栏",
"description": "The ARIA label for close button of mobile sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← 回到主菜单",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
"message": "切换导航栏",
"description": "The ARIA label for hamburger menu button of mobile navigation"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.blog.post.plurals": {
"message": "{count} 篇博文",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "{nPosts} 含有标签「{tagName}」",
"description": "The title of the page for a blog tag"
},
"theme.blog.author.pageTitle": {
"message": "{authorName} - {nPosts}",
"description": "The title of the page for a blog author"
},
"theme.blog.authorsList.pageTitle": {
"message": "Authors",
"description": "The title of the authors page"
},
"theme.blog.authorsList.viewAll": {
"message": "View All Authors",
"description": "The label of the link targeting the blog authors page"
},
"theme.contentVisibility.unlistedBanner.title": {
"message": "未列出页",
"description": "The unlisted content banner title"
},
"theme.contentVisibility.unlistedBanner.message": {
"message": "此页面未列出。搜索引擎不会对其索引,只有拥有直接链接的用户才能访问。",
"description": "The unlisted content banner message"
},
"theme.contentVisibility.draftBanner.title": {
"message": "Draft page",
"description": "The draft content banner title"
},
"theme.contentVisibility.draftBanner.message": {
"message": "This page is a draft. It will only be visible in dev and be excluded from the production build.",
"description": "The draft content banner message"
},
"theme.ErrorPageContent.tryAgain": {
"message": "重试",
"description": "The label of the button to try again rendering when the React error boundary captures an error"
},
"theme.common.skipToMainContent": {
"message": "跳到主要内容",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsPageTitle": {
"message": "标签",
"description": "The title of the tag list page"
}
}

View File

@ -0,0 +1,14 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

View File

@ -0,0 +1,46 @@
{
"version.label": {
"message": "Next",
"description": "The label for version current"
},
"sidebar.tutorialSidebar.category.Install": {
"message": "安装",
"description": "The label for category Install in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Kubernetes": {
"message": "Kubernetes",
"description": "The label for category Kubernetes in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Website": {
"message": "网站",
"description": "The label for category Website in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Framework": {
"message": "框架",
"description": "The label for category Framework in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Monitor": {
"message": "监控器",
"description": "The label for category Monitor in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Notification": {
"message": "通知",
"description": "The label for category Notification in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Server Status": {
"message": "服务器状态",
"description": "The label for category Server Status in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Telemetry": {
"message": "遥测技术",
"description": "The label for category Telemetry in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Feed": {
"message": "Feed流",
"description": "The label for category Feed in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.Develop": {
"message": "开发",
"description": "The label for category Develop in sidebar tutorialSidebar"
}
}

View File

@ -0,0 +1,38 @@
---
sidebar_position: 1
_i18n_hash: f20c701ad093f995d1aad2b2b37ae5ec
---
# 准备开发
## 准备使用 Docker 的数据库
```bash
docker run --name tianji-pg -e POSTGRES_DB=tianji -e POSTGRES_USER=tianji -e POSTGRES_PASSWORD=tianji -d postgres:15.4-alpine
```
## 准备 .env 文件
```bash
cp .env.example src/server/.env
```
`DATABASE_URL` 配置为 `postgresql://tianji:tianji@localhost:5432/tianji?schema=public`
如下所示:
```ini
DATABASE_URL="postgresql://tianji:tianji@localhost:5432/tianji?schema=public"
ALLOW_OPENAPI=true
```
## 准备数据库结构
现在你可以访问数据库,并可以访问
```bash
cd src/server && pnpm db:migrate:apply
```
## 默认账户
默认账户为 `admin`/`admin`

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: c65e22ae3d729a07b0b23f525a89b8ca
---
# 环境
以下是可以在 Docker 中配置的环境变量
| 名称 | 默认值 | 描述 |
| ---- | ---- | ----- |
| JWT_SECRET | - | 用于计算密钥的随机字符串 |
| ALLOW_REGISTER | false | 是否允许用户注册账户 |
| ALLOW_OPENAPI | false | 是否允许使用 OpenAPI 进行数据获取或提交,类似于通过 UI 操作 |
| SANDBOX_MEMORY_LIMIT | 16 | 自定义脚本监控沙盒内存限制控制监控脚本不占用过多内存单位MB最小值为 8 |
| MAPBOX_TOKEN | - | 用于替换默认访客地图的 MapBox 令牌 |
| AMAP_TOKEN | - | 用于替换默认访客地图的高德地图令牌 |
| CUSTOM_TRACKER_SCRIPT_NAME | - | 修改默认的 `tracker.js` 脚本名称以避免广告拦截 |
| DISABLE_ANONYMOUS_TELEMETRY | false | 禁用向天机官方发送遥测报告,我们会在最小匿名化的前提下向天机官网报告使用情况。 |
| DISABLE_AUTO_CLEAR | false | 禁用自动清除数据。 |

View File

@ -0,0 +1,33 @@
---
sidebar_position: 1
_i18n_hash: 50d9b12be939f0ba179beb1cd468e4f4
---
# 与 Sentry 集成
:::info
在 [sentry.io](https://sentry.io/) 了解更多关于 Sentry 的信息
:::
点击 `设置` => `集成` => `创建新集成`
![](/img/docs/sentry/sentry1.png)
创建一个 `内部集成` 应用程序
![](/img/docs/sentry/sentry2.png)
输入名称 `Tianji` 并将 webhook URL 填入表单。
![](/img/docs/sentry/sentry3.png)
别忘了启用 `警报规则操作`
![](/img/docs/sentry/sentry4.png)
然后,添加问题读取 `权限`,并为 webhook 添加 `问题``错误`
![](/img/docs/sentry/sentry5.png)
最后,您可以创建一个警报规则,并在通知部分的下来列表中看到 `Tianji`
![](/img/docs/sentry/sentry6.png)

View File

@ -0,0 +1,31 @@
---
sidebar_position: 1
_i18n_hash: c95e9693eac4df676574d4eb8357881d
---
# 使用 Helm 安装
Helm 是一个简化 Kubernetes 应用程序安装和管理的工具。通过 Helm您可以轻松快速地在 Kubernetes 中享受 tianji。
## 添加仓库
首先,您需要将 msgbyte 的 charts 仓库添加到 Helm 仓库列表中。
```bash
helm repo add msgbyte https://msgbyte.github.io/charts
```
现在,您可以使用 `helm search` 命令搜索 tianji。
```bash
helm search repo tianji
```
## 安装
然后,您可以使用以下命令轻松安装:
```bash
helm install tianji msgbyte/tianji
```
这将为您带来一个 PostgreSQL 数据库和 tianji。

View File

@ -0,0 +1,106 @@
---
sidebar_position: 1
_i18n_hash: 3cd3648cd037fe21e115e135f0c9fa5b
---
# 无 Docker 安装
使用 Docker 安装 `Tianji` 是最好的方式,你不需要考虑环境问题。
但如果你无法在服务器上使用 Docker可以尝试手动安装。
## 要求
你需要:
- [Node.js](https://nodejs.org/en/download/) 18.12+ / 20.4+
- [pnpm](https://pnpm.io/) 9.x9.7.1 更好)
- [Git](https://git-scm.com/downloads)
- [postgresql](https://www.postgresql.org/)
- [pm2](https://pm2.keymetrics.io/) - 用于在后台运行 Tianji
- [apprise](https://github.com/caronc/apprise) - 可选,如果你需要通知功能
## 克隆代码并构建
```bash
git clone https://github.com/msgbyte/tianji.git
cd tianji
pnpm install
pnpm build
```
## 准备环境文件
`src/server` 目录下创建一个 `.env` 文件
```ini
DATABASE_URL="postgresql://user:pass@127.0.0.1:5432/tianji?schema=public"
JWT_SECRET="replace-me-with-a-random-string"
```
确保你的数据库 URL 是正确的,并且记得在之前创建数据库。
更多环境配置可以查看此文档 [environment](../environment.md)
> 如果可以,最好确保你的编码是 en_US.utf8例如`createdb -E UTF8 -l en_US.utf8 tianji`
## 运行服务器
```bash
npm install pm2 -g && pm2 install pm2-logrotate
# 初始化数据库迁移
cd src/server
pnpm db:migrate:apply
# 启动服务器
pm2 start ./dist/src/server/main.js --name tianji
```
默认情况下,`Tianji` 将在 http://localhost:12345 上运行
## 更新代码到新版本
```bash
# 检出新的发布/标签
cd tianji
git fetch --tags
git checkout -q <version>
# 更新依赖
pnpm install
# 构建项目
pnpm build
# 运行数据库迁移
cd src/server
pnpm db:migrate:apply
# 重启服务器
pm2 restart tianji
```
# 常见问题
## 安装 `isolated-vm` 失败
如果你使用的是 Python 3.12,会报告如下错误:
```
ModuleNotFoundError: No module named 'distutils'
```
这是因为 Python 3.12 从内置模块中移除了 `distutils`。现在我们有了解决方案。
你可以将 Python 版本从 3.12 切换到 3.9 来解决这个问题。
### 如何在 brew 控制的 Python 中解决这个问题
```bash
brew install python@3.9
rm /opt/homebrew/bin/python3
ln -sf /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.9
```
然后你可以使用 `python3 --version` 检查版本

View File

@ -0,0 +1,46 @@
---
sidebar_position: 1
_i18n_hash: 252240b2a37c8c4784462e75b56d5243
---
# 介绍
## 什么是天机
一句话总结:
**天机** = **网站分析** + **运行时间监控** + **服务器状态**
### 为什么叫天机?
天机(天机,发音 Tiān Jī)在中文中意味着**天赐良机**或**策略**
“天”(Tiān)和“机”(Jī)可以分别翻译为“天堂”和“机器”或“机制”。当它们结合在一起时,可能指的是由更高力量或天体力量策划的战略或机会性计划或机会。
## 动机
在我们观察网站的过程中,我们经常需要同时使用多个应用程序。例如,我们需要像 `GA`/`umami` 这样的分析工具来检查 pv/uv 和每个页面的访问次数,我们需要一个运行时间监控器来检查服务器的网络质量和连接性,我们还需要使用 prometheus 来获取服务器报告的状态以检查服务器的质量。此外,如果我们开发一个允许开源部署的应用程序,我们通常需要一个遥测系统来帮助我们收集其他人部署情况的最基本信息。
我认为这些工具应该服务于同一个目的,那么是否有一个应用程序可以以轻量级的方式集成这些常见需求呢?毕竟,大多数时候我们不需要非常专业和深入的功能。但为了实现全面的监控,我需要安装这么多服务。
专精于一件事是好的,如果我们是相关能力的专家,我们需要这样的专业工具。但对于大多数只有轻量级需求的用户来说,一个**一体化**应用程序将更加方便和易于使用。
## 安装
使用 Docker 安装天机非常简单。只需确保你已经安装了 docker 和 docker-compose 插件
然后,在任何地方运行以下命令:
```bash
wget https://raw.githubusercontent.com/msgbyte/tianji/master/docker-compose.yml
docker compose up -d
```
> 默认账户是 **admin**/**admin**,请尽快更改密码。
## 社区
加入我们蓬勃发展的社区,与同行用户建立联系,分享经验,并及时了解最新的功能和发展。合作、提问并贡献于天机社区的成长。
- [GitHub](https://github.com/msgbyte/tianji)
- [Discord](https://discord.gg/8Vv47wAEej)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/tianji)

View File

@ -0,0 +1,80 @@
---
sidebar_position: 1
_i18n_hash: b3805dea583e9b96a5bf32e57ff9c130
---
# 自定义脚本
与传统的监控服务相比,**天机** 支持自定义脚本来支持更多定制化场景。
本质上,你可以将其理解为一个受限的、内存安全的 JavaScript 运行时,它接受一个数字来显示在你的图表上。最常见的场景是访问一个 URL 所需的网络请求时间。当然,它也可以是其他东西,例如你的 OpenAI 余额、你的 GitHub 星标数量,以及所有可以用数字表示的信息。
如果此脚本返回 -1则表示此工作失败并尝试向你发送通知就像正常监控一样。
如果你想查看一个数字变化的趋势,开启趋势模式可以帮助你更好地发现数字的细微变化。
以下是一些示例:
## 示例
### 从健康端点获取 Tailchat 可用服务数量
```js
const res = await request({
url: 'https://<tailchat-server-api>/health'
})
if(!res || !res.data || !res.data.services) {
return -1
}
return res.data.services.length
```
### 获取 GitHub 星标数量
```js
const res = await request({
url: 'https://api.github.com/repos/msgbyte/tianji'
})
return res.data.stargazers_count ?? -1
```
`msgbyte/tianji` 替换为你自己的仓库名称
### 获取 Docker 拉取数量
```js
const res = await request({
url: "https://hub.docker.com/v2/repositories/moonrailgun/tianji/"
});
return res.data.pull_count;
```
`moonrailgun/tianji` 替换为你自己的镜像名称
### 匹配文本的示例
```js
const start = Date.now();
const res = await request({
url: "https://example.com/"
});
const usage = Date.now() - start;
const matched = /maintain/.test(String(res.data));
if(matched) {
return -1;
}
return usage;
```
返回 `-1` 表示某些地方出错了。在这种情况下,表示 HTML 主体中包含 `maintain` 文本。
### 或者更多
非常欢迎你在这个页面提交你的脚本。天机是由开源社区驱动的。

View File

@ -0,0 +1,45 @@
---
sidebar_position: 5
_i18n_hash: 4ea8ae049c2d4b09f2847744ac37545f
---
# Webhook
如果你需要更灵活的通知方式可以尝试使用自定义Webhook来通知你的消息。这样你可以将天机的通知集成到任何系统中。
### 示例结果
天机系统将发送一个包含以下示例内容的POST请求。
```json
{
"notification": {
"workspaceId": "xxxxxxxxxxx",
"name": "新通知",
"type": "webhook",
"payload": {
"webhookUrl": "example.com"
}
},
"title": "新通知测试",
"content": "天机:洞察一切\\n这是来自新通知的测试通知\\n[图片]",
"raw": [
{
"type": "title",
"level": 2,
"content": "天机:洞察一切"
},
{
"type": "text",
"content": "这是来自新通知的测试通知"
},
{
"type": "newline"
},
{
"type": "image",
"url": "https://tianji.msgbyte.com/img/social-card.png"
}
],
"time": "2024-06-19T15:41:09.390Z"
}
```

View File

@ -0,0 +1,19 @@
---
sidebar_position: 2
_i18n_hash: 7ce5eca3bf7af802db48c3db37d996f5
---
# 服务器状态页面
您可以为用户创建一个服务器状态页面,以便向公众展示您的服务器状态。
## 配置自定义域名
您可以在自己的域名上配置状态页面,例如:`status.example.com`
在页面配置中设置并在您的DNS控制面板中创建一个`CNAME`记录。
```
CNAME status.example.com tianji.example.com
```
然后您可以通过自定义域名`status.example.com`访问您的页面。

View File

@ -0,0 +1,68 @@
---
sidebar_position: 1
_i18n_hash: 848acc7fae249b1c435a363e4693a5c7
---
# 服务器状态报告器
您可以使用天玑报告器轻松报告您的服务器状态。
您可以从 [https://github.com/msgbyte/tianji/releases](https://github.com/msgbyte/tianji/releases) 下载。
## 使用方法
```
tianji-reporter 使用方法:
--interval int
输入间隔时间,单位为秒 (默认 5)
--mode http
报告数据的发送模式,可选:`http` 或 `udp`,默认是 `http` (默认 "http")
--name string
此机器的标识名称
--url string
天玑的 http 地址例如https://tianji.msgbyte.com
--vnstat
使用 vnstat 进行流量统计,仅限 Linux
--workspace string
天玑的工作区 ID应为 UUID
```
**url** 和 **workspace** 是必需的,表示您将服务报告到哪个主机和工作区。
默认情况下,服务器节点名称将与主机名相同,因此您可以使用 `--name` 自定义名称,以便识别服务器。
## 自动安装脚本
您可以在 `天玑` -> `服务器` -> `添加` -> `自动` 标签中获取自动安装脚本。
它将自动下载报告器并在您的机器上创建 Linux 服务。因此,它需要 root 权限。
### 卸载
如果您想卸载报告器服务,可以使用以下命令:
```bash
curl -o- https://tianji.exmaple.com/serverStatus/xxxxxxxxxxxxxxxxxxx/install.sh?url=https://tianji.example.com | bash -s uninstall
```
主要变化是在安装命令后添加 `-s uninstall`
## 常见问题
### 如何查看天玑报告器服务日志?
如果您使用自动安装脚本进行安装,天玑将帮助您在 Linux 机器上安装一个名为 `tianji-reporter` 的服务。
您可以使用以下命令查看天玑报告器日志:
```bash
journalctl -fu tianji-reporter.service
```
### 即使在报告成功后,服务器标签中仍未找到您的机器
可能您的天玑位于反向代理(例如 `nginx`)之后。
请确保您的反向代理添加了 WebSocket 支持。
## 为什么我的机器总是离线?
请检查您的服务器时间。

View File

@ -0,0 +1,14 @@
---
sidebar_position: 99
_i18n_hash: 6bc67c1ed8a9a26ff57ad81aa4fa0b16
---
# 特别感谢
## 开源项目
天玑深受这些项目的启发,感谢你们为开源社区做出的贡献。
我也非常喜欢这些项目。向这些优秀的项目致敬!
- [umami](https://github.com/umami-software/umami)
- [uptime kuma](https://github.com/louislam/uptime-kuma)

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: c61b6c9968c295ffdfdc1a484f853504
---
# 介绍
## 背景
作为内容创作者,我们经常在各种第三方平台上发布文章。然而,对于那些认真对待自己内容的人来说,发布只是开始。我们需要持续监控文章的阅读量。不幸的是,我们的数据收集能力仅限于每个平台提供的内容,这严重依赖于平台自身的能力。此外,当我们在不同平台上分发相同内容时,阅读量和访问数据是完全隔离的。
作为一名开发者我创建了许多软件应用程序。然而一旦我发布这些应用程序我常常失去对它们的控制。例如在发布一个命令行程序后我无法知道用户如何与之交互甚至有多少用户在使用我的应用程序。同样在开发开源应用程序时过去我只能通过GitHub星标来衡量兴趣对实际使用情况一无所知。
因此,我们需要一个简单的解决方案,收集最少的信息,尊重个人隐私和其他限制。这个解决方案就是遥测技术。
## 遥测技术
在计算领域,遥测技术是一种常见的技术,它涉及最小化和匿名化地报告信息,以适应隐私问题,同时仍然满足内容创作者的基本分析需求。
例如React的Next.js框架使用遥测技术收集信息[API参考Next.js CLI | Next.js (nextjs.org)](https://nextjs.org/docs/app/api-reference/next-cli#telemetry)
或者通过在文章中嵌入一个1像素大小的空白透明像素图像可以在我们无法控制的网站上收集访问者数据。现代浏览器和大多数网站由于潜在的安全风险而阻止插入自定义脚本。然而与脚本相比图像显得更加无害。几乎所有网站都允许加载第三方图像这使得遥测技术成为可能。
## 通过图像我们可以收集哪些信息?
令人惊讶的是,接收一个图像请求可以让我们收集比预期更多的信息。
通过分析网络请求我们可以获取用户的IP地址、访问时间、引荐来源和设备类型。这使我们能够分析流量模式如高峰阅读时间、趋势、人口分布以及不同平台上的流量粒度。这些信息对于营销和推广活动特别有价值。
![](/img/telemetry/1.png)
## 我们如何实现遥测技术?
遥测技术是一种简单的技术,本质上需要一个端点来接收互联网请求。由于其简单性,很少有专门的工具用于此目的。许多人可能不认为分析重要,或者可能被初始障碍所阻止。然而,对这种功能的需求是明确的。
开发一个遥测解决方案很简单。你只需要创建一个项目,设置一个路由,从请求体中收集信息,并返回一个空白图像。
以下是使用Node.js的示例
```jsx
router.get(
'/telemetry.gif',
async (req, res) => {
const ip = req.ip;
const referer = req.header['referer'];
const userAgent = req.headers['user-agent'];
// 存储到你的数据库中
const blankGifBuffer = Buffer.from(
'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'base64'
);
res.header('Content-Type', 'image/gif').send(blankGifBuffer);
}
);
```
如果你不想自己开发解决方案,我推荐天机。作为一个提供**网站分析**、**正常运行时间监控**和**服务器状态**的开源项目,天机最近引入了一个遥测功能,以帮助内容创作者报告遥测数据,从而更好地收集数据。最重要的是,作为开源项目,你可以控制自己的数据,并将多个平台的流量集中在一个地方,避免在不同位置查看相同信息的碎片化。
![](/img/telemetry/2.png)
GitHub: [https://github.com/msgbyte/tianji](https://github.com/msgbyte/tianji)
官方网站: [https://tianji.msgbyte.com/](https://tianji.msgbyte.com/)

View File

@ -0,0 +1,29 @@
---
sidebar_position: 2
_i18n_hash: ca2b25a29f0f1a82407be367a1d03553
---
# 参数
以下是一些关于如何使用和配置遥测图像的示例。
所有参数都是可选的,它们将提升你在不同场景中的使用体验。
| 名称 | 描述 |
| -------- | --------- |
| url | 默认情况下系统会获取浏览器自动生成的引用URL。但在某些网站上可能不允许携带此头部信息因此你需要自行提供。如果天机在任何地方都无法获取URL系统将忽略此次访问不记录此访问。 |
| name | 定义遥测事件的名称,可用于区分同一遥测记录中的不同事件。 |
| title | **[仅限徽章]**,定义徽章的标题 |
| start | **[仅限徽章]**,定义徽章的起始计数 |
| fullNum | **[仅限徽章]**,定义徽章是否显示完整数字,默认情况下会缩写数字(例如:`12345` 显示为 `12.3k` |
## 如何使用
在URL中携带参数非常简单。
例如:
```
https://tianji.example.com/telemetry/<workspaceId>/<telemetryId>/badge.svg?name=myEvent&url=https://google.com&title=My+Counter&start=100000&fullNum=true
```
如果你对此不熟悉,可以查看相关维基页面:[https://en.wikipedia.org/wiki/Query_string](https://en.wikipedia.org/wiki/Query_string)

View File

@ -0,0 +1,25 @@
---
sidebar_position: 1
_i18n_hash: 3e7ad33b9d88240c2ee01504fb17ed2d
---
# 在 Docusaurus 中使用
`docusaurus.config.js` 中:
```js
/** @type {import('@docusaurus/types').Config} */
const config = {
// ...
scripts: [
{
src: 'https://<your domain>/tracker.js',
async: true,
defer: true,
'data-website-id': '<your-website-id>',
},
],
};
module.exports = config;
```

View File

@ -0,0 +1,64 @@
---
sidebar_position: 1
_i18n_hash: bcb6522b66b64594f82548e296f77934
---
# 跟踪器脚本
## 安装
要跟踪网站事件,您只需将一个简单的脚本(< 2 KB注入到您的网站中
脚本如下所示:
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx"></script>
```
您可以从 **Tianji** 网站列表中获取此脚本代码。
## 报告事件
**Tianji** 提供了一种简单的方式来报告用户点击事件,这有助于您跟踪用户喜欢和经常使用的操作。
这是网站分析中非常常见的方法。您可以通过使用 **Tianji** 快速实现。
在将脚本代码注入到您的网站后,您只需在 DOM 属性中添加一个 `data-tianji-event`
例如:
```html
<button data-tianji-event="submit-login-form">登录</button>
```
现在,当用户点击此按钮时,您的仪表板将接收到新的事件。
## 修改默认脚本名称
> 此功能在 v1.7.4+ 版本中可用
您可以在启动时使用环境变量 `CUSTOM_TRACKER_SCRIPT_NAME`
例如:
```
CUSTOM_TRACKER_SCRIPT_NAME="my-tracker.js"
```
然后您可以通过 `"https://<your-self-hosted-domain>/my-tracker.js"` 访问您的跟踪器脚本。
这是为了帮助您避免一些广告拦截器。
您不需要 `.js` 后缀。它可以是您选择的任何路径,甚至可以使用 `CUSTOM_TRACKER_SCRIPT_NAME="this/is/very/long/path"`
## 仅跟踪指定域名
通常情况下,跟踪器会在您的网站运行的任何地方报告所有事件。但有时我们需要忽略像 `localhost` 这样的事件。
Tianji 提供了一个跟踪器脚本的属性来实现这一点。
您可以在脚本中添加 `data-domains`。该值应为您要跟踪的根域名。使用 `,` 分隔多个域名。
```html
<script async defer src="https://<your-self-hosted-domain>/tracker.js" data-website-id="xxxxxxxxxxxxx" data-domains="website.com,www.website.com"></script>
```
然后您只能看到来自这些域名的事件。

View File

@ -0,0 +1,46 @@
{
"link.title.Docs": {
"message": "文档",
"description": "The title of the footer links column with title=Docs in the footer"
},
"link.title.Community": {
"message": "社区",
"description": "The title of the footer links column with title=Community in the footer"
},
"link.title.More": {
"message": "更多",
"description": "The title of the footer links column with title=More in the footer"
},
"link.item.label.Tutorial": {
"message": "教程",
"description": "The label of footer link with label=Tutorial linking to /docs/intro"
},
"link.item.label.Stack Overflow": {
"message": "Stack Overflow",
"description": "The label of footer link with label=Stack Overflow linking to https://stackoverflow.com/questions/tagged/tianji"
},
"link.item.label.Discord": {
"message": "Discord",
"description": "The label of footer link with label=Discord linking to https://discord.gg/8Vv47wAEej"
},
"link.item.label.Twitter": {
"message": "推特",
"description": "The label of footer link with label=Twitter linking to https://twitter.com/moonrailgun"
},
"link.item.label.Changelog": {
"message": "更新日志",
"description": "The label of footer link with label=Changelog linking to /changelog"
},
"link.item.label.API": {
"message": "API",
"description": "The label of footer link with label=API linking to /api"
},
"link.item.label.GitHub": {
"message": "GitHub",
"description": "The label of footer link with label=GitHub linking to https://github.com/msgbyte/tianji"
},
"copyright": {
"message": "Copyright © 2024 Tianji, Inc. Built with Msgbyte.",
"description": "The footer copyright"
}
}

View File

@ -0,0 +1,38 @@
{
"title": {
"message": "Tianji",
"description": "The title in the navbar"
},
"logo.alt": {
"message": "Tianji Logo",
"description": "The alt text of navbar logo"
},
"item.label.Docs": {
"message": "文档",
"description": "Navbar item with label Docs"
},
"item.label.Pricing": {
"message": "定价",
"description": "Navbar item with label Pricing"
},
"item.label.Changelog": {
"message": "更新日志",
"description": "Navbar item with label Changelog"
},
"item.label.API": {
"message": "API",
"description": "Navbar item with label API"
},
"item.label.Demo": {
"message": "演示",
"description": "Navbar item with label Demo"
},
"item.label.Discord": {
"message": "Discord",
"description": "Navbar item with label Discord"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

View File

Before

Width:  |  Height:  |  Size: 472 KiB

After

Width:  |  Height:  |  Size: 472 KiB

View File

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

View File

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB