diff --git a/app/admin/controller/nginx/AccessLog.php b/app/admin/controller/nginx/AccessLog.php new file mode 100644 index 0000000..104712c --- /dev/null +++ b/app/admin/controller/nginx/AccessLog.php @@ -0,0 +1,13 @@ + +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+ \ No newline at end of file diff --git a/app/admin/view/nginx/access_log/add.js b/app/admin/view/nginx/access_log/add.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/nginx/access_log/add.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/nginx/access_log/edit.html b/app/admin/view/nginx/access_log/edit.html new file mode 100644 index 0000000..67ab923 --- /dev/null +++ b/app/admin/view/nginx/access_log/edit.html @@ -0,0 +1,122 @@ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+
\ No newline at end of file diff --git a/app/admin/view/nginx/access_log/edit.js b/app/admin/view/nginx/access_log/edit.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/nginx/access_log/edit.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/nginx/access_log/index.html b/app/admin/view/nginx/access_log/index.html new file mode 100644 index 0000000..ef77867 --- /dev/null +++ b/app/admin/view/nginx/access_log/index.html @@ -0,0 +1,9 @@ +
+
+ +
+
+
diff --git a/app/admin/view/nginx/access_log/index.js b/app/admin/view/nginx/access_log/index.js new file mode 100644 index 0000000..b15a802 --- /dev/null +++ b/app/admin/view/nginx/access_log/index.js @@ -0,0 +1,48 @@ +$(function(){ + ua.table.render({ + init: init, + toolbar: [], + defaultToolbar: ['filter'], + cols: [[ + {type: 'checkbox'}, + {field: 'time_local', title: '时间', width: 170, search: 'range', templet: ua.table.date}, + {field: 'method', title: '方法', width: 80, search: 'select', selectList: {GET: 'GET', POST: 'POST', PUT: 'PUT', DELETE: 'DELETE', HEAD: 'HEAD', OPTIONS: 'OPTIONS', PATCH: 'PATCH'}}, + {field: 'uri', title: 'URI', minWidth: 200, searchOp: '%*%'}, + {field: 'status', title: '状态码', width: 90, search: 'select', selectList: {200: '200', 301: '301', 302: '302', 304: '304', 400: '400', 401: '401', 403: '403', 404: '404', 499: '499', 500: '500', 502: '502', 503: '503', 504: '504'}, templet: function(d) { + var s = parseInt(d.status); + var cls = 'layui-badge'; + if (s >= 200 && s < 300) cls = 'layui-badge layui-bg-green'; + else if (s >= 300 && s < 400) cls = 'layui-badge layui-bg-blue'; + else if (s >= 400 && s < 500) cls = 'layui-badge layui-bg-orange'; + else if (s >= 500) cls = 'layui-badge layui-bg-red'; + return '' + d.status + ''; + }}, + {field: 'remote_addr', title: '客户端IP', width: 140, searchOp: '%*%'}, + {field: 'request_time', title: '耗时(秒)', width: 100, search: 'number_limit', templet: function(d) { + var t = parseFloat(d.request_time); + if (t >= 1) return '' + t + 's'; + if (t >= 0.3) return '' + t + 's'; + return t + 's'; + }}, + {field: 'body_bytes_sent', title: '响应字节', width: 100, search: 'number_limit'}, + {field: 'http_user_agent', title: 'User-Agent', minWidth: 200, search: false}, + { + width: 100, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [ + [{ + class: 'layui-btn layui-btn-primary layui-btn-xs', + method: 'tab', + field: 'id', + text: '详情', + title: '查看详情', + auth: 'read', + url: init.readUrl, + icon: '' + }] + ] + }, + + ]], + }); + + ua.listen(); +}) diff --git a/app/admin/view/nginx/access_log/read.html b/app/admin/view/nginx/access_log/read.html new file mode 100644 index 0000000..ca0f137 --- /dev/null +++ b/app/admin/view/nginx/access_log/read.html @@ -0,0 +1,229 @@ +
+
+
+
+
+
+

#{$row.id} {$title}

