Skip to content

Commit

Permalink
新增访问日志查询功能
Browse files Browse the repository at this point in the history
1、支持指定时间段查询访问日志
2、支持指定时间段内统计点击量及独立IP数
  • Loading branch information
barats committed May 7, 2022
1 parent 80e7c3d commit 215d1e1
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.vscode
docker/container-data/*
tmp
build
build
.idea
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ docker/container-data/*
!docker/container-data/.keep
tmp
.DS_Store
build
build
.idea
38 changes: 31 additions & 7 deletions assets/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,39 @@ $(document).ready(function() {
}
});

$('#form-search-logs').form({
fields: {
url: {rules:[{
type:'empty',
prompt:'链接不能为空'
}]}
$('#logs-search-start-date').calendar({
type:'date',
text: {
months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
},
formatter: {
date: function (date, settings) {
if (!date) return '';
var day = date.getDate();
var month = date.getMonth() + 1;
var year = date.getFullYear();
return year + '-' + month + '-' + day;
}
}
});


$('#logs-search-end-date').calendar({
type:'date',
text: {
months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
},
formatter: {
date: function (date, settings) {
if (!date) return '';
var day = date.getDate();
var month = date.getMonth() + 1;
var year = date.getFullYear();
return year + '-' + month + '-' + day;
}
}
});

$('#sidebar-menu').sidebar('attach events', '#sidebar-menu-toggler');

Expand Down
55 changes: 45 additions & 10 deletions controller/admin_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func StatsPage(c *gin.Context) {
})
}

func UrlsPage(c *gin.Context) {
func SearchStatsPage(c *gin.Context) {
url := c.DefaultQuery("url", "")
strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
Expand All @@ -188,9 +188,9 @@ func UrlsPage(c *gin.Context) {
if err != nil {
size = DEFAULT_PAGE_SIZE
}
urls, err := service.GetPagesShortUrls(strings.TrimSpace(url), page, size)
c.HTML(http.StatusOK, "urls.html", gin.H{
"title": "短链接列表 - ohUrlShortener",
urls, err := service.GetPagedUrlIpCountStats(strings.TrimSpace(url), page, size)
c.HTML(http.StatusOK, "search_stats.html", gin.H{
"title": "查询统计 - ohUrlShortener",
"current_url": c.Request.URL.Path,
"error": err,
"shortUrls": urls,
Expand All @@ -203,7 +203,7 @@ func UrlsPage(c *gin.Context) {
})
}

func AccessLogsPage(c *gin.Context) {
func UrlsPage(c *gin.Context) {
url := c.DefaultQuery("url", "")
strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
Expand All @@ -215,21 +215,56 @@ func AccessLogsPage(c *gin.Context) {
if err != nil {
size = DEFAULT_PAGE_SIZE
}
logs, err := service.GetPagedAccessLogs(strings.TrimSpace(url), page, size)
c.HTML(http.StatusOK, "access_logs.html", gin.H{
"title": "访问日志查询 - ohUrlShortener",
urls, err := service.GetPagesShortUrls(strings.TrimSpace(url), page, size)
c.HTML(http.StatusOK, "urls.html", gin.H{
"title": "短链接列表 - ohUrlShortener",
"current_url": c.Request.URL.Path,
"error": err,
"logs": logs,
"shortUrls": urls,
"page": page,
"size": size,
"prefix": utils.AppConfig.UrlPrefix,
"first_page": page == 1,
"last_page": len(logs) < size,
"last_page": len(urls) < size,
"url": strings.TrimSpace(url),
})
}

func AccessLogsPage(c *gin.Context) {
url := c.DefaultQuery("url", "")
strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
start := c.DefaultQuery("start", "")
end := c.DefaultQuery("end", "")
page, err := strconv.Atoi(strPage)
if err != nil {
page = DEFAULT_PAGE_NUM
}
size, err := strconv.Atoi(strSize)
if err != nil {
size = DEFAULT_PAGE_SIZE
}

totalCount, distinctIpCount, err := service.GetAccessLogsCount(strings.TrimSpace(url), start, end)
logs, err := service.GetPagedAccessLogs(strings.TrimSpace(url), start, end, page, size)
c.HTML(http.StatusOK, "access_logs.html", gin.H{
"title": "访问日志查询 - ohUrlShortener",
"current_url": c.Request.URL.Path,
"error": err,
"logs": logs,
"page": page,
"size": size,
"prefix": utils.AppConfig.UrlPrefix,
"first_page": page == 1,
"last_page": len(logs) < size,
"url": strings.TrimSpace(url),
"total_count": totalCount,
"unique_ip_count": distinctIpCount,
"start_date": start,
"end_date": end,
})
}

func AccessLogsExport(c *gin.Context) {
url := c.PostForm("url")
logs, err := service.GetAllAccessLogs(strings.TrimSpace(url))
Expand Down
49 changes: 49 additions & 0 deletions docker/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: '3'
services:

postgres:
image: postgres:${PG_VERSION}
container_name: ${PG_CONTAINER_NAME}
hostname: postgres
env_file:
- ../docker/vars.env
environment:
- POSTGRES_USER=${PG_SUPER_USER}
- POSTGRES_PASSWORD=${PG_SUPER_PWD}
- TZ=PRC
- PGTZ=PRC
volumes:
- ../structure.sql:/docker-entrypoint-initdb.d/001.sql
- ../docker/container-data/postgresql:/var/lib/postgresql/data
ports:
- ${PG_LOCAL_PORT}:5432
healthcheck:
test: [ "CMD", "psql", "-U","${PG_SUPER_USER}","-d","oh_url_shortener" ]
timeout: 10s
interval: 3s
retries: 10
networks:
- ohurlshortener

redis:
image: redis:${RD_VERSION}
container_name: ${RD_CONTAINER_NAME}
hostname: redis
env_file:
- ../docker/vars.env
ports:
- ${RD_LOCAL_PORT}:6379
healthcheck:
test: [ "CMD", "redis-cli","-p","6379"]
timeout: 10s
interval: 3s
retries: 10
networks:
- ohurlshortener

networks:
ohurlshortener:
driver: bridge
name: "network_ohurlshortener"
driver_opts:
com.docker.network.enable_ipv6: "true"
4 changes: 2 additions & 2 deletions docker/vars.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

# ohUrlShortenerAdmin
OH_ADMIN_PORT=9092
OH_ADMIN_VERSION=1.3
OH_ADMIN_VERSION=1.4
OH_ADMIN_CONTAINER_NAME=ohurlshortener_admin

# ohUrlShortenerPortal
OH_PORTAL_PORT=9091
OH_PORTAL_VERSION=1.3
OH_PORTAL_VERSION=1.4
OH_PORTAL_CONTAINER_NAME=ohurlshortener_portal

# Postgresql Vars
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func initializeRoute02() (http.Handler, error) {
admin.GET("/dashboard", controller.DashbaordPage)
admin.GET("/urls", controller.UrlsPage)
admin.GET("/stats", controller.StatsPage)
admin.GET("/search_stats", controller.SearchStatsPage)
admin.GET("/access_logs", controller.AccessLogsPage)
admin.POST("/urls/generate", controller.GenerateShortUrl)
admin.POST("/urls/state", controller.ChangeState)
Expand Down
8 changes: 6 additions & 2 deletions service/access_logs_s.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,22 @@ func StoreAccessLogs() error {
return nil
}

func GetPagedAccessLogs(url string, page int, size int) ([]core.AccessLog, error) {
func GetPagedAccessLogs(url string, start, end string, page, size int) ([]core.AccessLog, error) {
if page < 1 || size < 1 {
return nil, nil
}
allAccessLogs, err := storage.FindAllAccessLogs(url, page, size)
allAccessLogs, err := storage.FindAllAccessLogs(url, start, end, page, size)
if err != nil {
log.Println(err)
return allAccessLogs, utils.RaiseError("内部错误,请联系管理员")
}
return allAccessLogs, nil
}

func GetAccessLogsCount(url string, start, end string) (int, int, error) {
return storage.FindAccessLogsCount(url, start, end)
}

func GetAllAccessLogs(url string) ([]core.AccessLog, error) {
allAccessLogs, err := storage.FindAllAccessLogsByUrl(url)
if err != nil {
Expand Down
44 changes: 32 additions & 12 deletions storage/access_logs_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package storage

import (
"fmt"
"ohurlshortener/core"
"ohurlshortener/utils"
)
Expand Down Expand Up @@ -37,26 +38,45 @@ func InsertAccessLogs(logs []core.AccessLog) error {
return DbNamedExec(query, logs)
}

func FindAccessLogsCount(url string) (int, error) {
var rowCount int
query := "SELECT count(l.id) FROM public.access_logs l"
// FindAccessLogsCount
//
// Find Access Logs Count and Unique IP Count
//
// First return value is total_count, Second return value is unique_ip_count ip count
func FindAccessLogsCount(url string, start, end string) (int, int, error) {
type LogsCount struct {
TotalCount int `db:"total_count"`
UniqueIpCount int `db:"unique_ip_count"`
}
query := `SELECT count(l.id) as total_count, count(distinct(l.ip)) as unique_ip_count FROM public.access_logs l WHERE 1=1 `
if !utils.EemptyString(url) {
query = "SELECT count(l.id) FROM public.access_logs l WHERE l.short_url = $1"
err := DbGet(query, &rowCount, url)
return rowCount, err
query += fmt.Sprintf(` AND l.short_url = '%s'`, url)
}
if !utils.EemptyString(start) {
query += fmt.Sprintf(` AND l.access_time >= to_date('%s','YYYY-MM-DD')`, start)
}
return rowCount, DbGet(query, &rowCount)
if !utils.EemptyString(end) {
query += fmt.Sprintf(` AND l.access_time < to_date('%s','YYYY-MM-DD')`, end)
}
var count LogsCount
return count.TotalCount, count.UniqueIpCount, DbGet(query, &count)
}

func FindAllAccessLogs(url string, page int, size int) ([]core.AccessLog, error) {
func FindAllAccessLogs(url string, start, end string, page, size int) ([]core.AccessLog, error) {
found := []core.AccessLog{}
offset := (page - 1) * size
query := "SELECT * FROM public.access_logs l ORDER BY l.id DESC LIMIT $1 OFFSET $2"
query := `SELECT * FROM public.access_logs l WHERE 1=1 `
if !utils.EemptyString(url) {
query := "SELECT * FROM public.access_logs l WHERE l.short_url = $1 ORDER BY l.id DESC LIMIT $2 OFFSET $3"
err := DbSelect(query, &found, url, size, offset)
return found, err
query += fmt.Sprintf(` AND l.short_url = '%s'`, url)
}
if !utils.EemptyString(start) {
query += fmt.Sprintf(` AND l.access_time >= to_date('%s','YYYY-MM-DD')`, start)
}
if !utils.EemptyString(end) {
query += fmt.Sprintf(` AND l.access_time < to_date('%s','YYYY-MM-DD')`, end)
}

query += ` ORDER BY l.id DESC LIMIT $1 OFFSET $2`
return found, DbSelect(query, &found, size, offset)
}

Expand Down
43 changes: 43 additions & 0 deletions storage/access_logs_storage_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package storage

import (
"testing"
)

func TestFindAccessLogsCount(t *testing.T) {
init4Test(t)

type args struct {
url string
start string
end string
}
tests := []struct {
name string
args args
want int
want1 int
wantErr bool
}{
{name: "TestCase 1", args: args{url: "", start: "", end: ""}, want: 18, want1: 7, wantErr: false},
{name: "TestCase 2", args: args{url: "gkT39tb5", start: "", end: ""}, want: 6, want1: 4, wantErr: false},
{name: "TestCase 3", args: args{url: "gkT39tb5", start: "2022-04-20", end: ""}, want: 2, want1: 1, wantErr: false},
{name: "TestCase 3", args: args{url: "gkT39tb5", start: "2022-04-07", end: "2022-04-11"}, want: 3, want1: 3, wantErr: false},
{name: "TestCase 1", args: args{url: "", start: "2022-04-01", end: ""}, want: 18, want1: 7, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1, err := FindAccessLogsCount(tt.args.url, tt.args.start, tt.args.end)
if (err != nil) != tt.wantErr {
t.Errorf("FindAccessLogsCount() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("FindAccessLogsCount() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("FindAccessLogsCount() got1 = %v, want %v", got1, tt.want1)
}
})
}
}
Loading

0 comments on commit 215d1e1

Please sign in to comment.