分享 34 4

    Tianji - 一个集成 网站分析 + 上线监控 + 服务器状态 的应用

    AI摘要:DeepSeek AI摘要 DeepSeek
    Tianji 是一个集成了网站分析、上线监控和服务器状态的多功能应用,结合了 uptime-kuma 、 nezha 和 umami 的功能。项目通过 Docker Compose 部署,支持 PostgreSQL 数据库,并提供默认的管理员账户。用户可以通过 API 获取网站统计数据,并使用 Cloudflare Workers 保护访问令牌。Tianji 还支持通过 HTML 和 JavaScript 调用统计数据,展示访客和页面浏览量。

    简介

    一个All-in-one的项目,集成了uptime-kuma+ nezha + umami 的功能的超强应用.

    项目地址

    https://github.com/msgbyte/tianji

    预览

    请输入图片描述

    部署

    使用 docker compose 的方式来部署

    mkdir /home/tianji
    cd /home/tianji
    vi docker-compose.yaml

    docker-compose.yaml的内容如下

    services:
      tianji:
        image: moonrailgun/tianji
        ports:
          - "12345:12345"
        environment:
          DATABASE_URL: postgresql://tianji:tianji@postgres:5432/tianji
          JWT_SECRET: replace-me-with-a-random-string
          ALLOW_REGISTER: "false"
          ALLOW_OPENAPI: "true"
        depends_on:
          - postgres
        restart: always
      postgres:
        image: postgres:15.4-alpine
        environment:
          POSTGRES_DB: tianji
          POSTGRES_USER: tianji
          POSTGRES_PASSWORD: tianji
        volumes:
          - ./tianji-db-data:/var/lib/postgresql/data
        restart: always
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
          interval: 5s
          timeout: 5s
          retries: 5

    运行容器

    docker compose up -d

    默认密码

    Url: http://<your-ip>:12345
    Default username: admin
    Default password: admin

    监控

    https://0tz.top/status/imsun
    可以使用一个小徽章显示状态
    博客

    遥测

    在页面插入一张图片就可以侦测到访问量,但是只能显示 pv 浏览量

    统计

    多用户

    没错,Tianji是支持多用户使用的,若是有想体验的朋友可以留言,我可以发送邀请.

    通知

    可以支持多种通知方式

    访客统计

    从木木老师那里得到灵感,使用API获取网站的统计数据并使用js 调用,替代Umami.

    在后台获取token websiteID workspaceID

    然后使用Cloudflare Workers来保护token.
    新建一个workers,填入以下代码(需要修改的部分已经标注出来)

    addEventListener('fetch', event => {
      event.respondWith(handleRequest(event.request))
    })
    
    const tianji = 'https://tianji.top'; #自行修改
    const token = 'sk_cf38cfb0bcb22d****'; #自行修改
    const workspaceID = 'clnzoxcy10001vy2ohi4obbi0'; #自行修改
    const websiteID = 'cm3sj40cs00018n2ezrgbdl5w'; #自行修改
    
    async function handleRequest(request) {
      const url = `${tianji}/open/workspace/${workspaceID}/website/${websiteID}/stats`;
    
      // 获取当前时间的 Unix 时间戳(以毫秒为单位)
      const now = Date.now();
    
      // 设置查询参数
      const params = new URLSearchParams({
        startAt: '1704067200000', // 2024年1月1日的 Unix 时间戳(毫秒)
        endAt: now.toString()  
      });
    
      const fullUrl = `${url}?${params.toString()}`;
    
      const headers = new Headers({
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      });
    
      const response = await fetch(fullUrl, {
        method: 'GET',
        headers: headers
      });
    
      const corsHeaders = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization'
      };
    
      if (request.method === 'OPTIONS') {
        return new Response(null, {
          headers: corsHeaders
        });
      }
    
      if (response.ok) {
        const data = await response.json();
        return new Response(JSON.stringify(data), {
          headers: {
            'Content-Type': 'application/json',
            ...corsHeaders
          }
        });
      } else {
        return new Response(`Failed to fetch data: ${response.status} ${response.statusText}`, {
          status: response.status,
          headers: corsHeaders
        });
      }
    }

    startAt 的值 是某时间的unix时间戳 可以自行设置查询范围

    调用

    使用html+js调用

    👣<p>本站到访<span id="uniques">0</span>位朋友.</p><p>共浏览页面<span id="pageviews">0</span>次</p>
    <script>
    // 定义 API URL
    const apiUrl = 'https://tj.imsun.org';
    
    fetch(apiUrl)
        .then(response => {
            if (!response.ok) {
                throw new Error('error');
            }
            return response.json();
        })
        .then(data => {
            const pageviewsElement = document.getElementById('pageviews');
            const uniquesElement = document.getElementById('uniques');
            pageviewsElement.textContent = data.pageviews.value;
            uniquesElement.textContent = data.uniques.value;
        })
        .catch(error => {
            console.error('获取数据时出现问题:', error);
        });
    </script>

    其他

    还有其他很多功能,等待摸索

    1. 沉沦

      2024-12-27 20:24
      香港 Yau Tsim Mong 旺角

      好东西,下来研究一下怎么用。

        1. 老孙

          2024-12-27 23:10
          美国 加州 洛杉矶
          @沉沦

          这个倒是很简单的

    2. ACEVS

      2024-12-27 19:55
      香港 鸡鱼环

      看上去不错哈~mark~

        1. 老孙

          2024-12-27 19:59
          新加坡 淡馬錫
          @ACEVS

          一个顶三个还是不错的