Merge pull request #10227 from overleaf/spd-td-opentelementry

Add opentelemetry to dev environment

GitOrigin-RevId: 31a8234197337a264412b411429692525793c8b0
This commit is contained in:
Simon Detheridge
2022-10-31 14:37:49 +00:00
committed by Copybot
parent 338c6be978
commit e2ac86adf4
11 changed files with 5485 additions and 39 deletions

View File

@@ -3,6 +3,7 @@ const os = require('os')
const ExpressCompression = require('compression')
const promClient = require('prom-client')
const promWrapper = require('./prom_wrapper')
const tracing = require('./tracing')
const DEFAULT_APP_NAME = 'unknown'
@@ -29,6 +30,9 @@ function configure(opts = {}) {
*/
function initialize(appName, opts = {}) {
appName = appName || DEFAULT_APP_NAME
if (tracing.tracingEnabled()) {
tracing.initialize(appName)
}
configure({ ...opts, appName })
collectDefaultMetrics({ timeout: 5000, prefix: '' })
promWrapper.setupSweeping()

View File

@@ -8,8 +8,17 @@
},
"dependencies": {
"@google-cloud/debug-agent": "^5.1.2",
"@google-cloud/opentelemetry-cloud-trace-exporter": "^1.1.0",
"@google-cloud/profiler": "^4.1.3",
"@google-cloud/trace-agent": "^5.1.1",
"@opentelemetry/api": "^1.0.4",
"@opentelemetry/auto-instrumentations-node": "^0.28.0",
"@opentelemetry/exporter-collector": "^0.25.0",
"@opentelemetry/exporter-jaeger": "^1.2.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.28.0",
"@opentelemetry/resources": "^1.2.0",
"@opentelemetry/sdk-node": "^0.28.0",
"@opentelemetry/semantic-conventions": "^1.2.0",
"compression": "^1.7.4",
"prom-client": "^11.1.3",
"yn": "^3.1.1"

View File

@@ -0,0 +1,58 @@
const opentelemetry = require('@opentelemetry/sdk-node')
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node')
const {
diag,
DiagConsoleLogger,
DiagLogLevel,
trace,
} = require('@opentelemetry/api')
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger')
const { Resource } = require('@opentelemetry/resources')
const {
SemanticResourceAttributes,
} = require('@opentelemetry/semantic-conventions')
const GCP = require('@google-cloud/opentelemetry-cloud-trace-exporter')
let tracer
function tracingEnabled() {
return process.env.GCP_OPENTELEMETRY || process.env.JAEGER_OPENTELEMETRY
}
function initialize(appName) {
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO)
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: appName,
[SemanticResourceAttributes.SERVICE_NAMESPACE]: 'Overleaf',
'host.type': 'VM',
})
let exporter
if (process.env.GCP_OPENTELEMETRY) {
exporter = new GCP.TraceExporter()
} else if (process.env.JAEGER_OPENTELEMETRY) {
exporter = new JaegerExporter({ host: process.env.JAEGER_HOST || 'jaeger' })
} else {
return
}
const sdk = new opentelemetry.NodeSDK({
traceExporter: exporter,
logger: console,
instrumentations: [getNodeAutoInstrumentations()],
resource,
})
tracer = trace.getTracer(appName)
sdk.start()
}
function getTracer() {
return tracer
}
module.exports = { initialize, getTracer, tracingEnabled }

5379
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1289,6 +1289,7 @@ const ProjectController = {
metadata: { viewport: false },
showUpgradePrompt,
fixedSizeDocument: true,
useOpenTelemetry: Settings.useOpenTelemetryClient,
})
timer.done()
}

View File

