@platformatic/sql-graphql 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -8,6 +8,7 @@ const { mercuriusFederationPlugin } = require('@mercuriusjs/federation')
8
8
  const { findNearestString } = require('@platformatic/utils')
9
9
  const establishRelations = require('./lib/relationship')
10
10
  const setupSubscriptions = require('./lib/subscriptions')
11
+ const setupTelemetry = require('./lib/telemetry')
11
12
  const scalars = require('graphql-scalars')
12
13
  const errors = require('./lib/errors')
13
14
 
@@ -186,6 +187,10 @@ async function mapperToGraphql (app, opts) {
186
187
  resolvers
187
188
  })
188
189
 
190
+ if (app.openTelemetry) {
191
+ setupTelemetry(app)
192
+ }
193
+
189
194
  app.log.debug({ schema: sdl }, 'computed schema')
190
195
  }
191
196
 
@@ -0,0 +1,55 @@
1
+ 'use strict'
2
+
3
+ const telemetryWrapper = (app, fn, operationType, operationName) => async (...args) => {
4
+ const { startInternalSpan, endInternalSpan } = app.openTelemetry
5
+ const context = args[2]
6
+ const request = context?.reply?.request
7
+ const document = JSON.stringify(request?.body)
8
+
9
+ // GraphQL semantic conventions, see: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/graphql.md#semantic-conventions-for-graphql-server
10
+ const telemetryAttributes = {
11
+ 'graphql.document': document,
12
+ 'graphql.operation.name': operationName,
13
+ 'graphql.operation.type': operationType
14
+ }
15
+ const spanName = `${operationType} ${operationName}`
16
+ const ctx = request.span?.context
17
+
18
+ const span = startInternalSpan(spanName, ctx, telemetryAttributes)
19
+ try {
20
+ const result = await fn(...args)
21
+ endInternalSpan(span)
22
+ return result
23
+ // We ignore this because in sqlite it's HARD to have a resolver exception without a schema validation exception first.
24
+ } catch (err) /* istanbul ignore next */ {
25
+ endInternalSpan(span, err)
26
+ throw err
27
+ }
28
+ }
29
+
30
+ const setupTelemetry = app => {
31
+ /* istanbul ignore next */
32
+ if (!app || !app.graphql) {
33
+ app.log.warn('No graphql plugin found, skipping telemetry setup')
34
+ return
35
+ }
36
+ const schema = app.graphql.schema
37
+ /* istanbul ignore next */
38
+ if (!schema) {
39
+ app.log.warn('No graphql schema found, skipping telemetry setup')
40
+ return
41
+ }
42
+ const schemaTypeMap = schema.getTypeMap()
43
+ for (const schemaType of Object.values(schemaTypeMap)) {
44
+ const schemaTypeName = schemaType.name.toLowerCase() // query, mutation, subscription
45
+ if (typeof schemaType.getFields === 'function') {
46
+ for (const [fieldName, field] of Object.entries(schemaType.getFields())) {
47
+ if (typeof field.resolve === 'function') {
48
+ field.resolve = telemetryWrapper(app, field.resolve, schemaTypeName, fieldName)
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ module.exports = setupTelemetry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-graphql",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Map SQL dbs to GraphQL",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -22,8 +22,9 @@
22
22
  "tap": "^16.3.9",
23
23
  "tsd": "^0.29.0",
24
24
  "ws": "^8.14.2",
25
- "@platformatic/sql-events": "1.3.0",
26
- "@platformatic/sql-mapper": "1.3.0"
25
+ "@platformatic/sql-events": "1.4.0",
26
+ "@platformatic/sql-mapper": "1.4.0",
27
+ "@platformatic/telemetry": "1.4.0"
27
28
  },
28
29
  "dependencies": {
29
30
  "@fastify/error": "^3.3.0",
@@ -35,7 +36,7 @@
35
36
  "graphql-type-json": "^0.3.2",
36
37
  "inflected": "^2.1.0",
37
38
  "mercurius": "^13.1.0",
38
- "@platformatic/utils": "1.3.0"
39
+ "@platformatic/utils": "1.4.0"
39
40
  },
40
41
  "tsd": {
41
42
  "directory": "test/types"