Skip to content

Commit

Permalink
Added the ability to set the date specificity in hours or mins.
Browse files Browse the repository at this point in the history
This is used in the visitors panel, so now it is possible to track
visitors at the hour or minute level. For instance, an hour
specificity would yield to display traffic as 18/Dec/2010:19, while
minute specificity yields to 18/Dec/2010:19:30
  • Loading branch information
allinurl committed Jun 4, 2016
1 parent f2dd2c0 commit a13c1fa
Show file tree
Hide file tree
Showing 14 changed files with 293 additions and 142 deletions.
6 changes: 6 additions & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,12 @@ rect.legend {
.chart-tooltip td.value {
text-align: right;
}
.chart-tooltip .blue {
background-color: #007BC3;
}
.chart-tooltip .red {
background-color: #FF303E;
}

/* DARK THEME */
.dark h1 {
Expand Down
14 changes: 10 additions & 4 deletions resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,16 @@ GoAccess.Util = {
},

// Format date from 20120124 to 24/Jan/2012
formatDate: function (value) {
var d = parseInt(value);
d = new Date(d / 1E4, (d % 1E4 / 100) - 1, d % 100);
return ('0' + d.getDate()).slice(-2) + '/' + this.months[d.getMonth()] + '/' + d.getFullYear();
formatDate: function (str) {
var y = str.substr(0,4), m = str.substr(4,2) - 1, d = str.substr(6,2),
h = str.substr(8,2) || 0, i = str.substr(10, 2) || 0, s = str.substr(12, 2) || 0;
var date = new Date(y,m,d,h,i,s);

var out = ('0' + date.getDate()).slice(-2) + '/' + this.months[date.getMonth()] + '/' + date.getFullYear();
10 <= str.length && (out += ":" + h);
12 <= str.length && (out += ":" + i);
14 <= str.length && (out += ":" + s);
return out;
},

// Format field value to human readable
Expand Down
4 changes: 2 additions & 2 deletions resources/tpls.html
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ <h3>File Options</h3>
<th colspan="2">{{data.0}}</th>
</tr>
<tr>
<td class="name"><span style="background-color:#447FB3"></span>hits</td>
<td class="name"><span class="blue"></span>hits</td>
<td class="value">{{data.1}}</td>
</tr>
{{#data.2}}
<tr>
<td class="name"><span style="background-color:#FF6854"></span>visitors</td>
<td class="name"><span class="red"></span>visitors</td>
<td class="value">{{data.2}}</td>
</tr>
{{/data.2}}
Expand Down
19 changes: 11 additions & 8 deletions src/commons.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,19 @@ struct tm *now_tm;

/* maximum number of items within a panel */
#define MAX_CHOICES 366
/* real-time */
#define MAX_CHOICES_RT 50

/* date and time length */
#define DATE_TIME 20
/* date length */
#define DATE_LEN 12
/* hour length */
#define HOUR_LEN 3
/* hour + ':' + min length */
#define HRMI_LEN 4 + 2
/* date and time length - e.g., 2016/12/12 12:12:12*/
#define DATE_TIME 19 + 1
/* date length - e.g., 2016/12/12 */
#define DATE_LEN 10 + 1
/* hour + ':' + min length - e.g., 12:12 */
#define HRMI_LEN 4 + 1 + 1

#define YR_FMT "%Y"
#define MO_FMT "%M"
#define DT_FMT "%d"

/* maximum protocol string length */
#define REQ_PROTO_LEN 9
Expand Down
36 changes: 19 additions & 17 deletions src/gdashboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,16 +448,15 @@ render_data_hosts (WINDOW * win, GDashRender render, char *value, int x)

/* Set panel's date on the given buffer
*
* On error, '---' placeholder is set into the buffer.
* On success, data is set on the given buffer. */
static void
set_visitors_date (char *buf, const char *value)
* On error, '---' placeholder is returned.
* On success, the formatted date is returned. */
static char *
set_visitors_date (const char *value)
{
/* verify we have a valid date conversion */
if (convert_date (buf, (char *) value, "%Y%m%d", "%d/%b/%Y", DATE_LEN) != 0) {
LOG_DEBUG (("invalid date: %s", value));
xstrncpy (buf, "---", 4);
}
const char *sdfmt = conf.spec_date_format;
const char *sndfmt = conf.spec_num_date_format;

return get_visitors_date (value, sndfmt, sdfmt);
}

/* Render the data metric for each panel */
Expand All @@ -467,28 +466,31 @@ render_data (GDashModule * data, GDashRender render, int *x)
GColors *color = get_color_by_item_module (COLOR_MTRC_DATA, data->module);
WINDOW *win = render.win;

char buf[DATE_LEN];
char *value;
char *date = NULL, *value = NULL, *buf = NULL;
int y = render.y, w = render.w, idx = render.idx, sel = render.sel;
int date_len = 0;

value = substring (data->data[idx].metrics->data, 0, w - *x);
if (data->module == VISITORS)
set_visitors_date (buf, value);
if (data->module == VISITORS) {
date = set_visitors_date (value);
date_len = strlen (date);
}

if (sel && data->module == HOSTS && data->data[idx].is_subitem) {
render_data_hosts (win, render, value, *x);
} else if (sel) {
draw_header (win, data->module == VISITORS ? buf : value, "%s", y, *x, w,
color_selected);
buf = data->module == VISITORS ? date : value;
draw_header (win, buf, "%s", y, *x, w, color_selected);
} else {
wattron (win, color->attr | COLOR_PAIR (color->pair->idx));
mvwprintw (win, y, *x, "%s", data->module == VISITORS ? buf : value);
mvwprintw (win, y, *x, "%s", data->module == VISITORS ? date : value);
wattroff (win, color->attr | COLOR_PAIR (color->pair->idx));
}

*x += data->module == VISITORS ? DATE_LEN - 1 : data->data_len;
*x += data->module == VISITORS ? date_len : data->data_len;
*x += DASH_SPACE;
free (value);
free (date);
}

/* Render the method metric for each panel
Expand Down
8 changes: 5 additions & 3 deletions src/gholder.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,16 @@ static void
data_visitors (GHolder * h)
{
char *date = NULL, *datum = NULL;
const char *sdfmt = conf.spec_date_format;
const char *sndfmt = conf.spec_num_date_format;

/* date is already in the 'Ymd' format, no need for additional conversion */
if (has_timestamp (conf.date_format))
return;
/*if (has_timestamp (conf.date_format)) */
/*return; */

/* verify we have a valid date conversion */
datum = h->items[h->idx].metrics->data;
date = get_visitors_date (datum, conf.date_format, "%Y%m%d");
date = get_visitors_date (datum, sdfmt, sndfmt);
free (datum);

h->items[h->idx].metrics->data = date;
Expand Down
5 changes: 3 additions & 2 deletions src/goaccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,9 +951,10 @@ init_processing (void)
verify_panels ();
/* initialize storage */
init_storage ();
if (conf.load_from_disk) {
if (conf.load_from_disk)
set_general_stats ();
}
/* date specificity format */
set_spec_date_format ();
}

/* Set up and open GeoIP database */
Expand Down
134 changes: 67 additions & 67 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ struct option long_opts[] = {
{"no-term-resolver" , no_argument , 0 , 'r' } ,
{"output-format" , required_argument , 0 , 'o' } ,
{"real-os" , no_argument , 0 , 0 } ,
{"time-dist-spec" , required_argument , 0 , 0 } ,
{"date-spec" , required_argument , 0 , 0 } ,
{"hour-spec" , required_argument , 0 , 0 } ,
{"real-time-html" , no_argument , 0 , 0 } ,
{"addr" , required_argument , 0 , 0 } ,
{"ws-url" , required_argument , 0 , 0 } ,
Expand All @@ -105,12 +106,12 @@ struct option long_opts[] = {
{"time-format" , required_argument , 0 , 0 } ,
{"with-mouse" , no_argument , 0 , 'm' } ,
{"with-output-resolver" , no_argument , 0 , 'd' } ,
#ifdef HAVE_LIBGEOIP
#ifdef HAVE_LIBGEOIP
{"std-geoip" , no_argument , 0 , 'g' } ,
{"geoip-database" , required_argument , 0 , 0 } ,
{"geoip-city-data" , required_argument , 0 , 0 } ,
#endif
#ifdef TCB_BTREE
#endif
#ifdef TCB_BTREE
{"cache-lcnum" , required_argument , 0 , 0 } ,
{"cache-ncnum" , required_argument , 0 , 0 } ,
{"compression" , required_argument , 0 , 0 } ,
Expand All @@ -137,120 +138,112 @@ cmd_help (void)

/* Log & Date Format Options */
"Log & Date Format Options\n\n"
" --log-format=<logformat> - Specify log format. Inner quotes need to\n"
" be escaped, or use single quotes.\n"
" --date-format=<dateformat> - Specify log date format. e.g.,\n"
" %%d/%%b/%%Y\n"
" --time-format=<timeformat> - Specify log time format. e.g.,\n"
" %%H:%%M:%%S\n\n"
" --date-format=<dateformat> - Specify log date format. e.g., %%d/%%b/%%Y\n"
" --log-format=<logformat> - Specify log format. Inner quotes need to be\n"
" escaped, or use single quotes.\n"
" --time-format=<timeformat> - Specify log time format. e.g., %%H:%%M:%%S\n\n"

/* User Interface Options */
"User Interface Options\n\n"
" -c --config-dialog - Prompt log/date/time configuration\n"
" window.\n"
" -c --config-dialog - Prompt log/date/time configuration window.\n"
" -i --hl-header - Color highlight active panel.\n"
" -m --with-mouse - Enable mouse support on main dashboard.\n"
" --color=<fg:bg[attrs, PANEL]> - Specify custom colors. See manpage for\n"
" more details and options.\n"
" --color=<fg:bg[attrs, PANEL]> - Specify custom colors. See manpage for more\n"
" details and options.\n"
" --color-scheme=<1|2> - Color schemes: 1 => Grey, 2 => Green.\n"
" --html-report-title=<title> - Set HTML report page title and header.\n"
" --json-pretty-print - Format JSON output w/ tabs & newlines.\n"
" --no-color - Disable colored output.\n"
" --no-column-names - Don't write column names in term\n"
" output.\n"
" --no-csv-summary - Disable summary metrics on the CSV\n"
" output.\n"
" --no-column-names - Don't write column names in term output.\n"
" --no-csv-summary - Disable summary metrics on the CSV output.\n"
" --no-progress - Disable progress metrics.\n"
" --no-tab-scroll - Disable scrolling through panels on TAB.\n\n"
" --no-tab-scroll - Disable scrolling through panels on TAB.\n"

/* Server Options */
"Server Options\n\n"
" --addr=<addr> - Specify IP address to bind server to.\n"
" --origin=<addr> - Ensure clients send the specified origin\n"
" header upon the WebSocket handshake.\n"
" --origin=<addr> - Ensure clients send the specified origin header\n"
" upon the WebSocket handshake.\n"
" --port=<port> - Specify the port to use.\n"
" --real-time-html - Enable real-time HTML output.\n"
" --ws-url=<url> - URL to which the WebSocket server responds.\n\n"
" --ws-url=<url> - URL to which the WebSocket server\n"
" responds.\n\n"

/* File Options */
"File Options\n\n"
" -f --log-file=<filename> - Path to input log file.\n"
" -l --debug-file=<filename> - Send all debug messages to the specified\n"
" file.\n"
" -p --config-file=<filename> - Custom configuration file.\n"
" --invalid-requests=<filename> - Log invalid requests to the specified\n"
" file.\n"
" --no-global-config - Don't load global configuration\n"
" file.\n\n"
" --invalid-requests=<filename> - Log invalid requests to the specified file.\n"
" --no-global-config - Don't load global configuration file.\n"

/* Parse Options */
"Parse Options\n\n"
" -a --agent-list - Enable a list of user-agents by host.\n"
" -d --with-output-resolver - Enable IP resolver on HTML|JSON output.\n"
" -e --exclude-ip=<IP> - Exclude one or multiple IPv4/6. Allows\n"
" IP ranges e.g. 192.168.0.1-192.168.0.10\n"
" -e --exclude-ip=<IP> - Exclude one or multiple IPv4/6. Allows IP\n"
" ranges e.g. 192.168.0.1-192.168.0.10\n"
" -H --http-protocol - Include HTTP request protocol if found.\n"
" -M --http-method - Include HTTP request method if found.\n"
" -o --output-format=csv|json - Output either a JSON or a CSV file.\n"
" -q --no-query-string - Ignore request's query string. Removing\n"
" the query string can greatly decrease\n"
" memory consumption.\n"
" -q --no-query-string - Ignore request's query string. Removing the\n"
" query string can greatly decrease memory\n"
" consumption.\n"
" -r --no-term-resolver - Disable IP resolver on terminal output.\n"
" --444-as-404 - Treat non-standard status code 444 as\n"
" 404.\n"
" --4xx-to-unique-count - Add 4xx client errors to the unique\n"
" visitors count.\n"
" --all-static-files - Include static files with a query\n"
" string.\n"
" --444-as-404 - Treat non-standard status code 444 as 404.\n"
" --4xx-to-unique-count - Add 4xx client errors to the unique visitors\n"
" count.\n"
" --all-static-files - Include static files with a query string.\n"
" --date-spec=<spec> - Date specificity. Possible values: `hr`\n"
" (default), or `min`.\n"
" --double-decode - Decode double-encoded values.\n"
" --enable-panel=<PANEL> - Enable parsing/displaying the given panel.\n"
" --hour-spec=<spec> - Hour specificity. Possible values: `hr`\n"
" (default), or `min` (tenth of a min).\n"
" --ignore-crawlers - Ignore crawlers.\n"
" --ignore-panel=<PANEL> - Ignore parsing/displaying the given panel.\n"
" --ignore-referer=<NEEDLE> - Ignore a referer from being counted.\n"
" Wild cards are allowed. i.e., *.bing.com\n"
" --ignore-referer=<NEEDLE> - Ignore a referer from being counted. Wild cards\n"
" are allowed. i.e., *.bing.com\n"
" --ignore-status=<CODE> - Ignore parsing the given status code.\n"
" --real-os - Display real OS names. e.g, Windows XP,\n"
" Snow Leopard.\n"
" --real-os - Display real OS names. e.g, Windows XP, Snow\n"
" Leopard.\n"
" --sort-panel=PANEL,METRIC,ORDER - Sort panel on initial load. For example:\n"
" --sort-panel=VISITORS,BY_HITS,ASC. See\n"
" manpage for a list of panels/fields.\n"
" --static-file=<extension> - Add static file extension. e.g.: .mp3.\n"
" Extensions are case sensitive.\n"
" --time-dist-spec=<spec> - Time Distribution specificity. Values are,\n"
" `hour` (default), or `min`.\n\n"
" Extensions are case sensitive.\n\n"

/* GeoIP Options */
#ifdef HAVE_LIBGEOIP
"GeoIP Options\n\n"
" -g --std-geoip - Standard GeoIP database for less memory\n"
" consumption.\n"
" --geoip-database=<path> - Specify path to GeoIP database file.\n"
" i.e., GeoLiteCity.dat, GeoIPv6.dat ...\n\n"
" --geoip-database=<path> - Specify path to GeoIP database file. i.e.,\n"
" GeoLiteCity.dat, GeoIPv6.dat ...\n\n"
#endif

/* On-Disk Database Options */
#ifdef TCB_BTREE
"On-Disk Database Options\n\n"
" --keep-db-files - Persist parsed data into disk.\n"
" --load-from-disk - Load previously stored data from\n"
" disk.\n"
" --db-path=<path> - Path of the database file.\n"
" Default [%s]\n"
" --xmmap=<number> - Set the size in bytes of the extra\n"
" mapped memory. Default [%d]\n"
" --cache-lcnum=<number> - Max number of leaf nodes to be\n"
" cached. Default [%d]\n"
" --cache-ncnum=<number> - Max number of non-leaf nodes to be\n"
" cached. Default [%d]\n"
" --tune-lmemb=<number> - Number of members in each leaf page.\n"
" --load-from-disk - Load previously stored data from disk.\n"
" --db-path=<path> - Path of the database file. Default [%s]\n"
" --cache-lcnum=<number> - Max number of leaf nodes to be cached. Default\n"
" [%d]\n"
" --cache-ncnum=<number> - Max number of non-leaf nodes to be cached.\n"
" Default [%d]\n"
" --tune-bnum=<number> - Number of elements of the bucket array. Default\n"
" [%d]\n"
" --tune-lmemb=<number> - Number of members in each leaf page. Default\n"
" [%d]\n"
" --tune-nmemb=<number> - Number of members in each non-leaf page.\n"
" Default [%d]\n"
" --tune-nmemb=<number> - Number of members in each non-leaf\n"
" page. Default [%d]\n"
" --tune-bnum=<number> - Number of elements of the bucket\n"
" array. Default [%d]\n"
" --xmmap=<number> - Set the size in bytes of the extra mapped\n"
" memory. Default [%d]\n"
#if defined(HAVE_ZLIB) || defined(HAVE_BZ2)
" --compression=<zlib|bz2> - Specifies that each page is\n"
" compressed with ZLIB|BZ2 encoding.\n\n"
" --compression=<zlib|bz2> - Specifies that each page is compressed with\n"
" ZLIB|BZ2 encoding.\n\n"
#endif
#endif

Expand Down Expand Up @@ -500,10 +493,17 @@ read_option_args (int argc, char **argv)
if (!strcmp ("double-decode", long_opts[idx].name))
conf.double_decode = 1;

/* time distribution specificity */
if (!strcmp ("time-dist-spec", long_opts[idx].name) &&
!strcmp (optarg, "min"))
conf.time_dist_min = 1;
/* hour specificity */
if (!strcmp ("hour-spec", long_opts[idx].name) && !strcmp (optarg, "min"))
conf.time_dist_spec_min = 1;

/* date specificity */
if (!strcmp ("date-spec", long_opts[idx].name)) {
if (!strcmp (optarg, "hr"))
conf.date_spec_hr = 1;
if (!strcmp (optarg, "min"))
conf.date_spec_min = 1;
}

/* no color */
if (!strcmp ("no-color", long_opts[idx].name))
Expand Down
Loading

0 comments on commit a13c1fa

Please sign in to comment.