elastic APM and NestJS does not differentiate graphql queries - graphql

I am adding the elastic-apm-node package to our nestjs backend. I am using the graphql feature of nestjs. Because of this, all requests are merged together as /graphql in elastic.
Is this how it is supposed to be? I imagined that since apollo-server-express is supported by elastic-apm-node, which is also used by nestjs, it should be displaying it better. Am I missing something?
UPDATE
The graphql feature is set up using the docs for nestjs: https://docs.nestjs.com/graphql/quick-start it is basically their recommended setup I am using.

It's hard to say without knowing exactly how you're using NestJS and GraphQL together, and without knowing which parts of Apollo Server that NestJS itself uses. Seeing a small sample of what I am using the graphql feature of nestjs means would be useful.
Here's a few datapoints that might help you narrow things down. Also, opening an issue in the Agent repository or a question in their forums might get more of the right eyes on this.
The Elastic APM instrumentation for Apollo Server works by wrapping the runHttpQuery function of the apollo-server-core module, and marking the transaction with trans._graphqlRoute.
When the agent sees this _graphqlRoute property, it runs some code that will set a default name for the transaction
if (trans._graphqlRoute) {
var name = queries.length > 0 ? queries.join(', ') : 'Unknown GraphQL query'
if (trans.req) var path = getPathFromRequest(trans.req, true)
var defaultName = name
defaultName = path ? defaultName + ' (' + path + ')' : defaultName
defaultName = operationName ? operationName + ' ' + defaultName : defaultName
trans.setDefaultName(defaultName)
trans.type = 'graphql'
}
In your application, either the _graphqlRoute property isn't getting set, or the renaming code above is doing something weird, or something about NestJS comes along and renames the transaction after it's been named with the above code.
Knowing more specifically what you're doing would help folks narrow in on your problems.

Related

Get raw parameters from react router

Is there any way to get the raw (without URL decoding) parameters from the react router V6.3 without making my own windows.location.href parser?
Example:
path: /companies/Samsung%2CInc,Lenovo%2CInc
const params = useParams();
const companies = params.companies?.split(',');
Expected:
[
'Samsung%2CInc',
'Lenovo%2CInc',
]
Getting:
[
'Samsung',
'Inc',
'Lenovo',
'Inc',
]
Any recommendations here?
PS. React Router does URL Decode, which is what I want to avoid. I found related issue on lib's issues board.
Apparently it is not possible at this moment. The URL decoding is coming from the matching part, which is a way deeper than useParams method.
I created a workaround gist that uses already parsed params and obtaining their RAW (URL encoded) version from the location.pathname
It works for my case, but I'm sure it could be optimized.

Using `createMockClient` for testing non react code?

I have mixed application that uses Apollo for both React and non-react code.
However, I can’t find documentation or code examples around testing non-react code with the apollo client,not using MockedProvider. I did, however, notice that apollo exports a mock client from the testing directory.
import { createMockClient } from '#apollo/client/testing';
I haven’t found any documentation about this API and am wondering if it’s intended to be used publicly and, if not, what the supported approach is for this.
The reason I need this is simple: When using Next.js’ SSR and/or SSG features data fetching and actual data rendering are split into separate functions.
So the fetching code is not using React, but Node.js to fetch data.
Therefore I use apolloClient.query to fetch the data I need.
When trying to wrap a react component around that fetching code in a test an wrap MockedProvider around that the apolloClient’s query method always returns undefined for mocked queries - so it seems this only works for the useQuery hook?
Do you have any idea how to mock the client in non-react code?
Thank you for your support in advance. If you need any further information from me feel free to ask.
Regards,
Horstcredible
I was in a similar position where I wanted to use a MockedProvider and mock the client class, rather than use useQuery as documented here: https://www.apollographql.com/docs/react/development-testing/testing/
Though it doesn't seem to be documented, createMockClient from '#apollo/client/testing' can be passed the same mocks as MockedProvider to mock without useQuery. These examples assume you have a MockedProvider:
export const mockGetAssetById = async (id: Number): Promise<any> => {
const client = createMockClient(mocks, GetAsset)
const data = await client.query({
query: GetAsset,
variables: id,
})
return data
}
Accomplishes the same as:
const { data } = useQuery(
GetAsset,
{ variables: { id } }
)

Applying a dependency to a service in icinga2

