Elixir: start http server only for prometheus metrics - http

I have following code:
defmodule MyApp.Http do
use Application
require Logger
def start(_type, _args) do
import Supervisor.Spec, warn: false
MyApp.PlugPipelineInstrumenter.setup()
MyApp.MetricsExporter.setup()
opts = [strategy: :one_for_one, name: MyApp.Http.Supervisor]
Supervisor.start_link([], opts)
end
end
defmodule MyApp.MetricsExporter do
use Prometheus.PlugExporter
end
defmodule MyApp.PlugPipelineInstrumenter do
use Prometheus.PlugPipelineInstrumenter
end
But it does nothing. When I add:
plug MyApp.MetricsExporter
plug MyApp.PlugPipelineInstrumenter
I get compilation error: undefined function plug/1. I use elixir 1.10.3. What do I do wrong here?

I made a hex package called prometheus_sidecar that creates a ranch server dedicated to prometheus (so you could run it in any elixir application) and wires up prometheus_plugs for you.
It leverages erlang's application start lifecycle so there is no required configuration, besides adding it as a library to your application.
Let me know if you find it useful.

Related

How to import a module inside the Deno REPL?

Attempting to import a module in the Deno REPL results in the following error:
Uncaught SyntaxError: Cannot use import statement outside a module
at evaluate (rt/40_repl.js:60:36)
at replLoop (rt/40_repl.js:160:15)
I use the Node REPL to quickly test out code, almost on a daily basis. The ability to import external code without writing a script or dealing with temporary files is a huge convenience.
Why can't Deno use import statements outside of a module? Is it even possible to use external code in the Deno REPL?
Starting with v1.4.3, you can use top-level await in the REPL to dynamically import modules:
> const path = await import("https://deno.land/std#0.73.0/path/mod.ts")
> path.basename("/my/path/name")
"name"
If you also try to use import a from "a" in Node REPL, it will also throw the same error. Only require can be directly used to import modules in Node REPL.
For Deno, there is no built-in CommonJS loader. Therefore it does not even provide require for you to load stuff synchronously.
The technical reason of why static import cannot be used in REPL is that REPL is actually a script evaluation tool: instead of compiling what you write into an ES Module, they are treated as plain scripts and directly fed into the engine, in the way similar to <script> in the browser without turning on the type="module". (ES modules with static imports have the semantics of asynchronously loading dependencies and determining the "shape" of a module without even actually running it.)
To import modules in Deno REPL, you can use dynamic import(). Personally I sometimes do the following (loading is usually fast enough such that you will pretty much have mod value set before you continue using the mod in REPL):
$ deno
> let mod; import("./mod.ts").then(m => mod = m)
Promise { <pending> }
Check file:///[blah]/mod.ts
> mod
Module { a: 1, Symbol(Symbol.toStringTag): "Module" }

Http-Conduit frequent connection failures

I am writing application which will download some files by HTTP. Up to some point I was using following code snippet to download page body:
import network.HTTP
simpleHTTP (getRequest "http://www.haskell.org/") >>= getResponseBody
It was working fine but it could not establish connection by HTTPS protocol. So to fix this I have switched to HTTP-Conduit and now I am using following code:
simpleHttp' :: Manager -> String -> IO (C.Response LBS.ByteString)
simpleHttp' manager url = do
request <- parseUrl url
runResourceT $ httpLbs request manager
It can connect to HTTPS but new frustrating problem appeared. About every fifth connection fails with exception:
getpics.hs: FailedConnectionException "i.imgur.com" 80
I am convinced that this is HTTP-Conduit problem because network.HTTP was working fine on same set of pages (excluding https pages).
Have anybody met such problem and know solution or better (and simple because this is simple task which should not take more than few lines of code) alternative to Conduit library?
One simple alternative would be to use the curl package. It supports HTTP, HTTPS and a bunch of other alternative protocols, as well as many options to customize its behavior. The price is introducing an external dependency on libcurl, required to build the package.
Example:
import Network.Curl
main :: IO ()
main = do
let addr = "https://google.com/"
-- Explicit type annotation is required for calls to curlGetresponse_.
-- Use ByteString instead of String for higher performance:
r <- curlGetResponse_ addr [] :: IO (CurlResponse_ [(String,String)] String)
print $ respHeaders r
putStr $ respBody r
Update: I tried to replicate your problem, but everything works for me. Could you post a Short, Self Contained, Compilable, Example that demonstrates the problem? My code:
import Control.Monad
import qualified Data.Conduit as C
import qualified Data.ByteString.Lazy as LBS
import Network.HTTP.Conduit
simpleHttp'' :: String -> Manager -> C.ResourceT IO (Response LBS.ByteString)
simpleHttp'' url manager = do
request <- parseUrl url
httpLbs request manager
main :: IO ()
main = do
let url = "http://i.imgur.com/"
count = 100
rs <- withManager $ \m -> replicateM count (simpleHttp'' url m)
mapM_ (print . responseStatus) $ rs

Importing ping module in RestrictedPython script in Plone

