Skip to content

Commit

Permalink
New StatsD plugin and Documentation about Tracing/Monitoring (#4422)
Browse files Browse the repository at this point in the history
* New StatsD plugin & Documentation about Tracing & Monitoring

* Fix website

* Go

* Fix

* Docs

* Fix typo

* ..
  • Loading branch information
ardatan authored Sep 2, 2022
1 parent e189199 commit 3165827
Show file tree
Hide file tree
Showing 22 changed files with 687 additions and 379 deletions.
10 changes: 10 additions & 0 deletions .changeset/brown-panthers-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@graphql-mesh/plugin-newrelic': patch
'@graphql-mesh/types': patch
'@graphql-mesh/plugin-statsd': patch
---

🚀🚀🚀 **New StatsD plugin** 🚀🚀🚀

You can learn more about tracing and monitoring in GraphQL with different plugins (StatsD, Prometheus, NewRelic and more) in our documentation.
[Tracing and Monitoring in GraphQL Mesh](http://www.graphql-mesh.com/docs/guides/monitoring-and-tracing)
3 changes: 0 additions & 3 deletions .github/workflows/algolia-integrity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ jobs:
- name: Build Packages
run: yarn build

- name: Build API docs JSON
run: yarn build:api-docs

- name: Algolia generate
run: yarn workspace website algolia-sync
env:
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/algolia-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ jobs:
- name: Build Packages
run: yarn build

- name: Build API docs JSON
run: yarn build:api-docs

- name: Algolia push
run: yarn workspace website algolia-sync
env:
Expand Down
6 changes: 1 addition & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
"private": true,
"scripts": {
"postinstall": "patch-package && husky install",
"prebuild:website": "yarn build && yarn build:api-docs",
"prebuild:website": "yarn build",
"build:website": "cd website && yarn build",
"generate-config-schema": "graphql-to-config-schema --schema ./**/yaml-config.graphql --json ./packages/types/src/config-schema.json --typings ./packages/types/src/config.ts --markdown ./website/src/generated-markdown && prettier --write ./packages/types/src",
"prebuild": "yarn generate-config-schema",
"transpile-ts": "tsc --project tsconfig.build.json",
"build": "yarn transpile-ts && bob build",
"build:api-docs": "ts-node --compiler-options='{\"module\":\"commonjs\"}' scripts/build-api-docs",
"copy-config-schema": "cp ./packages/types/src/config-schema.json ./packages/types/dist/",
"fix-bin": "node scripts/fix-bin.js",
"postbuild": "yarn copy-config-schema && yarn fix-bin",
Expand Down Expand Up @@ -55,9 +54,6 @@
"patch-package": "6.4.7",
"prettier": "2.7.1",
"ts-jest": "28.0.8",
"typedoc": "0.23.1",
"typedoc-plugin-markdown": "3.13.3",
"typedoc-plugin-rename-defaults": "0.6.4",
"typescript": "4.8.2"
},
"husky": {
Expand Down
3 changes: 1 addition & 2 deletions packages/plugins/newrelic/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ export default function useMeshNewrelic(options: MeshPluginOptions<YamlConfig.Ne
sourceSegment.addAttribute('key', JSON.stringify(key));
}
sourceSegment.start();
return ({ result }) => {
sourceSegment.addAttribute('result', JSON.stringify(result));
return () => {
sourceSegment.end();
};
},
Expand Down
22 changes: 22 additions & 0 deletions packages/plugins/newrelic/yaml-config.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,33 @@ extend type Plugin {
}

type NewrelicConfig @md {
"""
default `false`. When set to `true`, includes the GraphQL document defining the operations and fragments
"""
includeOperationDocument: Boolean
"""
default `false`. When set to `true`, includes all the operation variables with their values
"""
includeExecuteVariables: Boolean
"""
default: `false`. When set to `true`, includes the execution result
"""
includeRawResult: Boolean
"""
default `false`. When set to `true`, track resolvers as segments to monitor their performance
"""
trackResolvers: Boolean
"""
default `false`. When set to `true`, includes all the arguments passed to resolvers with their values
"""
includeResolverArgs: Boolean
"""
default `false`. When set to `true` append the names of operation root fields to the transaction name
"""
rootFieldsNaming: Boolean
"""
Allows to set a custom operation name to be used as transaction name and attribute
`extractOperationName: {context.headers['x-operation-name']}`
"""
extractOperationName: String
}
44 changes: 44 additions & 0 deletions packages/plugins/statsd/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@graphql-mesh/plugin-statsd",
"version": "0.0.0",
"sideEffects": false,
"main": "dist/index.js",
"module": "dist/index.mjs",
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
},
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./*": {
"require": "./dist/*.js",
"import": "./dist/*.mjs"
}
},
"license": "MIT",
"repository": {
"type": "git",
"url": "Urigo/graphql-mesh",
"directory": "packages/plugins/statsd"
},
"peerDependencies": {
"graphql": "*",
"hot-shots": "^8.0.0 || ^9.0.0"
},
"dependencies": {
"@envelop/statsd": "2.6.0",
"@graphql-mesh/utils": "0.41.1",
"@graphql-mesh/types": "0.82.0",
"tslib": "^2.4.0"
},
"devDependencies": {
"hot-shots": "9.0.0"
},
"publishConfig": {
"access": "public",
"directory": "dist"
}
}
67 changes: 67 additions & 0 deletions packages/plugins/statsd/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { MeshPlugin, MeshPluginOptions, YamlConfig } from '@graphql-mesh/types';
import StatsD, { Tags } from 'hot-shots';
import { useStatsD } from '@envelop/statsd';
import { getHeadersObj } from '@graphql-mesh/utils';

const metricNames = {
delegationCount: 'delegations.count',
delegationErrorCount: 'delegations.error.count',
delegationLatency: 'delegations.latency',
fetchCount: 'fetch.count',
fetchErrorCount: 'fetch.error.count',
fetchLatency: 'fetch.latency',
};

export default function useMeshStatsd(pluginOptions: MeshPluginOptions<YamlConfig.StatsdPlugin>): MeshPlugin<any> {
const client = new StatsD(pluginOptions.client);
const prefix = pluginOptions.prefix || 'graphql';
return {
onPluginInit({ addPlugin }) {
addPlugin(
useStatsD({
...pluginOptions,
client,
})
);
},
onFetch({ url, options, info }) {
const tags: Tags = {
url,
method: options.method,
sourceName: (info as any)?.sourceName,
fieldName: info?.fieldName,
requestHeaders: JSON.stringify(options.headers),
};
const start = Date.now();
return ({ response }) => {
tags.statusCode = response.status.toString();
tags.statusText = response.statusText;
const responseHeadersObj = getHeadersObj(response.headers);
tags.responseHeaders = JSON.stringify(responseHeadersObj);
client.increment(`${prefix}.${metricNames.fetchCount}`, tags);
const end = Date.now();
if (!response.ok) {
client.increment(`${prefix}.${metricNames.fetchErrorCount}`, tags);
}
client.histogram(`${prefix}.${metricNames.fetchLatency}`, end - start, tags);
};
},
onDelegate({ sourceName, fieldName, args, key }) {
const tags: Tags = {
sourceName,
fieldName,
args: JSON.stringify(args),
key,
};
const start = Date.now();
return ({ result }) => {
if (result instanceof Error) {
client.increment(`${prefix}.${metricNames.delegationErrorCount}`, tags);
}
client.increment(`${prefix}.${metricNames.delegationCount}`, tags);
const end = Date.now();
client.histogram(`${prefix}.${metricNames.delegationLatency}`, end - start, tags);
};
},
};
}
57 changes: 57 additions & 0 deletions packages/plugins/statsd/yaml-config.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
extend type Plugin {
statsd: StatsdPlugin
}

type StatsdPlugin @md {
"""
If you wish to disable introspection for logging (default: false)
"""
skipIntrospection: Boolean
"""
prefix.operations.count (default: graphql)
"""
prefix: String

"""
Client Configuration
"""
client: StatsdClientConfiguration
}

type StatsdClientConfiguration {
bufferFlushInterval: Int
bufferHolder: StatsdClientBufferHolder
cacheDns: Boolean
cacheDnsTtl: Int
globalTags: JSON
globalize: Boolean
host: String
isChild: Boolean
maxBufferSize: Int
mock: Boolean
path: String
port: Int
protocol: StatsdClientProtocol
sampleRate: Float
suffix: String
telegraf: Boolean
useDefaultRoute: Boolean
tagPrefix: String
tagSeperator: String
tcpGracefulErrorHandling: Boolean
tcpGracefulRestartRateLimit: Int
udsGracefulErrorHandling: Boolean
udsGracefulRestartRateLimit: Int
closingFlushInterval: Int
}

enum StatsdClientProtocol {
tcp
udp
uds
stream
}

type StatsdClientBufferHolder {
buffer: String!
}
Loading

1 comment on commit 3165827

@vercel
Copy link

@vercel vercel bot commented on 3165827 Sep 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.