shinyscorpion / wobserver Goto Github PK
View Code? Open in Web Editor NEWWeb based metrics, monitoring, and observer
License: MIT License
Web based metrics, monitoring, and observer
License: MIT License
Can we run it stand-alone and monitor other node (if that node doesn't have wobserver installed)?
I'm using wobserver in a Phoenix-Application (configured as plug).
Locally everything works just fine but when I run the application on the production server, I have the following problem:
proxy_pass localhost:4000
to hit the application.https://..../metrics
but then can't connect the websocket because it is still a ws
instead of wss
transport.It seems there is no way yet to configure wss
, right?
I'm giving this a shot in one of our elixir applications, and it works great in standalone mode and plug mode when running locally. But when we deploy to stage and prod, we use distillery releases. I think the distillery release breaks the way wobserver serves the index.html, because the file is not included in the release. This is the error we get:
Elixir.File.Error: could not read file stats "deps/wobserver/assets/index.html": no such file or directory
File "lib/file.ex", line 289, in File.stat!/2
File "lib/plug/adapters/cowboy/conn.ex", line 38, in Plug.Adapters.Cowboy.Conn.send_file/6
File "lib/plug/conn.ex", line 429, in Plug.Conn.send_file/5
File "lib/wobserver/web/router/static.ex", line 1, in Wobserver.Web.Router.Static.plug_builder_call/2
File "lib/plug/router/utils.ex", line 91, in Plug.Router.Utils.forward/4
File "lib/wobserver/web/router.ex", line 1, in Wobserver.Web.Router.plug_builder_call/2
File "lib/phoenix/router/route.ex", line 154, in Phoenix.Router.Route.forward/4
File "lib/phoenix/router.ex", line 261, in API.Router.dispatch/2
Any chance you could give distillery a shot to see how we could get around this?
Instead of having wobserver run its own cowboy instance with (apparently) no authentication, I'd like to be able to run wobserver from inside an app's existing administrator panel.
The main barrier to this is wobserver's websockets, which can be replaced with EventSource
.
The &Wobserver.Port.info/1
sometimes crashes the application by having an :undefined
port.
Fix by adding a case for :undefined
and filtering those from the resulting list in &Wobserver.Port.list/0
.
When freshly mix deps.compile wobserver
this as a dependency, the compilation gives these warnings, and indeed I'm not seeing a Wobserver.Assets
module in the project?
==> wobserver
Compiling 4 files (.ex)
warning: function Wobserver.Assets.html/0 is undefined (module Wobserver.Assets is not available)
lib/wobserver/web/router/static.ex:21
warning: function Wobserver.Assets.css/0 is undefined (module Wobserver.Assets is not available)
lib/wobserver/web/router/static.ex:32
warning: function Wobserver.Assets.js/0 is undefined (module Wobserver.Assets is not available)
lib/wobserver/web/router/static.ex:38
warning: function Wobserver.Assets.license/0 is undefined (module Wobserver.Assets is not available)
lib/wobserver/web/router/static.ex:43
Make includes generic.
In following instructions and looking through the source, it appears that the discovery of other nodes is limited to trying to connect to another Wobserver instance?
I was hoping it might be like Observer where I can have it display the information of other connected/clustered nodes. Is that a possibility? Or does Wobserver have to be installed on every node in the cluster that we might want to inspect?
Because of dependency issues, I created a small node with only Wobserver installed that could join an existing cluster and from there review/monitor all the nodes in the cluster.
Is this currently possible? If not, is it planned for the future?
Table Viewer tab doesn't work in release, all the other tabs System, Load Chart, etc works
Table Viewer tab works locally, it is for security ??
Increase the interval for the keep alive. Currently bugged and firing every 1-20 ms.
Plug mode does not redirect /<url>
to /<url>/
, so assets can not be loaded.
Should add redirect.
I have wobserver working in my application, However I want it to only run when I need it.
My solution was to remove :wobserver
from the applications list in mix.exs. When I need wobserver I start an iex session on the node and call Application.ensure_all_started(:wobserver)
. However doing this does and the visiting the wobserver port and I get the error that the site cannot be reached. Apart from removing wobserver from my applications list I have made no change to the setup that was working.
The sorting method in "table viewer" tab is alphabetic, therefore the sort by size is wrong because there are sizes with different units.
I am seeing the following error show up in the logs:
Ranch acceptor received unexpected message: {:system, {#PID<0.982.0>, #Reference<0.736632836.3709599745.155908>},
:get_status}
Which is logged from this line:
https://github.com/ninenines/ranch/blob/1.3.2/src/ranch_acceptor.erl#L53
It seems to be coming from this line
https://github.com/shinyscorpion/wobserver/blob/master/lib/wobserver/util/process.ex#L224
Searching my dependencies it looks like there are only 2 calls to :sys.get_status/2
, one from within ranch itself and another from this library.
Locally this works without issue. When hosted using SSL, I have Phoenix forcing SSL, and it seems to break the websocket connection.
I get "Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS."
I'm using Phoenix channels, and my application doesn't have any socket issues on other parts. Maybe I'm doing something wrong?
Title
I am trying to use the project, I have a server running phoenix and wobserver.
I have added a list of nodes I would like to connect but I keep getting the "Connection lost" error.
The two machine are in the same subnetwork without any firewall.
I am looking for tips, but also it would be nice to have a little more infos either on the logs or in the webpage on what's going on.
Thanks
We're on a fork of an earlier version of wobserver, but I thought I'd bring this issue up in the core repo as an issue.
We've been seeing consistent timeouts from this parallel_map
call: https://github.com/shinyscorpion/wobserver/blob/master/lib/wobserver/util/application.ex#L97. We've also noticed that the BEAM load spikes pretty hard whenever we navigate to the wobserver page for one of our apps that has many processes (~100 Ranch acceptors under a single supervisor). I'm guessing this has to do with all of the core :erlang
calls getting process info
Here's a stacktrace from our version:
14:40:38.116 [error] Task #PID<0.1046.0> started from #PID<0.1033.0> terminating
** (stop) exited in: Task.await(%Task{owner: #PID<0.1046.0>, pid: #PID<0.1056.0>, ref: #Reference<0.0.1.97714>}, 5000)
** (EXIT) time out
(elixir) lib/task.ex:416: Task.await/2
(elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
(wobserver) lib/wobserver/util/application.ex:101: Wobserver.Util.Application.structure_pid/1
(elixir) lib/task/supervised.ex:85: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:36: Task.Supervised.reply/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Function: #Function<1.105204156/0 in Wobserver.Util.Helper.parallel_map/2>
Args: []
14:40:38.116 [error] Ranch protocol #PID<0.1024.0> (:cowboy_protocol) of listener TaskRunner.Endpoint.HTTP terminated
** (exit) exited in: Task.await(%Task{owner: #PID<0.1046.0>, pid: #PID<0.1056.0>, ref: #Reference<0.0.1.97714>}, 5000)
** (EXIT) time out
When this time out happens the entire wobserver page fails to load which has made it unusable in app without changes.
I'd suggest using a pool to limit concurrency or chunking the processes
When running through the manual instructions step on the readme the gulp build
step gives the gulp: command not found
because the step as typed in is trying to call a global gulp
command although the project installs a local gulp
that has to be called via ./node_modules/.bin/gulp
, thus the command should probably be ./node_modules/.bin/gulp build
.
I opened PR months ago, do you need some help? What can we do it keep it moving? Should we start forking and create a new hex package?
Hello,
I want to protect everything below /wobserver from unauthorized users. So far I have tried
In both cases I hit the same dead end: the required cookie/header was not being sent at all below /wobserver/api. I suspect this is an idiosyncrasy of the javascript "fetch" API that is being used.
I found references to an undocumented security feature which, as I understand it, is needed for inter-node communication (and I only have one node for the forseeable future). Will this feature also authorize users? Otherwise, is there a workaround for the problem with cookies and certain headers not being sent?
Currently we can put a plug in front of the router for wobserver to block access for an unauthorized user, but currently there is no way to do the same for the socket without hijacking between them. The router should probably take a callback function that we can supply that gets passed the plug's conn and returns either a token (binary? easily generate-able securely via phoenix for example by the user) or an error. If a token is returned then they are allowed to access the wobserver, if an error then it should just 404 or whatever. The token should also be passed to the socket via the web page (or cookie) and the socket should verify that it is an allowed token (perhaps by passing it back to yet another user function, these could be specified in the config or on the injection sites), and if it is verified and allowed then the socket connection establishes else it is dropped.
Currently even if blocking the /wobserver
route the outside can still access the websocket directly to query.
The most simple solution would probably just be adding 2 callback functions to the config, and if they exist use them, else allow all as it does now.
Custom mix tasks by Elixir suggestions should be prefixed with the project name, so it should be mix wobserver.build
. A simple change and figured I should suggest it before the project gets too far along. :-)
The reason is though that if multiple libraries include mix tasks, because your task 'is' imported into the projects that depend on this library, then they can conflict or become uncallable or even override what is expected from another library.
If you are wanting to define a new mix task that is not imported into the users project that includes this library then you should use a mix alias instead. An example (just add this to the bottom of your mix.exs
file while adding a aliases: aliases()
to your project
list):
defp aliases do
[
build: &WobServer.Builder.build/1,
]
end
This example would add a new task of the name build
that is exposed only to this project (and not projects that depend on this project), this task will call the WobServer.Builder.build/1
function, just like your task gets called in its run/1
. :-)
Aliases have a lot of other features (see above link), including calling tasks before or after others, you can, say, override 'compile' so it always calls 'build' first and then the normal 'compile' (that way you do not need to distribute your Assets file but instead it can be built on-the-fly when the dependency is compiled, I'm 'pretty' sure dependency building calls the compile
alias in mix, but uncertain, would want to check...).
:-)
This is in my config.exs
file:
config :wobserver,
mode: :plug,
remote_url_prefix: "/wobserver",
security: BorsNG.WobserverSecurity
This is my authenticate function:
defmodule BorsNG.WobserverSecurity do
@spec authenticate(Conn.t) :: Conn.t
def authenticate(conn) do
raise "HERE"
end
end
It doesn't reach the raise "HERE"
line when I open the wobserver page.
This is because the module attributes are evaluated at build-time, which uses the files in "wobserver"'s configuration, not in the dependent modules.
The ability to mouse over a y-coordinate in the graph and see the numbers is useless when the graph moves before anybody can read it.
A disconnect does not alert or reconnect socket.
Improve connection loss handling by:
Hi!
I was inspecting the state of my process that contained some content from a blog post, when suddenly I saw:
The state of the process is interpreted directly in the html, which could lead to a possible code injection problem. If I had some script
tags in it, it would have been evaluated, god knows what could have happened.
I'm using version 0.1.7 of wobserver.
I can't issue a PR right now with my sucky internet, but if you want to correct the misbehavior, the code involved is around here.
I might sound rude, but I like this software, I'm not blaming anyone 🤗
Source code for the application is https://github.com/mgwidmann/slack_coder
I've been trying to figure this out with no luck on what is happening.
Heres the logs from Heroku, as you can see Heroku picks up on the GET /wobserver/ws
call to make the socket connect but Phoenix never logs it out anywhere (typically it doesn't log anything until the join). The browser gets returned back a 204 No Content.
### First, heres me hitting the observer
2017-05-12T02:28:41.645622+00:00 heroku[router]: at=info method=GET path="/wobserver/" host=slack-coder.herokuapp.com request_id=34a800f3-ae02-4271-b348-8718b55387ac fwd="173.79.136.174" dyno=web.1 connect=1ms service=1ms status=200 bytes=1167 protocol=https
2017-05-12T02:28:41.706605+00:00 heroku[router]: at=info method=GET path="/wobserver/app.js" host=slack-coder.herokuapp.com request_id=7cb447de-dccd-4348-b385-b64ff3d6012b fwd="173.79.136.174" dyno=web.1 connect=0ms service=7ms status=200 bytes=295092 protocol=https
2017-05-12T02:28:41.675036+00:00 heroku[router]: at=info method=GET path="/wobserver/main.css" host=slack-coder.herokuapp.com request_id=c6968364-00ab-4236-af54-9395d1a1c00a fwd="173.79.136.174" dyno=web.1 connect=0ms service=2ms status=200 bytes=39690 protocol=https
2017-05-12T02:28:41.644613+00:00 app[web.1]: 02:28:41.644 request_id=34a800f3-ae02-4271-b348-8718b55387ac [info] GET /wobserver/
2017-05-12T02:28:41.644627+00:00 app[web.1]: 02:28:41.644 request_id=34a800f3-ae02-4271-b348-8718b55387ac [info] Sent 200 in 160µs
2017-05-12T02:28:41.673737+00:00 app[web.1]: 02:28:41.672 request_id=c6968364-00ab-4236-af54-9395d1a1c00a [info] GET /wobserver/main.css
2017-05-12T02:28:41.673780+00:00 app[web.1]: 02:28:41.672 request_id=c6968364-00ab-4236-af54-9395d1a1c00a [info] Sent 200 in 78µs
2017-05-12T02:28:41.698442+00:00 app[web.1]: 02:28:41.697 request_id=7cb447de-dccd-4348-b385-b64ff3d6012b [info] GET /wobserver/app.js
2017-05-12T02:28:41.698447+00:00 app[web.1]: 02:28:41.698 request_id=7cb447de-dccd-4348-b385-b64ff3d6012b [info] Sent 200 in 55µs
2017-05-12T02:28:41.861420+00:00 heroku[router]: at=info method=GET path="/wobserver/ws" host=slack-coder.herokuapp.com request_id=8d3b5cf2-8cd2-48b2-9731-d9c375f48ae4 fwd="173.79.136.174" dyno=web.1 connect=0ms service=1ms status=204 bytes=99 protocol=https
### Heres me hitting my index route path which has a successfully implemented phoenix socket on it... Odd it does not have a heroku router GET call...
2017-05-12T02:29:13.284211+00:00 heroku[router]: at=info method=GET path="/" host=slack-coder.herokuapp.com request_id=e338d64f-50e5-40a0-b37e-57681bef7fd3 fwd="173.79.136.174" dyno=web.1 connect=0ms service=6ms status=200 bytes=12101 protocol=https
2017-05-12T02:29:13.315163+00:00 heroku[router]: at=info method=GET path="/css/app-f60f3ae0a7de39b988f6262c7c365a52.css?vsn=d" host=slack-coder.herokuapp.com request_id=dc3dfdc4-d52c-4923-97b8-d5e3045f1509 fwd="173.79.136.174" dyno=web.1 connect=0ms service=1ms status=200 bytes=1568 protocol=https
2017-05-12T02:29:13.278441+00:00 app[web.1]: 02:29:13.277 request_id=e338d64f-50e5-40a0-b37e-57681bef7fd3 [info] GET /
2017-05-12T02:29:13.282977+00:00 app[web.1]: 02:29:13.282 request_id=e338d64f-50e5-40a0-b37e-57681bef7fd3 [info] Sent 200 in 4ms
2017-05-12T02:29:13.469617+00:00 heroku[router]: at=info method=GET path="/images/code-climate-grey-eb25b8d23eac8ebfba0bbdcfbc5f5cbb.svg?vsn=d" host=slack-coder.herokuapp.com request_id=55bad725-b6b5-4b52-bee6-482f81b6ae06 fwd="173.79.136.174" dyno=web.1 connect=0ms service=2ms status=200 bytes=870 protocol=https
2017-05-12T02:29:13.339947+00:00 heroku[router]: at=info method=GET path="/js/app-9c01173be1eb302965bc17dfc8c823cb.js?vsn=d" host=slack-coder.herokuapp.com request_id=a9c2a67a-b9bc-420f-9b35-7bc489a622ce fwd="173.79.136.174" dyno=web.1 connect=0ms service=5ms status=200 bytes=102833 protocol=https
2017-05-12T02:29:13.895743+00:00 app[web.1]: 02:29:13.895 [info] JOIN prs:all to SlackCoder.PRChannel
2017-05-12T02:29:13.895754+00:00 app[web.1]: Transport: Phoenix.Transports.WebSocket
2017-05-12T02:29:13.895755+00:00 app[web.1]: Parameters: %{"github" => "mgwidmann"}
2017-05-12T02:29:13.896252+00:00 app[web.1]: 02:29:13.896 [info] Replied prs:all :ok
It seems the backup JSON API is also being blocked because its running on https and its using http only.
There is a higher than expected scheduler usage, when using websockets.
Look into whether this is just websocket related or something in the communication between wobserver and javascript interface.
Was wondering how to configure the nodes section when you have like 3 nodes behind a load balancer which you can't directly access though they can connect with each other off-course. Was expecting that if you configure the nodes you can see the web interface through 1 node and that one connects to the other nodes with the switcher. Maybe my view of how the node version should work isn't correct.
Was trying to configure it in combination with the plug mode. But then when I switched I got a lot of /ws endpoint not found errors on the webserver side.
In the logs I keep getting a :badarith
error randomly between 2 to 30 seconds, the stacktrace is (reformatted for readability):
** (ErlangError) erlang error:
[
reason: :badarith,
mfa: {Wobserver.Web.Client, :websocket_handle, 3},
stacktrace: [
{Wobserver.System.Scheduler, :"-utilization/0-fun-0-", 1, [file: 'lib/wobserver/system/scheduler.ex', line: 37]},
{Enum, :"-map/2-lists^map/1-0-", 2, [file: 'lib/enum.ex', line: 1229]},
{Wobserver.System, :overview, 0, [file: 'lib/wobserver/system.ex', line: 54]},
{Wobserver.Web.Client, :client_handle, 2, [file: 'lib/wobserver/web/client.ex', line: 47]},
{Wobserver.Web.Client, :websocket_handle, 3, [file: 'lib/wobserver/web/client.ex', line: 5]},
{:cowboy_websocket, :handler_call, 7, [file: 'c:/Users/<user>/Projects/my_server/deps/cowboy/src/cowboy_websocket.erl', line: 588]},
{:cowboy_protocol, :execute, 4, [file: 'c:/Users/<user>/Projects/my_server/deps/cowboy/src/cowboy_protocol.erl', line: 442]}
],
msg: {:text, "{\"command\":\"system\",\"data\":null}"},
req: [
socket: #Port<0.89433>,
transport: :ranch_tcp,
connection: :keepalive,
pid: #PID<0.1515.0>,
method: "GET",
version: :"HTTP/1.1",
peer: {{10, 1, 2, 158}, 64429},
host: "<user>",
host_info: :undefined,
port: 80,
path: "/observer/ws",
path_info: :undefined,
qs: "",
qs_vals: :undefined,
bindings: [],
headers: [
{"host", "<user>"},
{"user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"},
{"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
{"accept-language", "en-US,en;q=0.5"}, {"accept-encoding", "gzip, deflate"},
{"sec-websocket-version", "13"}, {"origin", "http://<user>"},
{"sec-websocket-extensions", "permessage-deflate"},
{"sec-websocket-key", "S82iJ2lUI+jBYrl9P6icQQ=="},
{"cookie", "_my_server_key=snip"},
{"connection", "keep-alive, Upgrade"},
{"pragma", "no-cache"},
{"cache-control", "no-cache"},
{"upgrade", "websocket"}
],
p_headers: [
{"sec-websocket-extensions", [{"permessage-deflate", []}]},
{"upgrade", ["websocket"]},
{"connection", ["keep-alive", "upgrade"]}
],
cookies: :undefined,
meta: [websocket_version: 13, websocket_compress: false],
body_state: :waiting,
buffer: "",
multipart: :undefined,
resp_compress: false,
resp_state: :done,
resp_headers: [],
resp_body: "",
onresponse: :already_called
],
state: %{proxy: nil, state: %{}}
]
(cowboy) c:/Users/<user>/Projects/my_server/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
Specifically it is complaining about the division on line 37 in the lib/wobserver/system/scheduler.ex
file, the whole function is:
def utilization do
ensure_started()
case last_utilization() do
false ->
get_utilization()
|> Enum.map(fn {_, u, t} ->u / t end)
last ->
get_utilization()
|> Enum.zip(last)
|> Enum.map(fn {{_, u0, t0}, {_, u1, t1}} -> (u1 - u0) / (t1 - t0) end)
end
end
I also see the error happen on the other Enum.map line as well, specifically it seems t
can be 0 in the first Enum.map and t1-t0
can be 0 in the other Enum.map at times, checks probably need to be added to do an alternative action instead.
I had put wobserver
behind a protected pipeline that included plug :protect_from_forgery
(a wrapper around plug Plug.CSRFProtection
) and could not get wobserver
working at all (Safari would refuse to load the app.js
for wobserver
and the log would report a CSRF protection violation for cross-origin resources).
As soon as I removed :protect_from_forgery
from the pipeline, wobserver
worked just fine. It would be great to have documentation on how to enable CSRF protection, but at a minimum, users should be warned that wobserver
is not currently compatible with Plug.CSRFProtection
and :protect_from_forgery
.
We display operational data that would be handy to copy and move around. Right now, we can't select anything to copy it.
At the moment seems that https://www.chartjs.org/assets/Chart.min.js is not responding which prevents wobserver UI from loading. Not sure if their SSL is broken (http://www.chartjs.org/assets/Chart.min.js works fine) or they don't support SSL at all, but bundling all required JS instead of relying on third-party services IMO makes more sense, especially in such kind of service as wobserver.
HTTPoison is old (1.3.1 is out)
Plug is old (1.7 is out)
Cowboy is old (2.5 is out)
makes it really hard to use it as it starts to create a lot of conflich with existing newer deps
Make it possible for selected pages to show the information of all nodes in the network.
Involves the following steps:
I have launched today wobserver as a part of my phoenix app that uses https but it fails to load with the following error in the browser:
Mixed Content: The page at 'https://myapp.com/monitor/wobserver/' was loaded over HTTPS, but requested an insecure script 'http://www.kryogenix.org/code/browser/sorttable/sorttable.js'. This request has been blocked; the content must be served over HTTPS.
Trying to get some attention from the devs, what's going on, where is the new version?
#44
Could you please update the cowboy version?
Failed to use "cowboy" (version 2.8.0) because
plug_cowboy (version 2.4.1) requires ~> 2.7
wobserver (version 0.1.8) requires ~> 1.1
Manually built and packed assets and got other things ready and it 'mostly' works now it seems, however Load Charts is entirely blank, Memory Allocators are entirely blank, Application only shows the drop-down box and description, it looks like a javascript library is supposed to be making the tables sortable in various other pages, however the javascript (and apparently some fonts) are attempting to be called externally, which does not work on the internal network server I'm running. ^.^
The traditionally Phoenix way to do it is using its bundler (brunch by default, but can replace with whatever, or a manual one) to bake everything together for ease of use in such situations, though this is not Phoenix based it is still a useful style for such locations as here. :-)
When websockets don't work or respond, the js falls back to the api instead of the websockets. But the wobserver_api_fallback forces a url with an http scheme, which causes insecure request errors when the application is using https.
I have added wobserver 0.1.5 to my phoenix app.
My config is
config :wobserver,
mode: :plug,
remote_url_prefix: "/wobserver"
and I have added forward "/wobserver", Wobserver.Web.Router
to the router.
It seems that if I open
http://localhost:4060/wobserver/
(notice slash at the end) it works fine but if I omit the last slash it tries to fetch assets from http://localhost:4060/app.js
etc.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.