I would like to check internet connexion from my plone site. I tried a ping in a python script
## Script (Python) "pwreset_action.cpy"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Reset a user's password
##parameters=randomstring, userid=None, password=None, password2=None
from Products.CMFCore.utils import getToolByName
from Products.PasswordResetTool.PasswordResetTool import InvalidRequestError, ExpiredRequestError
import ping, socket
status = "success"
pw_tool = getToolByName(context, 'portal_password_reset')
try:
pw_tool.resetPassword(userid, randomstring, password)
except ExpiredRequestError:
status = "expired"
except InvalidRequestError:
status = "invalid"
except RuntimeError:
status = "invalid"
context.plone_log("TRYING TO PING")
try :
ping.verbose_ping('www.google.com' , run=3)
context.plone_log("PING DONE")
except socket.error, e:
context.plone_log("PING FAILED")
return state.set(status=status)
I got these errors :
2012-07-20T11:37:08 INFO SignalHandler Caught signal SIGTERM
------
2012-07-20T11:37:08 INFO Z2 Shutting down fast
------
2012-07-20T11:37:08 INFO ZServer closing HTTP to new connections
------
2012-07-20T11:37:42 INFO ZServer HTTP server started at Fri Jul 20 11:37:42 2012
Hostname: 0.0.0.0
Port: 8080
------
2012-07-20T11:37:42 WARNING SecurityInfo Conflicting security declarations for "setText"
------
2012-07-20T11:37:42 WARNING SecurityInfo Class "ATTopic" had conflicting security declarations
------
2012-07-20T11:37:46 INFO plone.app.theming Patched Zope Management Interface to disable theming.
------
2012-07-20T11:37:48 INFO PloneFormGen Patching plone.app.portlets ColumnPortletManagerRenderer to not catch Retry exceptions
------
2012-07-20T11:37:48 INFO Zope Ready to handle requests
------
Python Scripts in Zope are sandboxed (via RestrictedPython, which means that any module imports have to be declared safe first. Adding modules to the declared-safe list is generally a Bad Idea unless you know what you are doing.
To declare a module as importable into Python Scripts, you'll need to create a python package, then add the following code to it so it is executed when Zope starts:
from Products.PythonScripts.Utility import allow_module
allow_module('ping')
This'll allow any import from that module (use with caution)!
It's better to allow only specific methods and classes from a module; use a ModuleSecurity declaration for that:
from AccessControl import ModuleSecurityInfo
ModuleSecurityInfo('ping').declarePublic('verbose_ping')
ModuleSecurityInfo('socket').declarePublic('error')
This is documented in the Security chapter of the Zope Developers Guide, specifically the section on module security assertions.
Note that it nearly always is a better idea to do all this work in a tightly constrained method in unrestricted code (e.g. a regular python package), then allow that method to be used from a python script instead.
It won't work.
You CANNOT import arbitrary Python modules in RestrictedPython scripts, as in the answer you were told yesterday:
https://stackoverflow.com/a/11568316/315168
If you need to use arbitraty Python modules you need to write your own Plone add-on for that and use a BrowserView for the purpose. RestrictedPython through-the-web-browser development is not enough:
http://collective-docs.readthedocs.org/en/latest/getstarted/index.html

Werkzeug and WebApp2 - debug display and console not working

I want to use Werkzeug as a local development server and cannot get the DebugApplication middle ware to work as documented - Werkzeug Debugging. Whats wrong here?
import webapp2
from system import config
from werkzeug.debug import DebuggedApplication
from werkzeug.serving import run_simple
application = webapp2.WSGIApplication(routes=config.routes, debug=False, config=config.options)
debugged_application = DebuggedApplication(application)
def main():
run_simple('localhost', 4000, debugged_application, use_reloader=True, use_debugger=True, threaded=True)
if __name__ == '__main__':
main()
I think that DebuggedApplication middleware tries to achieve the same as use_debugger=True, so no need to use both. The problem is that webapp2.WSGIApplication adds its own error handling before it goes through the debugger middleware, thus forbidding werkzeug debugger to see the actual exception.
My solution to this is to extend base WSGIApplication provided by webapp2 to re-raise the original exception. It works with python 2.7, and will pass the exception if and only if debug flag has been set to True in Application constructor.
class Application(webapp2.WSGIApplication):
def _internal_error(self, exception):
if self.debug:
raise
return super(Application, self)._internal_error(exception)
Not sure this is the cleanest possible way to do it, but it works for me.

Ruby : How to make a HttpRequest

I'm still new in ruby, please help.
I'm trying to make a http request in my standalone ruby script.
#!/usr/bin/ruby
require 'rubygems'
require 'net/http'
...
class someClass
...
def get_ruby_doc
request = HttpRequest.new(:get, 'http://www.ruby-doc.org/')
response = request.perform!
puts response.succeeded?
puts "yeah"
end
...
when I run the script, I get this error:
Uncaught exception: uninitialized constant someClass::HttpRequest
Can you please let me know what did I miss? Thanks.
I also try to do the same in rails console, same error.
You could try using rest-client
gem install rest-client
http://rubydoc.info/gems/rest-client/1.6.7/frames

Resources