Dynamically create Prometheus gauge names - javascript

I am using prom-client in my node app to send stats to our prometheus instance. I am firing off a set of requests to determine if the app is up or not. With that, I want to dynamically set the name of the gauge depending on what app is being pinged.
apps.map(app => {
request(app.url, (error, response, body) => {
let name = app.name
const gauge = new client.Gauge({
name: `${app.name}`,
help: `${app.name}`,
register,
})
if (error) {
console.log(`${app.name} ERROR!`, error)
gauge.set(0)
}
if (response && response.statusCode == 200) {
console.log(`${app.name} is up!`, response.statusCode)
gauge.set(0)
}
gateway.pushAdd({ jobName: 'app_up_down', register })
})
})
Setting the gauge name to ${app.name} is throwing an Invalid Name error. The only way I could get it to stop throwing that error was to hardcode the name which doesn't work for me. Does anyone know if there is a way to dynamically set this, or is this an issue with the package?

This looks like blackbox monitoring, for which the blackbox exporter is probably a better tool.
The particular error you're getting is likely as the name contains invalid characters, a label would be a better choice. In addition this is not a good use of the pushgateway.

Related

How to web-scrape the required result using Nodejs?

Hi I'm a beginner in scrapping and jQuery. I'm doing scraping using Nodejs ,learning scraping from this site. The dependencies I'm using with it are: cheerio, request-promise and fs. I have not issue in setting up the environment for it.
I tried to scrap the basic text data from this site. But I'm not be able to do so. I tried to change classes but the result the same.
I want to get and print it in this.
But I'm not be able to add the City and Property type sections(image above) in it by scraping.
What change should I make in the logic to get the above image result?
Here's my code:
const request = require("request-promise");
const cheerio = require("cheerio");
request(
"https://www.makaan.com/price-trends/property-rates-for-buy-in-hyderabad?page=2",
(error, response, html) => {
if (!error && response.statusCode == 200) {
const $ = cheerio.load(html);
const datarow = $(".tbl td, .tbl th,");
const output = datarow.find(".ta-1").text();
$(".ta-l.link-td-txt, .ta-, ").each((i, data) => {
const item = $(data).text();
console.log(item);
});
}
}
);
My current result: .
Issues With the current result:
1 : Not according to the above format.
2 : Name of headers of columns at first line are missing.
3 : Commas are missing between the fields.
Tried: I tried to search on google and YouTube to try to solve it. I also learn JQuery(basics) to solve it but I'm not getting at it.
Expecting: What should I do to get the result as mentioned above. What was wrong in my logic?

Algolia + Laravel backend API + nuxtJS

