Thursday, August 27, 2009

Java, который я не понимаю

Еще одна, наряду с добавлением элементов из одной типизированной wildcard коллекцией в другую особенность родовых типов в Java.

А именно, параметры для родовых типов не определяются автоматически (infer) из контекста. Хотя определяются автоматически для родовых функций. Поясню на примере. Фрагмент кода 1:
<T> String cat(T a, T b) { return String.valueOf(a) + String.valueOf(b); } ... System.out.println(cat(1, 2));
В этом фрагменте при инстанциировании cat компилятор автоматически определит, что T - int.

Фрагмент кода 2:
class Cat<T> { T a, b; Cat(T a, T b) { this.a = a; this.b = b; } String cat() { return String.valueOf(a) + String.valueOf(b); } } ... System.out.println(new Cat(1, 2).cat());
В этом фрагменте при инстанциировании класса Cat компилятор выдаст предупреждение, что класс родовой класс используется без указания родового параметра. Хотя из вызова конструктора можно было эти родовые параметры определить. Так как компилятор такого не делает, приходится лишний раз руками указывать тип:
System.out.println(new Cat<Integer>(1, 2).cat());
Это, конечно, плохо с точки зрения читабельности и поддерживаемости кода.

В Internet не очень много информации, почему так сделано. Я нашел только одно старое упоминание вот здесь форуме Sun, в котором говориться о том, что автоматическое определение родовых параметров расходится с идеологией Java. Но для методов так же сделано - почему для них не расходиться.

Thursday, June 25, 2009

Мониторинг лог-файлов с использованием Zabbix

Программный комплекс Zabbix (www.zabbix.com) - популярное средство для мониторинга компьютерных систем. Zabbix позволяет отслеживать различные системные и прикладные показатели, например, загруженность CPU и сетевых интерфейсов, скорость работы сайтов, размер пула соединений и др. При возникновении внештатных ситуаций можно настроить уведомление по различным каналам вроде емейл и SMS.

Часто возникает необходимость мониторинга лог-файлов. А именно, при возникновении ошибочной ситуации было бы полезно отсылать письмо или SMS. В версии 1.4 Zabbix нет встроенных средств, которые бы позволяли такое сделать. Мне пришлось для этого написать небольшой скрипт на bash, который потом подключить как пользовательский параметр в Zabbix. Скрипт можно скачать здесь diglog.sh

Для подключения скрипта в Zabbix нужно выполнить следующее:

1. Прописать в zabbix-agentd.conf строку для определения нового пользовательского параметра: UserParameter=diglog[*],/etc/zabbix/alert.d/diglog.sh $1 $2 После чего перезапустить zabbix-agent

2. Через веб-интерфейс Zabbix добавить новый Item. Ключ (key) у него должен быть, например, таким diglog[/home/application/application.log,/tmp/application.log.diglog] Первый параметр - это путь к лог-файлу, который нужно мониторить. Второй параметр - путь к файлу состояния, в котором будет хранится текущее положение в лог-файле. Файл состояния должен быть свой для каждого лог-файла.
Тип у Item'а должен быть Character по крайней мере для Zabbix 1.4.
После добавления Zabbix сразу же начнет выбирать по одной строчки из лог-файла.

3. Добавить триггер для обработку ошибок в лог-файле, например, с таким выражением: {ZABBIX Server:diglog[/home/application/application.log,/tmp/application.logdiglog].str(ERROR)}=1
4. Подключить к триггеру действия для отсылки уведомления об ошибке.

Wednesday, February 4, 2009

Collection.addAll в Java Generics

Родовые типы (generics) в Java - одна из самых интересных и полезных возможностей. Она очень грамотно и логично спроектирована, но иногда попадаются моменты, которые ставят в тупик. Лично я пару натыкался на такой фрагмент:
List<? extends MyType> l1; List<? extends MyType> l2; l1.addAll(l2); Компилятор при этом выдает ошибку в строке, где элементы одной коллекции добавляются в другую. Казалось бы, в чем проблема - коллекции типизированы одинаково, следовательно, могут содержать одинаковые элементы. На самом деле, если бы такой код был допустимым, нарушалась бы безопасность типов (в коллекцию можно было бы добавить недопустимые элементы). Это демонстрирует следующий пример:
List<Double> dl = null; List<Integer> il = null; List<? extends Number> l1 = dl; List<? extends Number> l2 = il; l1.addAll(l2); В коллекцию Double попадают объекты типа Integer.