@@ -14,7 +14,7 @@ function isBodyParserError(nextArg) {
const wrapBodyParser = method => opts => {
const middleware = bodyParser[method](opts)
return (req, res, next) => {
return function bodyParser(req, res, next) {
middleware(req, res, nextArg => {
if (isBodyParserError(nextArg)) {
return HttpErrorHandler.handleErrorByStatusCode(

View File

@@ -20,7 +20,7 @@ const RedisStore = require('connect-redis')(session)
const bodyParser = require('./BodyParserWrapper')
const methodOverride = require('method-override')
const cookieParser = require('cookie-parser')
const bearerToken = require('express-bearer-token')
const bearerTokenMiddleware = require('express-bearer-token')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
@@ -67,7 +67,7 @@ if (Settings.behindProxy) {
* X-Original-Forwarded-For. Express expects all proxy IPs to be in a comma
* separated list in X-Forwarded-For.
*/
app.use((req, res, next) => {
app.use(function getForwardedForHeader(req, res, next) {
if (
req.headers['x-original-forwarded-for'] &&
req.headers['x-forwarded-for']
@@ -100,7 +100,7 @@ Object.defineProperty(app.request, 'ip', {
return ip
},
})
app.use(function (req, res, next) {
app.use(function ignoreAbortedConnections(req, res, next) {
if (req.destroyed) {
// Request has been aborted already.
return
@@ -115,7 +115,7 @@ app.use(function (req, res, next) {
if (Settings.exposeHostname) {
const HOSTNAME = require('os').hostname()
app.use((req, res, next) => {
app.use(function exposeHostname(req, res, next) {
res.setHeader('X-Served-By', HOSTNAME)
next()
})
@@ -135,7 +135,8 @@ Modules.registerAppMiddleware(app)
app.use(bodyParser.urlencoded({ extended: true, limit: '2mb' }))
app.use(bodyParser.json({ limit: Settings.max_json_request_size }))
app.use(methodOverride())
app.use(bearerToken())
// add explicit name for telemetry
app.use(bearerTokenMiddleware())
app.use(metrics.http.monitor(logger))
@@ -206,7 +207,7 @@ webRouter.use(translations.setLangBasedOnDomainMiddleware)
if (Settings.cookieRollingSession) {
// Measure expiry from last request, not last login
webRouter.use(function (req, res, next) {
webRouter.use(function touchSession(req, res, next) {
if (!req.session.noSessionCallback) {
req.session.touch()
if (SessionManager.isUserLoggedIn(req.session)) {
@@ -229,7 +230,7 @@ expressLocals(webRouter, privateApiRouter, publicApiRouter)
webRouter.use(SessionAutostartMiddleware.invokeCallbackMiddleware)
webRouter.use(function (req, res, next) {
webRouter.use(function checkIfSiteClosed(req, res, next) {
if (Settings.siteIsOpen) {
next()
} else if (hasAdminAccess(SessionManager.getSessionUser(req.session))) {
@@ -239,7 +240,7 @@ webRouter.use(function (req, res, next) {
}
})
webRouter.use(function (req, res, next) {
webRouter.use(function checkIfEditorClosed(req, res, next) {
if (Settings.editorIsOpen) {
next()
} else if (req.url.indexOf('/admin') === 0) {
@@ -253,7 +254,7 @@ webRouter.use(AuthenticationController.validateAdmin)
// add security headers using Helmet
const noCacheMiddleware = require('nocache')()
webRouter.use(function (req, res, next) {
webRouter.use(function addNoCacheHeader(req, res, next) {
const isLoggedIn = SessionManager.isUserLoggedIn(req.session)
const isProjectPage = !!req.path.match('^/project/[a-f0-9]{24}$')
if (isLoggedIn || isProjectPage) {

View File

@@ -27,6 +27,7 @@ meta(name="ol-galileoPromptWords" data-type="string" content=galileoPromptWords)
meta(name="ol-galileoFeatures" data-type="json" content=galileoFeatures)
meta(name="ol-detachRole" data-type="string" content=detachRole)
meta(name="ol-showUpgradePrompt" data-type="boolean" content=showUpgradePrompt)
meta(name="ol-useOpenTelemetry" data-type="boolean" content=useOpenTelemetry)
- var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {})
meta(name="ol-fileActionI18n" data-type="json" content=fileActionI18n)

View File

@@ -16,6 +16,7 @@
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import '../tracing'
import App from './base'
import FileTreeManager from './ide/file-tree/FileTreeManager'
import LoadingManager from './ide/LoadingManager'
@@ -64,7 +65,6 @@ import './features/editor-navigation-toolbar/controllers/editor-navigation-toolb
import './features/pdf-preview/controllers/pdf-preview-controller'
import './features/share-project-modal/controllers/react-share-project-modal-controller'
import './features/source-editor/controllers/editor-switch-controller'
import getMeta from './utils/meta'
import { cleanupServiceWorker } from './utils/service-worker-cleanup'
import { reportCM6Perf } from './infrastructure/cm6-performance'

View File

@@ -0,0 +1,37 @@
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
import { Resource } from '@opentelemetry/resources'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http/build/esnext'
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'
import { ZoneContextManager } from '@opentelemetry/context-zone'
import { registerInstrumentations } from '@opentelemetry/instrumentation'
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web'
import getMeta from './js/utils/meta'
if (getMeta('ol-useOpenTelemetry')) {
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'frontend',
[SemanticResourceAttributes.SERVICE_NAMESPACE]: 'Overleaf',
})
const provider = new WebTracerProvider({ resource })
provider.addSpanProcessor(
new SimpleSpanProcessor(
new OTLPTraceExporter({
url: `https://${window.location.hostname}/otlp/v1/traces`,
})
)
)
provider.register({
// Changing default contextManager to use ZoneContextManager - supports asynchronous operations - optional
contextManager: new ZoneContextManager(),
})
// Registering instrumentations
registerInstrumentations({
instrumentations: [getWebAutoInstrumentations()],
})
}

View File

@@ -82,6 +82,18 @@
"@lezer/common": "^1.0.1",
"@lezer/highlight": "^1.1.1",
"@lezer/lr": "^1.2.3",
"@opentelemetry/api": "^1.0.4",
"@opentelemetry/auto-instrumentations-web": "^0.27.2",
"@opentelemetry/context-zone": "^1.2.0",
"@opentelemetry/exporter-jaeger": "^1.2.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.28.0",
"@opentelemetry/instrumentation": "^0.27.0",
"@opentelemetry/instrumentation-document-load": "^0.27.1",
"@opentelemetry/instrumentation-xml-http-request": "^0.28.0",
"@opentelemetry/resources": "^1.2.0",
"@opentelemetry/sdk-trace-base": "^1.2.0",
"@opentelemetry/sdk-trace-web": "^1.2.0",
"@opentelemetry/semantic-conventions": "^1.2.0",
"@overleaf/logger": "*",
"@overleaf/metrics": "*",
"@overleaf/o-error": "*",