+
ID: {$row.id}
+
+
+ + +
+
+
+
+
+ +
+
+
+
来源日志文件路径
+
+ {notempty name="row.file_path"} + {$row.file_path} + {else/} + 暂无数据 + {/notempty} +
+
+
+
客户端 IP(含 IPv6)
+
+ {notempty name="row.remote_addr"} + {$row.remote_addr} + {else/} + 暂无数据 + {/notempty} +
+
+
+
HTTP 认证用户名
+
+ {notempty name="row.remote_user"} + {$row.remote_user} + {else/} + 暂无数据 + {/notempty} +
+
+
+
请求时间戳(业务时区)
+
+ {notempty name="row.time_local"} + {$row.time_local|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+
+
HTTP 方法
+
+ {notempty name="row.method"} + {$row.method} + {else/} + 暂无数据 + {/notempty} +
+
+
+
请求 URI(超 255 截断)
+
+ {notempty name="row.uri"} + {$row.uri} + {else/} + 暂无数据 + {/notempty} +
+
+
+
查询字符串
+
+ {notempty name="row.query_string"} + {$row.query_string} + {else/} + 暂无数据 + {/notempty} +
+
+
+
HTTP 协议版本
+
+ {notempty name="row.http_version"} + {$row.http_version} + {else/} + 暂无数据 + {/notempty} +
+
+
+
响应体字节数
+
+ {notempty name="row.body_bytes_sent"} + {$row.body_bytes_sent} + {else/} + 暂无数据 + {/notempty} +
+
+
+
Referer
+
+ {notempty name="row.http_referer"} + {$row.http_referer} + {else/} + 暂无数据 + {/notempty} +
+
+
+
User-Agent(超 500 截断)
+
+ {notempty name="row.http_user_agent"} + {$row.http_user_agent|raw} + {else/} + 暂无内容 + {/notempty} +
+
+
+
nginx 请求总耗时
+
+ {notempty name="row.request_time"} + {$row.request_time} + {else/} + 暂无数据 + {/notempty} +
+
+
+
upstream 响应时间
+
+ {notempty name="row.upstream_response_time"} + {$row.upstream_response_time} + {else/} + 暂无数据 + {/notempty} +
+
+
+
总发送字节数(含 header)
+
+ {notempty name="row.bytes_sent"} + {$row.bytes_sent} + {else/} + 暂无数据 + {/notempty} +
+
+
+
国家(GeoIP 预留)
+
+ {notempty name="row.country"} + {$row.country} + {else/} + 暂无数据 + {/notempty} +
+
+
+
省份(GeoIP 预留)
+
+ {notempty name="row.province"} + {$row.province} + {else/} + 暂无数据 + {/notempty} +
+
+
+
城市(GeoIP 预留)
+
+ {notempty name="row.city"} + {$row.city} + {else/} + 暂无数据 + {/notempty} +
+
+ +
+
+ +
+

基础信息

+
+
+
ID
+
{$row.id}
+
+
+
HTTP 状态码
+
+ {notempty name="row.status"} + {$row.status} + {else/} + 暂无数据 + {/notempty} +
+
+
+
入库时间戳
+
+ {notempty name="row.create_time"} + {$row.create_time|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/admin/view/nginx/access_log/read.js b/app/admin/view/nginx/access_log/read.js new file mode 100644 index 0000000..f5671a7 --- /dev/null +++ b/app/admin/view/nginx/access_log/read.js @@ -0,0 +1,22 @@ +$(function(){ + // 删除数据 + window.deleteData = function(id) { + layer.confirm('确定要删除这条数据吗?', { + icon: 3, + title: '提示' + }, function(index) { + $.post('{{:url("delete")}}', {id: id}, function(res) { + if (res.code == 0) { + layer.msg('删除成功', {icon: 1}, function() { + location.href = '{{:url("index")}}'; + }); + } else { + layer.msg(res.msg, {icon: 2}); + } + }, 'json'); + layer.close(index); + }); + }; + + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/nginx/log_position/_common.js b/app/admin/view/nginx/log_position/_common.js new file mode 100644 index 0000000..b788eda --- /dev/null +++ b/app/admin/view/nginx/log_position/_common.js @@ -0,0 +1,11 @@ +var init = { + tableElem: '#currentTable', + tableRenderId: 'currentTableRenderId', + indexUrl: 'nginx.log_position/index', + addUrl: '', + editUrl: '', + readUrl: 'nginx.log_position/read', + deleteUrl: '', + exportUrl: '', + modifyUrl: '', +}; diff --git a/app/admin/view/nginx/log_position/add.html b/app/admin/view/nginx/log_position/add.html new file mode 100644 index 0000000..f0a7b00 --- /dev/null +++ b/app/admin/view/nginx/log_position/add.html @@ -0,0 +1,56 @@ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+
\ No newline at end of file diff --git a/app/admin/view/nginx/log_position/add.js b/app/admin/view/nginx/log_position/add.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/nginx/log_position/add.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/nginx/log_position/edit.html b/app/admin/view/nginx/log_position/edit.html new file mode 100644 index 0000000..ecdaf1e --- /dev/null +++ b/app/admin/view/nginx/log_position/edit.html @@ -0,0 +1,56 @@ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ {notempty name='$Request.param.backTagId'} +
返回
+ {/notempty} + + +
+ +
+
\ No newline at end of file diff --git a/app/admin/view/nginx/log_position/edit.js b/app/admin/view/nginx/log_position/edit.js new file mode 100644 index 0000000..4a445e0 --- /dev/null +++ b/app/admin/view/nginx/log_position/edit.js @@ -0,0 +1,3 @@ +$(function(){ + ua.listen(); +}) \ No newline at end of file diff --git a/app/admin/view/nginx/log_position/index.html b/app/admin/view/nginx/log_position/index.html new file mode 100644 index 0000000..34e7d7f --- /dev/null +++ b/app/admin/view/nginx/log_position/index.html @@ -0,0 +1,9 @@ +
+
+ +
+
+
diff --git a/app/admin/view/nginx/log_position/index.js b/app/admin/view/nginx/log_position/index.js new file mode 100644 index 0000000..e900449 --- /dev/null +++ b/app/admin/view/nginx/log_position/index.js @@ -0,0 +1,41 @@ +$(function(){ + ua.table.render({ + init: init, + toolbar: [], + defaultToolbar: ['filter'], + cols: [[ + {type: 'checkbox'}, + {field: 'id', title: 'ID', width: 80}, + {field: 'file_path', title: '文件路径', minWidth: 250}, + {field: 'inode', title: 'inode', width: 120}, + {field: 'offset', title: '偏移量', width: 120}, + {field: 'last_read_time', title: '最后读取时间', width: 170, search: 'range', templet: ua.table.date}, + {field: 'last_line_hash', title: '最后行哈希', width: 160, search: false}, + {field: 'parse_fail_count', title: '失败次数', width: 100, search: 'number_limit', templet: function(d) { + var c = parseInt(d.parse_fail_count); + if (c > 0) return '' + c + ''; + return '0'; + }}, + {field: 'parse_fail_samples', title: '失败样本', minWidth: 200, search: false}, + {field: 'create_time', title: '创建时间', width: 170, search: 'range', templet: ua.table.date}, + {field: 'update_time', title: '更新时间', width: 170, search: false, templet: ua.table.date}, + { + width: 100, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [ + [{ + class: 'layui-btn layui-btn-primary layui-btn-xs', + method: 'tab', + field: 'id', + text: '详情', + title: '查看详情', + auth: 'read', + url: init.readUrl, + icon: '' + }] + ] + }, + + ]], + }); + + ua.listen(); +}) diff --git a/app/admin/view/nginx/log_position/read.html b/app/admin/view/nginx/log_position/read.html new file mode 100644 index 0000000..0d68f53 --- /dev/null +++ b/app/admin/view/nginx/log_position/read.html @@ -0,0 +1,119 @@ +
+
+
+
+
+
+

#{$row.id} {$title}

+
ID: {$row.id}
+
+
+ + +
+
+
+
+
+ +
+
+
+
日志文件绝对路径
+
+ {notempty name="row.file_path"} + {$row.file_path} + {else/} + 暂无数据 + {/notempty} +
+
+
+
文件 inode,用于检测日志轮转
+
+ {notempty name="row.inode"} + {$row.inode} + {else/} + 暂无数据 + {/notempty} +
+
+
+
上次读取到的字节偏移
+
+ {notempty name="row.offset"} + {$row.offset} + {else/} + 暂无数据 + {/notempty} +
+
+
+
上次读取时间戳
+
+ {notempty name="row.last_read_time"} + {$row.last_read_time|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+
+
上次最后一行的 md5 哈希(容错校验)
+
+ {notempty name="row.last_line_hash"} + {$row.last_line_hash} + {else/} + 暂无数据 + {/notempty} +
+
+
+
解析失败累计次数
+
+ {notempty name="row.parse_fail_count"} + {$row.parse_fail_count} + {else/} + 暂无数据 + {/notempty} +
+
+
+
解析失败样本行(最多保留若干条)
+
+ {notempty name="row.parse_fail_samples"} + {$row.parse_fail_samples|raw} + {else/} + 暂无内容 + {/notempty} +
+
+ +
+
+ +
+

基础信息

+
+
+
ID
+
{$row.id}
+
+
+
创建时间戳
+
+ {notempty name="row.create_time"} + {$row.create_time|date="Y-m-d H:i:s"} + {else/} + 暂无数据 + {/notempty} +
+
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/admin/view/nginx/log_position/read.js b/app/admin/view/nginx/log_position/read.js new file mode 100644 index 0000000..f5671a7 --- /dev/null +++ b/app/admin/view/nginx/log_position/read.js @@ -0,0 +1,22 @@ +$(function(){ + // 删除数据 + window.deleteData = function(id) { + layer.confirm('确定要删除这条数据吗?', { + icon: 3, + title: '提示' + }, function(index) { + $.post('{{:url("delete")}}', {id: id}, function(res) { + if (res.code == 0) { + layer.msg('删除成功', {icon: 1}, function() { + location.href = '{{:url("index")}}'; + }); + } else { + layer.msg(res.msg, {icon: 2}); + } + }, 'json'); + layer.close(index); + }); + }; + + ua.listen(); +}) \ No newline at end of file diff --git a/extend/base/admin/controller/nginx/AccessLogBase.php b/extend/base/admin/controller/nginx/AccessLogBase.php new file mode 100644 index 0000000..2a69f03 --- /dev/null +++ b/extend/base/admin/controller/nginx/AccessLogBase.php @@ -0,0 +1,106 @@ + 'desc', + ]; + + public function __construct(App $app) + { + parent::__construct($app); + + $this->model = new \app\admin\model\NginxAccessLog(); + } + + /** + * @NodeAnotation(title="列表") + */ + public function index() + { + if ($this->request->isAjax()) { + if (input('selectFields')) { + return $this->selectList(); + } + list($page, $limit, $where, $excludes, $request_options, $group) = $this->buildTableParames(); + $count = $this->model + ->where($where) + ->group($group) + ->count(); + $list = $this->model + ->where($where) + ->page($page, $limit) + ->order($this->sort) + ->group($group) + ->select(); + $data = [ + 'code' => 0, + 'msg' => '', + 'count' => $count, + 'data' => $list, + ]; + + return json($data); + } + + return $this->fetch(); + } + + /** + * @NodeAnotation(title="详情") + */ + public function read($id) + { + $row = $this->model->find($id); + empty($row) && $this->error('数据不存在'); + + $this->assign('row', $row); + + return $this->fetch(); + } + + /** + * @NodeAnotation(title="添加") + */ + public function add() + { + $this->error('日志表不允许手动添加'); + } + + /** + * @NodeAnotation(title="编辑") + */ + public function edit($id) + { + $this->error('日志表不允许编辑'); + } + + /** + * @NodeAnotation(title="删除") + */ + public function delete($id) + { + $this->error('日志表不允许删除'); + } + + /** + * @NodeAnotation(title="属性修改") + */ + public function modify() + { + $this->error('日志表不允许修改'); + } +} diff --git a/extend/base/admin/controller/nginx/LogPositionBase.php b/extend/base/admin/controller/nginx/LogPositionBase.php new file mode 100644 index 0000000..ab3c06c --- /dev/null +++ b/extend/base/admin/controller/nginx/LogPositionBase.php @@ -0,0 +1,106 @@ + 'desc', + ]; + + public function __construct(App $app) + { + parent::__construct($app); + + $this->model = new \app\admin\model\NginxLogPosition(); + } + + /** + * @NodeAnotation(title="列表") + */ + public function index() + { + if ($this->request->isAjax()) { + if (input('selectFields')) { + return $this->selectList(); + } + list($page, $limit, $where, $excludes, $request_options, $group) = $this->buildTableParames(); + $count = $this->model + ->where($where) + ->group($group) + ->count(); + $list = $this->model + ->where($where) + ->page($page, $limit) + ->order($this->sort) + ->group($group) + ->select(); + $data = [ + 'code' => 0, + 'msg' => '', + 'count' => $count, + 'data' => $list, + ]; + + return json($data); + } + + return $this->fetch(); + } + + /** + * @NodeAnotation(title="详情") + */ + public function read($id) + { + $row = $this->model->find($id); + empty($row) && $this->error('数据不存在'); + + $this->assign('row', $row); + + return $this->fetch(); + } + + /** + * @NodeAnotation(title="添加") + */ + public function add() + { + $this->error('日志表不允许手动添加'); + } + + /** + * @NodeAnotation(title="编辑") + */ + public function edit($id) + { + $this->error('日志表不允许编辑'); + } + + /** + * @NodeAnotation(title="删除") + */ + public function delete($id) + { + $this->error('日志表不允许删除'); + } + + /** + * @NodeAnotation(title="属性修改") + */ + public function modify() + { + $this->error('日志表不允许修改'); + } +}