diff --git a/.jshintignore b/.jshintignore index c72813792c..477776a99d 100644 --- a/.jshintignore +++ b/.jshintignore @@ -8,4 +8,5 @@ appengine/sails/api/responses/** appengine/webpack/dist/** functions/** **/node_modules/** -coverage/ \ No newline at end of file +coverage/ +logging/fluent.js \ No newline at end of file diff --git a/logging/fluent.js b/logging/fluent.js new file mode 100644 index 0000000000..2965b0e7d8 --- /dev/null +++ b/logging/fluent.js @@ -0,0 +1,57 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var express = require('express'); +var app = express(); + +app.get('*', function (req, res, next) { + return next('oops'); +}); + +// [START fluent] +var structuredLogger = require('fluent-logger').createFluentSender('myapp', { + host: 'localhost', + port: 24224, + timeout: 3.0 +}); + +var report = function (err, req) { + var payload = { + serviceContext: { + service: 'myapp', + }, + message: err.stack, + context: { + httpRequest: { + url: req.originalUrl, + method: req.method, + referrer: req.header('Referer'), + userAgent: req.header('User-Agent'), + remoteIp: req.ip, + responseStatusCode: 500, + } + } + }; + structuredLogger.emit('errors', payload); +}; + +// Handle errors (the following uses the Express framework) +app.use(function (err, req, res, next) { + report(err, req); + res.status(500).send(err.response || 'Something broke!'); +}); +// [END fluent] + +module.exports = app; diff --git a/logging/package.json b/logging/package.json index dca3aa1946..53a125b670 100644 --- a/logging/package.json +++ b/logging/package.json @@ -14,6 +14,8 @@ "export": "node export.js" }, "dependencies": { + "express": "^4.13.4", + "fluent-logger": "^1.1.0", "gcloud": "^0.30.3" } } diff --git a/test/logging/fluent.test.js b/test/logging/fluent.test.js new file mode 100644 index 0000000000..275db0f3e0 --- /dev/null +++ b/test/logging/fluent.test.js @@ -0,0 +1,51 @@ +// Copyright 2015-2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var test = require('ava'); +var proxyquire = require('proxyquire').noPreserveCache(); +var request = require('supertest'); + +test.cb('should log error', function (t) { + var loggerCalled = false; + + var structuredLogger = { + emit: function (name) { + loggerCalled = true; + t.is(name, 'errors'); + } + }; + + var app = proxyquire('../../logging/fluent.js', { + 'fluent-logger': { + createFluentSender: function (name, options) { + t.is(name, 'myapp'); + t.same(options, { + host: 'localhost', + port: 24224, + timeout: 3.0 + }); + return structuredLogger; + } + } + }); + + request(app) + .get('/') + .expect(500) + .expect(function () { + t.is(loggerCalled, true, 'structuredLogger.emit should have been called'); + }) + .end(t.end); +});