_createClient() {
    const endpoint = this._endpoint
    logger.trace('Creating gRPC client for: ', endpoint)

    const packageDefinition = protoLoader.loadSync(PROTO_DEFINITION_PATH, PROTO_OPTIONS)

    const protoDescriptor = grpc.loadPackageDefinition(packageDefinition)

    const traceApi = protoDescriptor.com.newrelic.trace.v1

    const credentials = this._insecureConnection ? grpc.credentials.createInsecure() : this._generateCredentials(grpc)

    const opts = {}

    if (this._compression) {
      // 2 = gzip compression
      // see: https://github.com/grpc/grpc-node/blob/master/packages/grpc-js/src/compression-algorithms.ts#L21
      opts['grpc.default_compression_algorithm'] = 2
      this._metrics
        .getOrCreateMetric(`${NAMES.INFINITE_TRACING.COMPRESSION}/enabled`)
        .incrementCallCount()
    } else {
      this._metrics
        .getOrCreateMetric(`${NAMES.INFINITE_TRACING.COMPRESSION}/disabled`)
        .incrementCallCount()
    }

    // this defines retries of writes to stream if it fails with `UNAVAILABLE` or `INTERNAL`
    const serviceConfig = {
      methodConfig: [
        {
          name: [
            {
              service: 'com.newrelic.trace.v1.IngestService'
            }
          ],
          retryPolicy: {
            maxAttempts: 10,
            initialBackoff: '0.1s',
            maxBackoff: '1s',
            backoffMultiplier: 2,
            retryableStatusCodes: ['UNAVAILABLE', 'INTERNAL']
          }
        }
      ]
    }
    opts['grpc.service_config'] = JSON.stringify(serviceConfig)

    return new traceApi.IngestService(endpoint, credentials, opts)
  }
Creates gRPC service client to use for establishing gRPC streams.

WARNING: creating a client more than once can result in a memory leak.
ChannelImplementation and related objects will stay in memory even after
the stream is closed and we do not have a handle to the client. Currently
impacting grpc-js@1.2.11 and several earlier versions.

@returns {object} protobuf API for IngestService