mirror of
https://github.com/Kugelschieber/marvinblum.git
synced 2026-01-18 14:50:27 +00:00
Added dates to tracking page and improved charts.
This commit is contained in:
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/cenkalti/backoff/v4 v4.0.2 // indirect
|
github.com/cenkalti/backoff/v4 v4.0.2 // indirect
|
||||||
github.com/emvi/api-go v0.0.0-20191210194347-0a945446f6a8
|
github.com/emvi/api-go v0.0.0-20191210194347-0a945446f6a8
|
||||||
github.com/emvi/logbuch v1.1.1
|
github.com/emvi/logbuch v1.1.1
|
||||||
github.com/emvi/pirsch v0.0.0-20200625233854-9bc410bf1483
|
github.com/emvi/pirsch v1.0.0
|
||||||
github.com/gorilla/mux v1.7.4
|
github.com/gorilla/mux v1.7.4
|
||||||
github.com/gosimple/slug v1.9.0
|
github.com/gosimple/slug v1.9.0
|
||||||
github.com/jmoiron/sqlx v1.2.0
|
github.com/jmoiron/sqlx v1.2.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -99,6 +99,8 @@ github.com/emvi/pirsch v0.0.0-20200625182355-75f0aba03718 h1:FOaeJg2A9rGb5WMZsnW
|
|||||||
github.com/emvi/pirsch v0.0.0-20200625182355-75f0aba03718/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g=
|
github.com/emvi/pirsch v0.0.0-20200625182355-75f0aba03718/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g=
|
||||||
github.com/emvi/pirsch v0.0.0-20200625233854-9bc410bf1483 h1:hTW+M/0XaAEn1+bpXL/z2DZAFU1xgvKk56OgL1lodSU=
|
github.com/emvi/pirsch v0.0.0-20200625233854-9bc410bf1483 h1:hTW+M/0XaAEn1+bpXL/z2DZAFU1xgvKk56OgL1lodSU=
|
||||||
github.com/emvi/pirsch v0.0.0-20200625233854-9bc410bf1483/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g=
|
github.com/emvi/pirsch v0.0.0-20200625233854-9bc410bf1483/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g=
|
||||||
|
github.com/emvi/pirsch v1.0.0 h1:PAxXw98iZcN3CKamp0ShzKJYPRGagmTPaBGYHe9FHhk=
|
||||||
|
github.com/emvi/pirsch v1.0.0/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
|
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
|
||||||
|
|||||||
26
main.go
26
main.go
@@ -128,11 +128,27 @@ func serveTracking() http.HandlerFunc {
|
|||||||
start = 7
|
start = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
totalVisitorsLabels, totalVisitorsDps := tracking.GetTotalVisitors(start)
|
var startDate, endDate time.Time
|
||||||
hourlyVisitorsLabels, hourlyVisitorsDps := tracking.GetHourlyVisitors(start)
|
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
logbuch.Warn("Error parsing tracking form", logbuch.Fields{"err": err})
|
||||||
|
} else {
|
||||||
|
startDate, _ = time.Parse("2006-01-02", r.FormValue("start-date"))
|
||||||
|
endDate, _ = time.Parse("2006-01-02", r.FormValue("end-date"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if startDate.IsZero() || endDate.IsZero() {
|
||||||
|
startDate = time.Now().UTC().Add(-time.Hour * 24 * time.Duration(start))
|
||||||
|
endDate = time.Now().UTC()
|
||||||
|
}
|
||||||
|
|
||||||
|
totalVisitorsLabels, totalVisitorsDps := tracking.GetTotalVisitors(startDate, endDate)
|
||||||
|
hourlyVisitorsLabels, hourlyVisitorsDps := tracking.GetHourlyVisitors(startDate, endDate)
|
||||||
hourlyVisitorsTodayLabels, hourlyVisitorsTodayDps := tracking.GetHourlyVisitorsToday()
|
hourlyVisitorsTodayLabels, hourlyVisitorsTodayDps := tracking.GetHourlyVisitorsToday()
|
||||||
tplCache.RenderWithoutCache(w, "tracking.html", struct {
|
tplCache.RenderWithoutCache(w, "tracking.html", struct {
|
||||||
Start int
|
Start int
|
||||||
|
StartDate time.Time
|
||||||
|
EndDate time.Time
|
||||||
TotalVisitorsLabels template.JS
|
TotalVisitorsLabels template.JS
|
||||||
TotalVisitorsDps template.JS
|
TotalVisitorsDps template.JS
|
||||||
PageVisits []tracking.PageVisits
|
PageVisits []tracking.PageVisits
|
||||||
@@ -144,10 +160,12 @@ func serveTracking() http.HandlerFunc {
|
|||||||
ActiveVisitors int
|
ActiveVisitors int
|
||||||
}{
|
}{
|
||||||
start,
|
start,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
totalVisitorsLabels,
|
totalVisitorsLabels,
|
||||||
totalVisitorsDps,
|
totalVisitorsDps,
|
||||||
tracking.GetPageVisits(start),
|
tracking.GetPageVisits(startDate, endDate),
|
||||||
tracking.GetLanguages(start),
|
tracking.GetLanguages(startDate, endDate),
|
||||||
hourlyVisitorsLabels,
|
hourlyVisitorsLabels,
|
||||||
hourlyVisitorsDps,
|
hourlyVisitorsDps,
|
||||||
hourlyVisitorsTodayLabels,
|
hourlyVisitorsTodayLabels,
|
||||||
|
|||||||
@@ -52,6 +52,19 @@ body {
|
|||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tracking-form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-form input {
|
||||||
|
margin: 3px 6px 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
margin: 80px 0;
|
margin: 80px 0;
|
||||||
}
|
}
|
||||||
@@ -81,4 +94,8 @@ p {
|
|||||||
.menu {
|
.menu {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tracking-form {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<section>
|
<section>
|
||||||
<h1>Tracking</h1>
|
<h1>Tracking</h1>
|
||||||
<p>
|
<p>
|
||||||
This page shows tracking statistics for my website using <a href="https://github.com/emvi/pirsch" target="_blank">Pirsch</a> and <a href="https://www.chartjs.org/" target="_blank">Chart.Js</a>. The data shows unique visitors.
|
This page shows tracking statistics for my website using <a href="https://github.com/emvi/pirsch" target="_blank">Pirsch</a> and <a href="https://www.chartjs.org/" target="_blank">Chart.Js</a>. The data shows unique visitors. All times and dates are UTC.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="/tracking?start=7" class="button {{if eq .Start 7}}filled{{end}}">Week</a>
|
<a href="/tracking?start=7" class="button {{if eq .Start 7}}filled{{end}}">Week</a>
|
||||||
@@ -13,11 +13,19 @@
|
|||||||
<a href="/tracking?start=182" class="button {{if eq .Start 182}}filled{{end}}">Half Year</a>
|
<a href="/tracking?start=182" class="button {{if eq .Start 182}}filled{{end}}">Half Year</a>
|
||||||
<a href="/tracking?start=365" class="button {{if eq .Start 365}}filled{{end}}">Year</a>
|
<a href="/tracking?start=365" class="button {{if eq .Start 365}}filled{{end}}">Year</a>
|
||||||
</p>
|
</p>
|
||||||
|
<form class="tracking-form">
|
||||||
|
<input type="date" name="start-date" value="{{format .StartDate "2006-01-02"}}" />
|
||||||
|
<input type="date" name="end-date" value="{{format .EndDate "2006-01-02"}}" />
|
||||||
|
<input type="submit" value="Update" />
|
||||||
|
</form>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Active Visitors</h2>
|
<h2>Active Visitors</h2>
|
||||||
<p>
|
<p>
|
||||||
Active within the last five minutes: {{.ActiveVisitors}}
|
Active visitors within the last five minutes: {{.ActiveVisitors}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The next diagram shows active visitors for each hour of today.
|
||||||
</p>
|
</p>
|
||||||
<canvas id="hourlyVisitorsToday" class="tracking"></canvas>
|
<canvas id="hourlyVisitorsToday" class="tracking"></canvas>
|
||||||
</section>
|
</section>
|
||||||
@@ -27,10 +35,37 @@
|
|||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Visitors Per Hour</h2>
|
<h2>Visitors Per Hour</h2>
|
||||||
|
<p>
|
||||||
|
This is the cumulated visitor count per hour on each day of the selected time frame.
|
||||||
|
</p>
|
||||||
<canvas id="hourlyVisitors" class="tracking"></canvas>
|
<canvas id="hourlyVisitors" class="tracking"></canvas>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Pages Visits</h2>
|
<h2>Languages</h2>
|
||||||
|
<p>
|
||||||
|
Here are the top 10 languages used by my visitors.
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Language</th>
|
||||||
|
<th>Absolute</th>
|
||||||
|
<th>Relative</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range $data := .Languages}}
|
||||||
|
<tr>
|
||||||
|
<td>{{if $data.Language}}{{$data.Language}}{{else}}(not set){{end}}</td>
|
||||||
|
<td>{{$data.Visitors}}</td>
|
||||||
|
<td>{{round (multiply $data.RelativeVisitors 100)}} %</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Page Visits</h2>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{{range $i, $data := .PageVisits}}
|
{{range $i, $data := .PageVisits}}
|
||||||
@@ -40,39 +75,14 @@
|
|||||||
</section>
|
</section>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>Languages</h2>
|
|
||||||
<p>
|
|
||||||
Here are the top 10 languages used by my visitors.
|
|
||||||
</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Language</th>
|
|
||||||
<th>Absolute</th>
|
|
||||||
<th>Relative</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{range $data := .Languages}}
|
|
||||||
<tr>
|
|
||||||
<td>{{if $data.Language}}{{$data.Language}}{{else}}(not set){{end}}</td>
|
|
||||||
<td>{{$data.Visitors}}</td>
|
|
||||||
<td>{{round (multiply $data.RelativeVisitors 100)}} %</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/Chart-v2.9.3.bundle.min.js"></script>
|
<script type="text/javascript" src="/static/js/Chart-v2.9.3.bundle.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
new Chart(document.getElementById('hourlyVisitorsToday').getContext('2d'), {
|
new Chart(document.getElementById('hourlyVisitorsToday').getContext('2d'), {
|
||||||
type: "line",
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: [{{.HourlyVisitorsTodayLabels}}],
|
labels: [{{.HourlyVisitorsTodayLabels}}],
|
||||||
datasets: [{
|
datasets: [{
|
||||||
backgroundColor: "rgba(127, 127, 127, 0.05)",
|
backgroundColor: "#7f7f7f",
|
||||||
borderColor: "#7f7f7f",
|
borderColor: "#7f7f7f",
|
||||||
label: "Hourly Visitors for Today",
|
label: "Hourly Visitors for Today",
|
||||||
data: [{{.HourlyVisitorsTodayDps}}]
|
data: [{{.HourlyVisitorsTodayDps}}]
|
||||||
@@ -94,11 +104,11 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
new Chart(document.getElementById('hourlyVisitors').getContext('2d'), {
|
new Chart(document.getElementById('hourlyVisitors').getContext('2d'), {
|
||||||
type: "line",
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: [{{.HourlyVisitorsLabels}}],
|
labels: [{{.HourlyVisitorsLabels}}],
|
||||||
datasets: [{
|
datasets: [{
|
||||||
backgroundColor: "rgba(127, 127, 127, 0.05)",
|
backgroundColor: "#7f7f7f",
|
||||||
borderColor: "#7f7f7f",
|
borderColor: "#7f7f7f",
|
||||||
label: "Hourly Visitors",
|
label: "Hourly Visitors",
|
||||||
data: [{{.HourlyVisitorsDps}}]
|
data: [{{.HourlyVisitorsDps}}]
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ type PageVisits struct {
|
|||||||
Data template.JS
|
Data template.JS
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTotalVisitors(start int) (template.JS, template.JS) {
|
func GetTotalVisitors(startDate, endDate time.Time) (template.JS, template.JS) {
|
||||||
visitors, err := analyzer.Visitors(&pirsch.Filter{From: getStartTime(start), To: today()})
|
visitors, err := analyzer.Visitors(&pirsch.Filter{From: startDate, To: endDate})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logbuch.Error("Error reading visitor statistics", logbuch.Fields{"err": err})
|
logbuch.Error("Error reading visitor statistics", logbuch.Fields{"err": err})
|
||||||
@@ -30,8 +30,8 @@ func GetTotalVisitors(start int) (template.JS, template.JS) {
|
|||||||
return getLabelsAndData(visitors)
|
return getLabelsAndData(visitors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPageVisits(start int) []PageVisits {
|
func GetPageVisits(startDate, endDate time.Time) []PageVisits {
|
||||||
visits, err := analyzer.PageVisits(&pirsch.Filter{From: getStartTime(start), To: today()})
|
visits, err := analyzer.PageVisits(&pirsch.Filter{From: startDate, To: endDate})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logbuch.Error("Error reading page statistics", logbuch.Fields{"err": err})
|
logbuch.Error("Error reading page statistics", logbuch.Fields{"err": err})
|
||||||
@@ -48,8 +48,8 @@ func GetPageVisits(start int) []PageVisits {
|
|||||||
return pageVisits
|
return pageVisits
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLanguages(start int) []pirsch.VisitorLanguage {
|
func GetLanguages(startDate, endDate time.Time) []pirsch.VisitorLanguage {
|
||||||
languages, _, err := analyzer.Languages(&pirsch.Filter{From: getStartTime(start), To: today()})
|
languages, _, err := analyzer.Languages(&pirsch.Filter{From: startDate, To: endDate})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logbuch.Error("Error reading language statistics", logbuch.Fields{"err": err})
|
logbuch.Error("Error reading language statistics", logbuch.Fields{"err": err})
|
||||||
@@ -63,8 +63,8 @@ func GetLanguages(start int) []pirsch.VisitorLanguage {
|
|||||||
return languages
|
return languages
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHourlyVisitors(start int) (template.JS, template.JS) {
|
func GetHourlyVisitors(startDate, endDate time.Time) (template.JS, template.JS) {
|
||||||
visitors, err := analyzer.HourlyVisitors(&pirsch.Filter{From: getStartTime(start), To: today()})
|
visitors, err := analyzer.HourlyVisitors(&pirsch.Filter{From: startDate, To: endDate})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logbuch.Error("Error reading hourly visitors", logbuch.Fields{"err": err})
|
logbuch.Error("Error reading hourly visitors", logbuch.Fields{"err": err})
|
||||||
|
|||||||
Reference in New Issue
Block a user