Logging requests to GraphQL Metrics

You can easily use Stellate GraphQL Metrics without proxying all your requests through Stellate. To achieve that you can push data about your GraphQL requests to our logging endpoint directly from your origin server.

We also provide plugins for multiple servers.

Authorization

In order to authorize you need to send a token with the request using the Stellate-Logging-Token header.

Obtaining the token

You can create the token on the Stellate dashboard by going to your service settings.

Endpoint

Send a POST request to https://<service-name>.stellate.sh/log. The following properties can be sent in the request body.

PropertyExpected typeIs requiredDescription
operationstringtrueThe GraphQL query handled by the origin
methodstringtrueThe HTTP method used to send the GraphQL request
responseSizenumbertrueThe length of the stringified response body
responseHashnumbertrueA blake3 hash of the JSON-stringified execution result
elapsednumbertrueThe time (in ms) it took to handle the GraphQL request
operationNamestringfalseThe name of the operation that has been executed
variablesobjectfalseThe variables sent with the GraphQL requests (stored as hash to count distinct variables for the given GraphQL operation)
variablesHashnumberfalseA blake3 hash of the JSON-stringified variables object (takes precendence over the variables property)
ipstringfalseThe IP that send the GraphQL request (will be hashed with SHA-256 before storing it)
errorsobject[]falseThe list of GraphQL errors that are part of the execution result
statusCodenumbertrueThe HTTP status code of the response
statusTextstringfalseThe text sent with the above HTTP status code (by default we use the standardized status texts)
userAgentstringfalseThe value of the user-agent header sent with the HTTP request
refererstringfalseThe value of the referer header sent with the HTTP request
hasSetCookiebooleanfalseThe value of the set-cookie header sent with the HTTP response

You will need to include a logging-token in the Stellate-Logging-Token header, these can be generated in the service-settings.

Response

For a successful log intake, the above endpoint will respond with a 204 status code. If there was an error, it'll respond with a 400 status code.

How to hash values

When generating an integer hash you can do so with the following function, this is needed for the responseBodyHash

function createIntHash(str) {
  let val = 0
  const strlen = str.length

  if (strlen === 0) {
    return val
  }

  for (let i = 0; i < strlen; ++i) {
    const code = str.charCodeAt(i)
    val = (val << 5) - val + code
    val &= val // Int32
  }
  return val >>> 0 // uInt32
}

Plugins

All of these plugins take a fetch function as an argument, this enables using these plugins in any JavaScript environment. If you are running NodeJS you can use the node-fetch package, and in an edge environment (e.g. Cloudflare Workers) pass the global fetch function.

Plugin for apollo-server

import { createStellateLoggerPlugin } from 'stellate/apollo-server'
import { startStandaloneServer } from '@apollo/server/standalone'
import { ApolloServer } from '@apollo/server'

const stellatePlugin = createStellateLoggerPlugin({
  serviceName: '${serviceName}',
  token: '${loggingToken}',
  // a fetch compliant function, can be from `node-fetch` if you are running in NodeJS,
  // or the global fetch function if running in a v8 environment (e.g. Cloudflare Workers)
  fetch: fetch,
})

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [stellatePlugin],
})

const { url } = await startStandaloneServer(server, { listen: { port: 4000 } })

Plugin for graphql-yoga

import { createStellateLoggerPlugin } from 'stellate/graphql-yoga'
import { createServer } from 'node:http'
import { createYoga, createSchema } from 'graphql-yoga'

const stellatePlugin = createStellateLoggerPlugin({
  serviceName: '${serviceName}',
  token: '${loggingToken}',
  // a fetch compliant function, can be from `node-fetch` if you are running in NodeJS,
  // or the global fetch function if running in a v8 environment (e.g. Cloudflare Workers)
  fetch: fetch,
})

const yoga = createYoga({ schema, plugins: [stellatePlugin] })
const server = createServer(yoga)
server.listen(4000)

Plugin for GraphQL Mesh

Install @envelop/core and stellate:

$ npm install @envelop/core stellate

Include it in your plugins file:

// envelopPlugins.ts
import { createStellateLoggerPlugin } from 'stellate/envelop'
import { MeshPlugin } from '@graphql-mesh/types'

const plugins: MeshPlugin = [
  createStellateLoggerPlugin({
    serviceName: '${serviceName}',
    token: '${loggingToken}',
    // a fetch compliant function, can be from `node-fetch` if you are running in NodeJS,
    // or the global fetch function if running in a v8 environment (e.g. Cloudflare Workers)
    fetch: fetch,
  }),
]

// reference this file using 'additionalEnvelopPlugins' in your .meshrc.yaml config file
export default plugins

Plugin for GraphQL Envelop

Can be used with any envelop compatible plugin system, such as GraphQL Mesh, etc. Start by installing @envelop/core and stellate:

$ npm install @envelop/core stellate

Then add it to your envelop plugins:

import { createStellateLoggerPlugin } from 'stellate/envelop'
import { envelop } from '@envelop/core'

export const getEnveloped = envelop({
  plugins: [
    // ... other plugins
    createStellateLoggerPlugin({
      serviceName: '${serviceName}',
      token: '${loggingToken}',
      // a fetch compliant function, can be from `node-fetch` if you are running in NodeJS,
      // or the global fetch function if running in a v8 environment (e.g. Cloudflare Workers)
      fetch: fetch,
    }),
  ],
})

server.on('req', async (req, res) => {
  // The request entry is important here so the stellage plugin has the request context
  getEnveloped({ request: req })
})