I have a Laravel 8 backend API and a completely separate NuxtJS frontend. I have integrated Algolia into the backend API. I have a nice adapter and service and I can search my index.
Now, I am not interested in using scout because I don't like what it is doing and how it works and that's not the problem so I would like to leave it out of the discussion.
So I've made search work on the frontend with Vuetify autocomplete but I decided to use VueInstant search as this is supposed to save me some work when it comes to integrating query suggestions.
Before I can even get query suggestion I need to get the basic search working with Vue Instant Search.
GOAL
I want to have a VueInstant Search with the backend search client.
WHAT I HAVE SO FAR
THAT IS WITHOUT QUERY SUGGESTIONS JUST THE BASIC SEARCH WITH VUEINSTANT SEARCH
I have backend code that searches my index. I have the frontend code that creates a new connection to my backend (don't worry about how it looks like I just need to get this to work first and then I will invest the time to refactor it):
customSearchClient () {
const that = this
return {
search(requests) {
return that.fetchContainers({ criteria: { query: 'super' }, updateStore: false }).then(response => {
// console.log({ response }, typeof response)
// return response.data.hits
return { results: response.data }
// return response
// return response.data.hits
})
}
}
}
And this is my code for the form:
<ais-instant-search index-name="containers-index" :search-client="customSearchClient()" >
<ais-search-box />
<ais-hits>
<template slot="item" slot-scope="{ item }">
<h1><ais-highlight :hit="item" attribute="name" /></h1>
<p><ais-highlight :hit="item" attribute="description" /></p>
</template>
</ais-hits>
</ais-instant-search>
PROBLEMS
I can get the searchbox to show and query if I remove ais-hits tags. As soon as I add them I get weird errors depending on how I format my response from the backend. I just try to pass it as it is.
I went through some debugging and tried to wrap this into various wrappers as they seem to be missing but eventually it always breaks, for example:
algoliasearch.helper.js?ea40:1334 Uncaught (in promise) TypeError: content.results.slice is not a function at AlgoliaSearchHelper._dispatchAlgoliaResponse (algoliasearch.helper.js?ea40:1334:1)
And that is the Algolia code that breaks.
this._currentNbQueries -= (queryId - this._lastQueryIdReceived);
this._lastQueryIdReceived = queryId;
if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');
var results = content.results.slice();
states.forEach(function(s) {
var state = s.state;
var queriesCount = s.queriesCount;
var helper = s.helper;
var specificResults = results.splice(0, queriesCount);
var formattedResponse = helper.lastResults = new SearchResults(state, specificResults);
SUMAMRY
The ideal solution would be to not to use this InstantSearch thing but I have no clue how to manage more than one index on the server side.
Or am I completely wrong about all of that? Anyone can advise?

Extract domain from URL in Typescript app using new URL() API

I've got a URL containing a lot of params, and I need to extract just the domain name in order to perform a check on that domain name only. The app I'm coding in is a typescript application, it treats URL as a type instead of a string.
Originally I was writing code that was along these lines:
const hostnameExample = "http://www.foo.bar.com?search=www.google.com"
//example of URL I'm trying to get just a domain of
const cleanupParams2 = (url: string) => {
let domain = new URL(url);
return domain.hostname;
}
export const isExternalLink = (hostname?: string, goodDomains: string[] = []) => {
return goodDomains.every((domain) => {
if (hostname && !hostname.startsWith("#")) {
return cleanupParams2(hostname).indexOf(domain) < 0;
}
});
};
I'm getting an error message in my unit test scripts, I really don't even understand the error messages I'm getting or why I'm getting them to be honest.
expect(jest.fn()).not.toHaveBeenCalled()
Expected number of calls: 0
Received number of calls: 14
1: "Invalid URL: www.foo.bar.comĀ·
What would be wrong with the source code that it would be throwing an error, and/or what in the world is that error? It's being thrown from basically any file that appears to directly or indirectly be using the isExternalLink function. I know I'm not showing all of the code here, but this is the problematic code basically.

Can we test if element text includes text_ A or text_B with cypress?

Just wondering if there is a way to test that an element contains text_A or text_B with cypress. For example, I have an element that is filled with the error returned from an API request and I want to check whether the error message includes text_A or text_B. Tried the following code but it works only if text_A is present and fails when text_B is returned.I don't get any error for invalid syntax from cypress, any help would be appreciated.
cy.get('body').then((body) => {
if (body.find('#request-error').length > 0) {
cy.get('#request-error').then((el)=> {
assert.include(el.text(), ('text_A' || 'text_B'));
});
} else {
// DO SOMETHING ELSE
}
});
Essentially you have an array of possible error messages, so you can test if the element's text exists within that array.
expect(['text_A', 'text_B']).to.include(el.text())
Another option that reads better would be to use .oneOf
expect(el.text()).to.be.oneOf(['text_A', 'text_B']);
https://docs.cypress.io/guides/references/assertions.html#BDD-Assertions
I am late but you can do it with satisfy:
cy.get('.text-element').invoke('text').then(text => {
expect(text).to.satisfy((mText: string) => possibleMatchesArray.includes(mText));
});

How do I post an HTML class into a mongoDB collection using express/mongoose and client-side JS?

First off my programming knowledge is entirely on the front-end, but I'm experimenting with node, express, mongoose, and mongodb. I'm using someone else's template to try and build an app the right way, but I'm lost when connecting the dots. I have the following jade:
form(method='post', action="/post/comment/" + post.id)
textarea(name='text')
input(type='submit', value='Save')
Combined with this from the routes/posts.js file
app.post("/post/comment/:id", loggedIn, function (req, res, next) {
var id = req.param('id');
var text = req.param('text');
var author = req.session.user;
Comment.create({
post: id
, text: text
, author: author
}, function (err, comment) {
if (err) return next(err);
res.redirect("/post/" + id);
});
});
and this is models/comment.js :
var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
var createdDate = require('../plugins/createdDate');
var schema = mongoose.Schema({
text: { type: String, trim: true, validate: validateText }
, post: { type: ObjectId, index: true }
, author: String
})
function validateText (str) {
return str.length < 250;
}
schema.plugin(createdDate);
module.exports = mongoose.model('Comment', schema);
Now this works fine, for submitting a comment and saving it in the DB. Problem is, is that I don't want to save a comment, but HTML after a function has manipulated it. So I tried:
var everything = $('.whatever').html();
$.post("/post/comment/:id", everything,
function(){
console.log('html saved!')
}
)
But I got a POST http://localhost:3000/post/comment/:id 500 (Internal Server Error) Now I'm aware that I probably don't have the id variable so I tried pasting in the number that is in the url, and that seemed to go through without error, but than didn't show up in the DB. I'm aware that this may not be a specific question, and that I may be going about this entirely wrong but any general direction would be much appreciated. Thanks.
You seem to have a number of problems here. Try taking a look at the following:
Your router is set to receive posts to "/post/comment/:id", but your post in the last code block is posting to "/post/comments/:id", where comments is plural. This will likely result in a 404. (Check the networks tab of your browser javascript console. It may be silently failing without you realizing it).
Your 500 error is likely coming from the fact that you directly posted ":id", instead of an actual identifier. Many node apps will have an app.param() block set up to validate these parameters, and your friend's template is likely breaking when it doesn't get a number it expects.
The data that you post must match the schema of the model you're saving it to. Any keys that aren't named in the schema will be stripped prior to saving, and in your case, if no keys match, it will just be a default comment instance, and won't save at all.
Hope that helps!

Categories

Resources