We are using icinga2 for monitoring. We have a lot service checks which are applied dynamically through apply rules. Additionally, these are services applied to a hashmap of database instances which are on various hosts. The long and the short of it is that our service names are determined dynamically so one might be, for example HOST!DBNAME-svcvheck.
So the scenario is that most of these services depend on a database is up, e.g., `HOST!DBNAME-tnsping". Unfortunately, the documentation examples are fairly simple and don't include dynamically creating a parent service reference. What I think I want to do is something like this:
apply Dependency "db-connectivity" to Service {
parent_service_name = "$host.name$!$service.vars.envname$-tnsping"
# also tried variants of this, e.g.
# parent_service_name = host.name + "!" + service.vars.envname + "-tnsping"
child_service_name = service.name
child_host_name = host.name
disable_checks = true
assign where "oracle-db-svc" in service.templates
}
The host doesn't really matter in my case because the dependencies are only the services but the child_host_name is a required field.
No matter what I do I can't seem to get it to recognize the parent service. For example:
Error: Dependency 'scan-szepdb041x.myhost.org!UAT2-beqfilelast!db-connectivity' references a parent host/service which doesn't exist.
The rules for referencing other object variables while applying a Dependency seem a bit different from applying a Service.
Does anyone have any ideas or examples of dynamically apply service dependencies to services which were generated dynamically?
you probably have to loop over existing hosts and see if they match. Then you define dependency inside of a loop.
I had a similar example for dynamically generating disk checks. If i find it, i'll post it here in a few days.
Not sure if that is possible with dependencies, but I'll see.
edit: see if somethig like that will be enough to get you started:
for (server in get_objects(Host)) {
if (match("somename*", server.name)) {
apply Dependency "db-connectivity" + server.name to Service use (server) {
parent_service_name = server.name + service.vars.envvname + "-tnsping"
child_service_name = service.name
child_host_name = host.name
disable_checks = true
assign where "oracle-db-svc" in service.templates
}
}
}

how can I get ALL records from route53?

how can I get ALL records from route53?
referring code snippet here, which seemed to work for someone, however not clear to me: https://github.com/aws/aws-sdk-ruby/issues/620
Trying to get all (I have about ~7000 records) via resource record sets but can't seem to get the pagination to work with list_resource_record_sets. Here's what I have:
route53 = Aws::Route53::Client.new
response = route53.list_resource_record_sets({
start_record_name: fqdn(name),
start_record_type: type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
})
response.last_page?
response = response.next_page until response.last_page?
I verified I'm hooked into right region, I see the record I'm trying to get (so I can delete later) in aws console, but can't seem to get it through the api. I used this: https://github.com/aws/aws-sdk-ruby/issues/620 as a starting point.
Any ideas on what I'm doing wrong? Or is there an easier way, perhaps another method in the api I'm not finding, for me to get just the record I need given the hosted_zone_id, type and name?
The issue you linked is for the Ruby AWS SDK v2, but the latest is v3. It also looks like things may have changed around a bit since 2014, as I'm not seeing the #next_page or #last_page? methods in the v2 API or the v3 API.
Consider using the #next_record_name and #next_record_type from the response when #is_truncated is true. That's more consistent with how other paginations work in the Ruby AWS SDK, such as with DynamoDB scans for example.
Something like the following should work (though I don't have an AWS account with records to test it out):
route53 = Aws::Route53::Client.new
hosted_zone = ? # Required field according to the API docs
next_name = fqdn(name)
next_type = type
loop do
response = route53.list_resource_record_sets(
hosted_zone_id: hosted_zone,
start_record_name: next_name,
start_record_type: next_type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
)
records = response.resource_record_sets
# Break here if you find the record you want
# Also break if we've run out of pages
break unless response.is_truncated
next_name = response.next_record_name
next_type = response.next_record_type
end

Google Spreadsheet API - returns remote 500 error

Has anyone battled 500 errors with the Google spreadsheet API for google domains?
I have copied the code in this post (2-legged OAuth): http://code.google.com/p/google-gdata/source/browse/trunk/clients/cs/samples/OAuth/Program.cs, substituted in my domain;s API id and secret and my own credentials, and it works.
So it appears my domain setup is fine (at least for the contacts/calendar apis).
However swapping the code out for a new Spreadsheet service / query instead, it reverts to type: remote server returned an internal server error (500).
var ssq = new SpreadsheetQuery();
ssq.Uri = new OAuthUri("https://spreadsheets.google.com/feeds/spreadsheets/private/full", "me", "mydomain.com");
ssq.OAuthRequestorId = "me#mydomain.com"; // can do this instead of using OAuthUri for queries
var feed = ssservice.Query(ssq); //boom 500
Console.WriteLine("ss:" + feed.Entries.Count);
I are befuddled
I had to make sure to use the "correct" class:
not
//using SpreadsheetQuery = Google.GData.Spreadsheets.SpreadsheetQuery;
but
using SpreadsheetQuery = Google.GData.Documents.SpreadsheetQuery;
stinky-malinky
Seems you need the gdocs api to query for spreadsheets, but the spreadsheet api to query inside of a spreadsheet but nowhere on the internet until now will you find this undeniably important tit-bit. Google sucks hard on that one.

Resources